Playing audio file with QMediaPlayer pause Media player

Hi.

I am using QMediaPlayer with QMediaPlaylist to play short audio samples. Source code is here: https://github.com/Framstag/libosmscout/blob/master/libosmscout-client-qt/src/osmscout/InstalledVoicesModel.cpp#L138

It works fine, but when some music is played by Jolla Media Player, it is paused in the moment when start playing my samples… I tried to setup different audio roles, for example mediaPlayer->setAudioRole(QAudio::NotificationRole); but without success. Moreover, mediaPlayer->supportedAudioRoles(); gives me empty list.

I tried to search related pulseaudio features, but without success.

output of pacmd list-sink-inputs:

    index: 13
        driver: <protocol-native.c>
        flags: START_CORKED 
        state: CORKED
        sink: 0 <sink.primary>
        volume: front-left: 15246 /  23% / -38,00 dB,   front-right: 15246 /  23% / -38,00 dB
                balance 0,00
        muted: no
        current latency: 110,00 ms
        requested latency: 80,00 ms
        sample spec: s16le 2ch 44100Hz
        channel map: front-left,front-right
                     Stereo
        resample method: speex-fixed-2
        module: 15
        client: 11 <jolla-mediaplayer>
        properties:
                media.name = "'Tarantula' by '$pyda/Fresh/Pendulum/Tenor Fly'"
                application.name = "jolla-mediaplayer"
                native-protocol.peer = "UNIX socket client"
                native-protocol.version = "32"
                application.process.id = "19088"
                application.process.user = "nemo"
                application.process.host = "Sailfish"
                application.process.binary = "threaded-ml"
                application.language = "cs_CZ.utf8"
                application.process.machine_id = "1e2da36a728b4bbabd8ddd58634d2cbe"
                application.process.arg0 = "/usr/bin/jolla-mediaplayer"
                policy.group = "player"
                policy.stream_flags = hex:00000000
                media.role = "x-maemo"
                module-stream-restore.id = "sink-input-by-media-role:x-maemo"
                media.title = "Tarantula"
                media.artist = "$pyda/Fresh/Pendulum/Tenor Fly"
    index: 322
        driver: <protocol-native.c>
        flags: START_CORKED 
        state: RUNNING
        sink: 0 <sink.primary>
        volume: front-left: 15246 /  23% / -38,00 dB,   front-right: 15246 /  23% / -38,00 dB
                balance 0,00
        muted: no
        current latency: 93,85 ms
        requested latency: 80,00 ms
        sample spec: float32le 2ch 44100Hz
        channel map: front-left,front-right
                     Stereo
        resample method: speex-fixed-2
        module: 15
        client: 157 <harbour-osmscout>
        properties:
                media.name = "Playback Stream"
                application.name = "harbour-osmscout"
                native-protocol.peer = "UNIX socket client"
                native-protocol.version = "32"
                application.process.id = "30408"
                application.process.user = "nemo"
                application.process.host = "Sailfish"
                application.process.binary = "booster-silica-qt5"
                application.language = "cs_CZ.utf8"
                application.process.machine_id = "1e2da36a728b4bbabd8ddd58634d2cbe"
                application.process.arg0 = "/usr/bin/harbour-osmscout"
                policy.group = "player"
                policy.stream_flags = hex:00000000
                media.role = "x-maemo"
                module-stream-restore.id = "sink-input-by-media-role:x-maemo"

I tried to reproduce it with paplay with various properties, but without success too :frowning:

paplay -v --property=media.role=x-maemo --property=policy.group=player sample.ogg

It is possible to keep player playing, possibly just decrease volume for short time?

If you’re just playing short sounds, QSoundEffect is a better choice and wont pause the media player

1 Like

QSoundEffect may be usable for it. But I wold prefer better control for sound output. I need it for playing navigation commands… Moreover, I would like to understand the architecture and how it works. Here is minimal MediaPlayer tool: https://github.com/Karry/osmscout-sailfish/blob/master/src/MediaPlayer.cpp It behaves the same when I am using two instances of this media player. When second one start playing some file, first one is paused… Why? How? Where it is controlled?

more details - when player is paused, stacktrace is:

