38 #include <QDBusMessage>
43 using namespace media;
46 namespace MediaHubService {
56 bool isAttached =
false;
69 void onCurrentPlayerChanged();
73 static unsigned int session_counter = 0;
75 const unsigned int current_session = session_counter++;
79 pathForPlayer(current_session),
80 QUuid::createUuid().toString(),
111 request_context_resolver(QSharedPointer<
apparmor::
lomiri::DBusDaemonRequestContextResolver>::create()),
112 request_authenticator(QSharedPointer<
apparmor::
lomiri::ExistingAuthenticator>::create()),
113 m_connection(config.connection),
121 MH_ERROR() <<
"Failed to register MPRIS object";
133 if (player->
audioStreamRole() == Player::AudioStreamRole::multimedia) {
143 return "/com/lomiri/MediaHub/Service/sessions/" + QString::number(key);
152 MH_ERROR(
"Requested adaptor for non-existing player %d", info.
key);
169 bool ok = adaptor->registerAt(info.
objectPath);
176 auto trackListAdaptor =
182 ok =
m_connection.registerObject(trackList->objectName(),
184 QDBusConnection::ExportAllSlots |
185 QDBusConnection::ExportScriptableSignals |
186 QDBusConnection::ExportAllProperties);
188 MH_ERROR(
"Failed to export TrackList for %d", info.
key);
206 if (!ok)
return false;
226 QDBusMessage msg = message();
227 QDBusConnection bus = connection();
229 const auto sessionInfo = d->createSessionInfo();
232 MH_DEBUG(
"Session created by request of: %s, key: %d, uuid: %s",
233 qUtf8Printable(client.
name), client.
key, qUtf8Printable(sessionInfo.uuid));
237 d->impl->create_session(client);
238 d->uuid_player_map[sessionInfo.uuid] = client.
key;
240 d->request_context_resolver->resolve_context_for_dbus_name_async(client.
name,
241 [
this, client](
const media::apparmor::lomiri::Context& context)
243 Q_D(ServiceSkeleton);
244 MH_DEBUG(
" -- app_name='%s', attached", qUtf8Printable(context.str()));
245 d->player_owner_map[client.key] = OwnerInfo { context.str(), true, client.name };
247 }
catch(
const std::runtime_error& e)
255 d->exportPlayer(sessionInfo);
256 uuid = sessionInfo.uuid;
257 op = QDBusObjectPath(sessionInfo.objectPath);
260 void ServiceSkeleton::DetachSession(
const QString &uuid)
266 if (!d->uuidIsValid(uuid, key))
return;
267 if (!d->player_owner_map.contains(key))
return;
269 auto &info = d->player_owner_map[key];
272 if (info.isAttached && info.serviceName == message().service()) {
273 info.isAttached =
false;
274 info.serviceName.clear();
276 auto player = d->impl->playerByKey(key);
277 player->setLifetime(Player::Lifetime::resumable);
279 }
catch(
const std::runtime_error& e)
287 void ServiceSkeleton::ReattachSession(
const QString &uuid)
291 if (!d->uuidIsValid(uuid, key)) {
297 QDBusObjectPath op(d->pathForPlayer(key));
299 QDBusMessage msg = message();
300 QDBusConnection bus = connection();
301 msg.setDelayedReply(
true);
305 d->request_context_resolver->resolve_context_for_dbus_name_async(msg.service(),
306 [
this, msg, bus, key, op](
const media::apparmor::lomiri::Context& context)
308 Q_D(ServiceSkeleton);
309 auto &info = d->player_owner_map[key];
310 MH_DEBUG(
" -- reattach app_name='%s', info='%s', '%s'",
311 qUtf8Printable(context.str()),
312 qUtf8Printable(info.profile),
313 qUtf8Printable(info.serviceName));
314 if (info.profile == context.str()) {
315 info.isAttached = true;
316 info.serviceName = msg.service();
319 PlayerImplementation *player = d->impl->playerByKey(key);
322 auto reply = msg.createReply();
323 reply << QVariant::fromValue(op);
328 auto reply = msg.createErrorReply(
329 mpris::Service::Errors::ReattachingSession::name(),
330 "Invalid permissions for the requested session");
335 }
catch(
const std::runtime_error& e)
343 void ServiceSkeleton::DestroySession(
const QString &uuid)
348 if (!d->uuidIsValid(uuid, key)) {
356 QDBusMessage msg = message();
357 QDBusConnection bus = connection();
358 msg.setDelayedReply(
true);
360 d->request_context_resolver->resolve_context_for_dbus_name_async(msg.service(),
361 [
this, msg, bus, uuid, key](
const media::apparmor::lomiri::Context& context)
363 Q_D(ServiceSkeleton);
364 auto info = d->player_owner_map.value(key);
365 MH_DEBUG(
" -- Destroying app_name='%s', info='%s', '%s'",
366 qUtf8Printable(context.str()),
367 qUtf8Printable(info.profile),
368 qUtf8Printable(info.serviceName));
369 if (info.profile == context.str()) {
372 d->uuid_player_map.remove(uuid);
373 d->player_owner_map.remove(key);
376 PlayerImplementation *player = d->impl->playerByKey(key);
379 player->setLifetime(media::Player::Lifetime::normal);
382 bus.send(msg.createReply());
385 auto reply = msg.createErrorReply(
386 mpris::Service::Errors::DestroyingSession::name(),
387 "Invalid permissions for the requested session");
392 }
catch(
const std::runtime_error& e)
399 QDBusObjectPath ServiceSkeleton::CreateFixedSession(
const QString &name)
405 if (d->named_player_map.contains(name) == 0) {
407 auto sessionInfo = d->createSessionInfo();
409 QDBusMessage msg = message();
411 QDBusObjectPath op(sessionInfo.objectPath);
413 auto session = d->impl->create_session(client);
414 session->setLifetime(media::Player::Lifetime::resumable);
416 d->exportPlayer(sessionInfo);
417 d->named_player_map.insert(name, client.
key);
421 const auto player = d->named_player_map.contains(name) ?
422 d->impl->playerByKey(d->named_player_map[name]) :
nullptr;
426 "Unable to locate player session");
430 return QDBusObjectPath(d->pathForPlayer(player->key()));
432 }
catch(
const std::runtime_error& e)
446 auto player = d->impl->playerByKey(key);
449 "Unable to locate player session");
453 return QDBusObjectPath(d->pathForPlayer(key));
461 d->impl->pause_other_sessions(key);
463 catch (
const std::out_of_range &e) {
464 MH_WARNING(
"Failed to look up Player instance for key %d\
465 , no valid Player instance for that key value and cannot set current player.\
466 This most likely means that media-hub-server has crashed and restarted.", key);
469 "Player key not found");