#0  MediaPlayerTest::playerStateChanged (this=0xbefff584, state=QMediaPlayer::PausedState) at /home/mersdk/share/SailfishOS/projects/osmscout-sailfish/src/MediaPlayer.cpp:33
#1  0xb69cd122 in QtPrivate::QSlotObjectBase::call (a=0xbeffed28, r=<optimized out>, this=0x2a18dfe0) at ../../include/QtCore/../../src/corelib/kernel/qobject_impl.h:124
#2  QMetaObject::activate (sender=sender@entry=0x2a046650, signalOffset=<optimized out>, local_signal_index=local_signal_index@entry=2, argv=argv@entry=0xbeffed28) at kernel/qobject.cpp:3715
#3  0xb69cd43a in QMetaObject::activate (sender=sender@entry=0x2a046650, m=<optimized out>, local_signal_index=local_signal_index@entry=2, argv=argv@entry=0xbeffed28) at kernel/qobject.cpp:3595
#4  0xb6f7cbc8 in QMediaPlayer::stateChanged (this=this@entry=0x2a046650, _t1=<optimized out>, _t1@entry=QMediaPlayer::PausedState) at .moc/moc_qmediaplayer.cpp:707
#5  0xb6f7cfc6 in QMediaPlayerPrivate::_q_stateChanged (this=<optimized out>, ps=QMediaPlayer::PausedState) at playback/qmediaplayer.cpp:211
#6  0xb6f7f5ca in QMediaPlayer::qt_static_metacall (_o=<optimized out>, _c=<optimized out>, _id=<optimized out>, _a=<optimized out>) at playback/qmediaplayer.h:207
#7  0xb69cd258 in QMetaObject::activate (sender=0x2a186ae8, signalOffset=<optimized out>, local_signal_index=local_signal_index@entry=3, argv=argv@entry=0xbeffee30) at kernel/qobject.cpp:3730
#8  0xb69cd43a in QMetaObject::activate (sender=<optimized out>, m=<optimized out>, local_signal_index=local_signal_index@entry=3, argv=argv@entry=0xbeffee30) at kernel/qobject.cpp:3595
#9  0xb6f74c90 in QMediaPlayerControl::stateChanged (this=<optimized out>, _t1=<optimized out>) at .moc/moc_qmediaplayercontrol.cpp:342
#10 0xb3432bc2 in QGstreamerPlayerControl::qt_static_metacall (_o=<optimized out>, _c=<optimized out>, _id=12, _a=<optimized out>) at .moc/moc_qgstreamerplayercontrol.cpp:120
#11 0xb69cd258 in QMetaObject::activate (sender=0x2a187eb0, signalOffset=<optimized out>, local_signal_index=<optimized out>, argv=<optimized out>) at kernel/qobject.cpp:3730
#12 0xb2ef7d02 in ResourcePolicyInt::handleResourcesReleasedByManager (this=0xb2f0911c <(anonymous namespace)::Q_QGS_globalResourcePolicyInt::innerFunction()::holder>) at resourcepolicyint.cpp:430
#13 0xb69cd258 in QMetaObject::activate (sender=0x2a16a800, signalOffset=<optimized out>, local_signal_index=<optimized out>, argv=<optimized out>) at kernel/qobject.cpp:3730
#14 0xb69cd258 in QMetaObject::activate (sender=sender@entry=0x2a186cf8, signalOffset=<optimized out>, local_signal_index=local_signal_index@entry=8, argv=argv@entry=0x0) at kernel/qobject.cpp:3730
#15 0xb69cd43a in QMetaObject::activate (sender=sender@entry=0x2a186cf8, m=<optimized out>, local_signal_index=local_signal_index@entry=8, argv=argv@entry=0x0) at kernel/qobject.cpp:3595
#16 0xb2edfe8e in ResourcePolicy::ResourceEngine::resourcesReleasedByManager (this=this@entry=0x2a186cf8) at moc/moc_resource-engine.cpp:287
#17 0xb2edbf76 in ResourcePolicy::ResourceEngine::receivedRelease (this=this@entry=0x2a186cf8, message=message@entry=0xbefff104) at src/resource-engine.cpp:247
#18 0xb2edc120 in handleReleaseMessage (message=0xbefff104, rs=<optimized out>) at src/resource-engine.cpp:240
#19 0xb2ea60fc in client_method (dcon=<optimized out>, dbusmsg=0x2a084698, user_data=<optimized out>) at dbus-proto.c:732
#20 0xb5719a88 in _dbus_object_tree_dispatch_and_unlock () from /usr/lib/libdbus-1.so.3
#21 0xb570e23e in dbus_connection_dispatch () from /usr/lib/libdbus-1.so.3
#22 0xb2ebb86c in DBUSConnectionEventLoop::dispatch (this=this@entry=0xb2ecd178 <(anonymous namespace)::Q_QGS_classInstance::innerFunction()::holder>) at dbusconnectioneventloop.cpp:111
#23 0xb2ebbbc0 in DBUSConnectionEventLoop::readSocket (this=0xb2ecd178 <(anonymous namespace)::Q_QGS_classInstance::innerFunction()::holder>, fd=<optimized out>) at dbusconnectioneventloop.cpp:84
#24 0xb69cd258 in QMetaObject::activate (sender=sender@entry=0x2a188b40, signalOffset=<optimized out>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0xbefff300) at kernel/qobject.cpp:3730
#25 0xb69cd43a in QMetaObject::activate (sender=sender@entry=0x2a188b40, m=<optimized out>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0xbefff300) at kernel/qobject.cpp:3595
#26 0xb6a1e8b8 in QSocketNotifier::activated (this=this@entry=0x2a188b40, _t1=<optimized out>) at .moc/moc_qsocketnotifier.cpp:135
#27 0xb69d4cf8 in QSocketNotifier::event (this=0x2a188b40, e=<optimized out>) at kernel/qsocketnotifier.cpp:260
#28 0xb69b0c44 in doNotify (event=<optimized out>, receiver=<optimized out>) at ../../include/QtCore/../../src/corelib/kernel/qobject.h:137
#29 QCoreApplication::notify (this=<optimized out>, receiver=<optimized out>, event=<optimized out>) at kernel/qcoreapplication.cpp:1076
#30 0xb69b0d52 in QCoreApplication::notifyInternal2 (receiver=0x2a188b40, event=event@entry=0xbefff434) at ../../include/QtCore/../../src/corelib/kernel/qobject.h:137
#31 0xb69e9ca6 in QCoreApplication::sendEvent (event=0xbefff434, receiver=<optimized out>) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:225
#32 socketNotifierSourceDispatch (source=0x2a0181d8) at kernel/qeventdispatcher_glib.cpp:102
#33 0xb599c38c in g_main_dispatch (context=0x2a041568) at ../glib/gmain.c:3179
#34 g_main_context_dispatch (context=context@entry=0x2a041568) at ../glib/gmain.c:3844
#35 0xb599c524 in g_main_context_iterate (context=context@entry=0x2a041568, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:3917
#36 0xb599c57c in g_main_context_iteration (context=0x2a041568, may_block=may_block@entry=1) at ../glib/gmain.c:3978
#37 0xb69e99a2 in QEventDispatcherGlib::processEvents (this=0x2a06da88, flags=...) at kernel/qeventdispatcher_glib.cpp:423
#38 0xb69af9ea in QEventLoop::exec (this=this@entry=0xbefff548, flags=..., flags@entry=...) at ../../include/QtCore/../../src/corelib/global/qflags.h:131
#39 0xb69b51e0 in QCoreApplication::exec () at ../../include/QtCore/../../src/corelib/global/qflags.h:111
#40 0x2a0018c4 in main (argc=<optimized out>, argv=<optimized out>) at /home/mersdk/share/SailfishOS/projects/osmscout-sailfish/src/MediaPlayer.cpp:78

…so it is clear that Qt media players are communicating via D-Bus…

I found it!

If I understand it correctly, there are two concepts. Media role that may signalize that sound from current application is car navigation or music player… But Gstreamer backend in Qt 5.6 used on Sailfish don’t use it. Every player needs to acquire “resource” (using session D-Bus) to be able play something. When some music player start playing it “steal” resource from previous one and it pause its playback. It have to be resumed manually then. Luckily I found this commit: https://github.com/qt/qtmultimedia/commit/1c5ea95 There are multiple resource classes and they behaves differently… It may be set by NEMO_RESOURCE_CLASS_OVERRIDE environment variable. When second player is using “navigator” class, first player with “player” class is paused and resumed when “navigator” stops…

This is exactly what I need! And it is easy to setup: https://github.com/Karry/osmscout-sailfish/commit/84dd52280de9304660d0042d06dde8aa1ea98bf4 Why I was not able to find it in documentation?

cc @rinigus , it may improve behavior even for Pure Maps :wink: https://github.com/rinigus/pure-maps/issues/120

5 Likes

@karry: great find! Interesting that it is a part of Qt-proper. I do wonder whether it will work on Ubuntu Touch and other mobile Linux’es. I guess we will find out at some point.

Thanks for pinging!