2 * This file is part of QMAFW
4 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights
7 * Contact: Visa Smolander <visa.smolander@nokia.com>
9 * This software, including documentation, is protected by copyright controlled
10 * by Nokia Corporation. All rights are reserved. Copying, including
11 * reproducing, storing, adapting or translating, any or all of this material
12 * requires the prior written consent of Nokia Corporation. This material also
13 * contains confidential information which may not be disclosed to others
14 * without the prior written consent of Nokia.
19 #include <QMetaMethod>
24 #include <X11/Xdefs.h>
26 #include <MafwCallbackHelper.h>
27 #include <MafwMetadata.h>
28 #include <MafwMediaInfo.h>
30 #include "MafwGstRenderer.h"
31 #include "MafwBlankingPreventer.h"
32 #include "mafw-gst-renderer-worker.h"
33 #include "MafwGstRendererVolume.h"
34 #include "MafwGstRendererDolby.h"
35 #include "MafwGstRendererNetworkMonitor.h"
36 #include "MafwGstRendererHaltState.h"
37 #include "MafwGstRendererPlaylistFileUtility.h"
38 #include "MafwGstScreenshot.h"
39 #include "MafwMmcMonitor.h"
42 #include <contextsubscriber/contextproperty.h>
43 #include <QDBusConnection>
44 #include <QDBusMessage>
46 #include <QSparqlConnection>
47 #include <QSparqlResult>
48 #include <QSparqlQuery>
49 #include <QSparqlError>
51 // milliseconds, stamp after playing this much
52 const int PLAYED_STAMP_INTERVAL = 5000;
54 const int MAX_SUPPORTED_HEIGHT = 720;
55 const int MAX_SUPPORTED_WIDTH = 1280;
56 // how many time we retried to make played stamps
57 const int PLAYED_STAMP_TRIES = 3;
59 static const int ISO_DATE_BASE_LENGTH = 19; // length of "CCYY-MM-DDThh:mm:ss"
62 const QString PROPERTY_DOLBY_STATE_MUSIC = "mobile-surround-state-music";
63 const QString PROPERTY_DOLBY_STATE_MUSIC_ROOM = "mobile-surround-state-music-room";
64 const QString PROPERTY_DOLBY_STATE_MUSIC_COLOR = "mobile-surround-state-music-color";
65 const QString PROPERTY_DOLBY_STATE_VIDEO = "mobile-surround-state-video";
66 const QString PROPERTY_DOLBY_STATE_VIDEO_ROOM = "mobile-surround-state-video-room";
67 const QString PROPERTY_DOLBY_STATE_VIDEO_COLOR = "mobile-surround-state-video-color";
68 const QString PROPERTY_VOLUME = "volume";
69 const QString PROPERTY_AUTOPAINT = "autopaint";
70 const QString PROPERTY_COLORKEY = "colorkey";
71 const QString PROPERTY_XID = "xid";
72 const QString PROPERTY_RENDER_RECT = "render-rectangle";
73 const QString PROPERTY_CURRENT_FRAME_ON_PAUSE = "current-frame-on-pause";
74 const QString PROPERTY_PLAYBACK_SPEED = "playback-speed";
75 const QString PROPERTY_FORCE_ASPECT_RATIO = "force-aspect-ratio";
77 // audio/video destinations
78 const QString CONTEXT_FW_PROPERTY_AUDIO_ROUTE = "/com/nokia/policy/audio_route";
79 const QString CONTEXT_FW_PROPERTY_VIDEO_ROUTE = "/com/nokia/policy/video_route";
80 const QString AUDIO_ROUTE_NULL = "null";
81 const QString AUDIO_ROUTE_IHF = "ihf";
82 const QString AUDIO_ROUTE_FMRADIO = "fmtx";
83 const QString AUDIO_ROUTE_IHF_AND_FMRADIO = "ihfandfmtx";
84 const QString AUDIO_ROUTE_EARPIECE = "earpiece";
85 const QString AUDIO_ROUTE_EARPIECE_AND_TVOUT = "earpieceandtvout";
86 const QString AUDIO_ROUTE_TV_OUT = "tvout";
87 const QString AUDIO_ROUTE_IHF_AND_TV_OUT = "ihfandtvout";
88 const QString AUDIO_ROUTE_HEADPHONE = "headphone";
89 const QString AUDIO_ROUTE_HEADSET = "headset";
90 const QString AUDIO_ROUTE_BTHSP = "bthsp";
91 const QString AUDIO_ROUTE_BTA2DP = "bta2dp";
92 const QString AUDIO_ROUTE_IHF_AND_HEADSET = "ihfandheadset";
93 const QString AUDIO_ROUTE_IHF_AND_HEADPHONE = "ihfandheadphone";
94 const QString AUDIO_ROUTE_IHF_AND_BTHSP = "ihfandbthsp";
95 const QString AUDIO_ROUTE_TV_OUT_AND_BTHSP = "tvoutandbthsp";
96 const QString AUDIO_ROUTE_TV_OUT_AND_BTA2DP = "tvoutandbta2dp";
97 const QString VIDEO_ROUTE_TV_OUT = "tvout";
98 const QString VIDEO_ROUTE_BUILT_IN = "builtin";
99 const QString VIDEO_ROUTE_BUILT_IN_AND_TV_OUT = "builtinandtvout";
101 const QString DBUS_INTERFACE_DBUS="org.freedesktop.DBus";
102 const QString DBUS_SIGNAL_NAME_OWNER_CHANGED="NameOwnerChanged";
103 const QString DBUS_NAME_PCFD = "com.nokia.policy.pcfd";
105 /********************************************************************
106 * MafwGstRenderer::MafwGstRenderer
107 ********************************************************************/
108 MafwGstRenderer::MafwGstRenderer(const QString& uuid,
109 const QString& pluginName,
113 MafwBasicRenderer(uuid, pluginName, name, parent),
114 m_initialized(false),
115 m_currentState(MafwRenderer::Invalid),
117 m_currentContent(""),
118 m_playingItem(MafwBasicRenderer::UnknownUri),
119 m_blankingPreventer(0),
121 m_networkMonitor(new MafwGstRendererNetworkMonitor()),
123 m_playedStamped(false),
124 m_playedStampTryCounter(0),
125 m_sparqlConnection(new QSparqlConnection("QTRACKER", QSparqlConnectionOptions(), this)),
128 m_playlistFileUtil(0),
129 m_playingPlaylistFile(false),
130 m_unsupportedTypeError(0),
131 m_playedPlaylistItem(false),
134 qDebug() << __PRETTY_FUNCTION__;
136 m_dolby = new MafwGstRendererDolby(this);
137 connect(m_dolby, SIGNAL(mafwDHMMusicPropertyChanged()),
138 this, SLOT(handleDHMMusicPropertyChanged()));
139 connect(m_dolby, SIGNAL(mafwDHMVideoPropertyChanged()),
140 this, SLOT(handleDHMVideoPropertyChanged()));
147 /* make this connection a queued connection to postpone results delivery,
148 * so that results callback is not called already in the function that
149 * initiates this procedure */
150 QObject::connect(this, SIGNAL(signalGetPosition(QObject*,
152 this, SLOT(slotGetPosition(QObject*,
154 Qt::QueuedConnection);
156 /* make this connection a queued connection to postpone results delivery,
157 * so that results callback is not called already in the function that
158 * initiates this procedure */
159 QObject::connect(this, SIGNAL(signalMafwProperty(QString,
162 this, SLOT(slotMafwProperty(QString,
165 Qt::QueuedConnection);
167 /* make this connection a queued connection to postpone results delivery,
168 * so that results callback is not called already in the function that
169 * initiates this procedure */
170 QObject::connect(this, SIGNAL(signalGetCurrentMediaInfo(QObject*,
173 this, SLOT(slotGetCurrentMediaInfo(QObject*,
176 Qt::QueuedConnection);
178 m_playedStampTimer.setSingleShot(true);
179 connect(&m_playedStampTimer,SIGNAL(timeout()),this,SLOT(slotStamp()));
181 m_videoRoute = new ContextProperty(CONTEXT_FW_PROPERTY_VIDEO_ROUTE);
182 m_audioRoute = new ContextProperty(CONTEXT_FW_PROPERTY_AUDIO_ROUTE);
184 connectNameOwnerChanged();
186 m_playlistNextTimer.setSingleShot(true);
187 connect(&m_playlistNextTimer, SIGNAL(timeout()),
188 this, SLOT(playNextURIFromPlaylist()));
190 /* connection is to track when policy is on/off */
191 connect(this, SIGNAL(mafwPropertyChanged(const QString, const QVariant)),
192 this, SLOT(handlePropertyChanged(const QString&, const QVariant&)));
194 /* Connection to handle online status message if necessary */
195 connect(m_networkMonitor, SIGNAL(prepareNetworkChange()),
196 this, SLOT(haltStreaming()));
197 connect(m_networkMonitor, SIGNAL(networkChangeFinished()),
198 this, SLOT(continueStreaming()));
200 connect(&m_haltState, SIGNAL(decayed()),
201 this, SLOT(stopStreaming()));
204 /********************************************************************
205 * MafwGstRenderer::~MafwGstRenderer
206 ********************************************************************/
207 MafwGstRenderer::~MafwGstRenderer()
210 qDebug() << __PRETTY_FUNCTION__;
212 // this releases the resources allocated by the worker, do this before
213 // releasing anything else so any callbacks from worker won't be called
214 mafw_gst_renderer_worker_exit(m_worker);
218 delete m_networkMonitor;
220 delete m_urnQueryResult;
221 delete m_stampItResult;
222 delete m_sparqlConnection;
226 if( m_unsupportedTypeError )
228 g_error_free(m_unsupportedTypeError);
233 /********************************************************************
234 * MafwGstRenderer::initialize
235 ********************************************************************/
236 bool MafwGstRenderer::initialize(QSettings *settings)
239 qDebug() << __PRETTY_FUNCTION__;
241 //if already initialized do nothing
244 return m_initialized;
247 m_initialized = MafwBasicRenderer::initialize();
251 // fail to apply default policy is not considered fatal for now
252 if (MafwBasicRenderer::setDefaultRendererPolicy(MafwRendererPolicy::MediaPlayer))
254 MafwRendererPolicy *policy = rendererPolicy();
256 policy->setDefaultResources(MafwRendererPolicy::Audio);
260 qWarning() << "Setting default policy failed, continuing";
263 m_blankingPreventer = new MafwBlankingPreventer(this);
265 m_screenshot = new MafwGstScreenshot(this);
267 connect(m_screenshot, SIGNAL(screenshotTaken(char*,GError*)),
268 this, SLOT(handleScreenshot(char*,GError*)));
269 connect(m_screenshot, SIGNAL(screenshotCancelled()),
270 this, SLOT(cancelScreenshot()));
272 m_worker = mafw_gst_renderer_worker_new(this);
273 m_worker->notify_play_handler = &playCallback;
274 m_worker->notify_pause_handler = &pauseCallback;
275 m_worker->notify_error_handler = &errorCallback;
276 m_worker->notify_eos_handler = &eosCallback;
277 m_worker->notify_ready_state_handler = &readyStateCallback;
278 m_worker->notify_metadata_handler = &metadataCallback;
279 m_worker->notify_property_handler = &propertyCallback;
280 m_worker->notify_buffer_status_handler = &bufferStatusCallback;
281 m_worker->blanking__control_handler = &blankingControlCallback;
282 m_worker->screenshot_handler = &screenshotCallback;
284 setConfiguration(settings);
286 // Initialize Dolby support
287 m_dolby->initialize();
289 m_mmcMonitor = new MafwMmcMonitor(this);
290 connect( m_mmcMonitor, SIGNAL( preUnmount() ), this, SLOT( mmcPreUnmount() ) );
292 // connect the audio routes AND check the current values of routes.
293 connect( m_videoRoute, SIGNAL( valueChanged() ), this, SLOT( slotRouteChanged() ) );
294 connect( m_audioRoute, SIGNAL( valueChanged() ), this, SLOT( slotRouteChanged() ) );
297 return m_initialized;
300 /********************************************************************
301 * MafwGstRenderer::playCallback
302 ********************************************************************/
303 void MafwGstRenderer::playCallback(MafwGstRendererWorker *worker,
308 qDebug() << __PRETTY_FUNCTION__;
309 MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
311 if( self->m_currentState == MafwRenderer::Paused )
313 Q_EMIT self->rendererResumed();
317 if( self->m_playingPlaylistFile )
319 if( !self->m_playedPlaylistItem )
321 qDebug() << "Emitting playing item event";
322 Q_EMIT self->rendererPlaying(static_cast<int>(self->m_playingItem));
323 self->m_playedPlaylistItem = true;
328 Q_EMIT self->rendererPlaying(static_cast<int>(self->m_playingItem));
332 if( mafw_gst_renderer_worker_get_position(worker)==0 )
334 self->m_playedStamped = false;
335 self->m_playedStampTryCounter = 0;
338 if( !self->m_playedStamped )
340 const QUrl url = self->m_currentContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
341 if (url.scheme() == "file")
343 qDebug() << __PRETTY_FUNCTION__ << "starting play stamp timer.";
344 self->m_playedStampTimer.start(PLAYED_STAMP_INTERVAL);
348 self->m_currentState = MafwRenderer::Playing;
351 /********************************************************************
352 * MafwGstRenderer::bufferStatusCallback
353 ********************************************************************/
354 void MafwGstRenderer::bufferStatusCallback(MafwGstRendererWorker *worker,
361 qDebug() << __PRETTY_FUNCTION__;
362 MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
364 Q_EMIT self->bufferingInfo(static_cast<float>(percent));
367 /********************************************************************
368 * MafwGstRenderer::constructMafwError
369 ********************************************************************/
370 MafwError MafwGstRenderer::constructMafwError(const GError* error)
373 guint32 code = static_cast<guint32>(error->code);
375 //for streams the media not found is other than the default
376 if( code == WORKER_ERROR_MEDIA_NOT_FOUND && mafw_gst_renderer_worker_get_streaming(m_worker) )
378 mafwError.setCode(MafwError::RendererError_URINotAvailable);
380 else if(code == WORKER_ERROR_UNSUPPORTED_TYPE)
382 handleResolutionError(mafwError);
384 else if (errorMap().contains(code))
386 mafwError.setCode(errorMap().value(code));
390 mafwError.setCode(MafwError::NothingButErrors);
393 mafwError.setMessage(error->message);
397 /********************************************************************
398 * MafwGstRenderer::errorCallback
399 ********************************************************************/
400 void MafwGstRenderer::errorCallback(MafwGstRendererWorker *worker,
405 qWarning() << __PRETTY_FUNCTION__ << error->message;
408 MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
410 code = static_cast<guint32>(error->code);
412 //The content might be a playlist file which was tried to play without
413 //mime type. This case can be detected by trying to play it as playlist
414 //file. If that was not the case same error will be signalled via
415 //MafwGstRenderer::handlePlaylistFileParsingErrors
416 if (!self->m_playingPlaylistFile &&
417 !self->m_unsupportedTypeError &&
418 code == WORKER_ERROR_POSSIBLY_PLAYLIST_TYPE)
420 QMap<QString, QVariant> mime;
421 mime[MAFW_METADATA_KEY_MIME] = "audio/x-scpls";
422 self->m_currentContent.setMetaData(mime);
423 self->doPlay(self->m_currentContent);
424 self->m_unsupportedTypeError = g_error_copy(error);
425 qWarning() << __PRETTY_FUNCTION__ << "Probably we were trying to play playlist file without mime type. If that's the case use bool play(url, 'audio/x-scpls').";
426 qWarning() << __PRETTY_FUNCTION__ << "Trying to play as playlist file now...";
429 mafwError = self->constructMafwError(error);
431 /* We release resources when we got error that causes stop.
432 * WORKER_ERROR_CANNOT_SET_POSITION and WORKER_ERROR_DRM_NOT_ALLOWED error don't cause stop.
434 if((code != WORKER_ERROR_CANNOT_SET_POSITION
435 && code != WORKER_ERROR_DRM_NOT_ALLOWED)
436 && !self->m_playingPlaylistFile)
438 Q_EMIT self->rendererError(mafwError);
439 MafwRendererPolicy *policy = self->rendererPolicy();
444 qDebug() << __PRETTY_FUNCTION__ << "Resources released because of error" << mafwError.code();
448 qWarning() << __PRETTY_FUNCTION__ << "No policy exists!";
453 else if (code != WORKER_ERROR_CANNOT_SET_POSITION && code != WORKER_ERROR_DRM_NOT_ALLOWED) //Try next uri
455 //using singleshot gives worker/gstreamer time to do
456 //cleanup before calling worker_play
457 if (self->m_playlistFileUtil->getUriList().isEmpty())
459 //delayed call to playNextURIFromPlaylist used to give the parser
460 //enough time to read new items from the playlist
461 self->m_playlistFileUtil->setPendingError(mafwError);
463 self->m_playlistNextTimer.start(1000);
467 self->m_playlistNextTimer.start(0);
472 Q_EMIT self->rendererError(mafwError);
476 /********************************************************************
477 * MafwGstRenderer::propertyCallback
478 ********************************************************************/
479 void MafwGstRenderer::propertyCallback(MafwGstRendererWorker *worker,
489 MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
493 case WORKER_PROPERTY_AUTOPAINT:
494 name = PROPERTY_AUTOPAINT;
496 case WORKER_PROPERTY_COLORKEY:
497 name = PROPERTY_COLORKEY;
499 case WORKER_PROPERTY_XID:
502 case WORKER_PROPERTY_CURRENT_FRAME_ON_PAUSE:
503 name = PROPERTY_CURRENT_FRAME_ON_PAUSE;
505 case WORKER_PROPERTY_PLAYBACK_SPEED:
506 name = PROPERTY_PLAYBACK_SPEED;
508 case WORKER_PROPERTY_FORCE_ASPECT_RATIO:
509 name = PROPERTY_FORCE_ASPECT_RATIO;
511 case WORKER_PROPERTY_RENDER_RECTANGLE:
512 name = PROPERTY_RENDER_RECT;
515 qWarning() << __PRETTY_FUNCTION__ << "unknown property id:" << id;
520 qDebug() << __PRETTY_FUNCTION__ << name;
522 QVariant result = getValue(value);
524 if (result.isValid())
526 Q_EMIT self->mafwPropertyChanged(name, result);
531 /********************************************************************
532 * MafwGstRenderer::blankingControlCallback
533 ********************************************************************/
534 void MafwGstRenderer::blankingControlCallback(MafwGstRendererWorker *worker,
535 gpointer owner, gboolean prohibit)
539 qDebug() << __PRETTY_FUNCTION__ << prohibit;
540 MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
541 if(self->m_videoRoute->value() == VIDEO_ROUTE_TV_OUT ||
542 self->m_videoRoute->value() == VIDEO_ROUTE_BUILT_IN_AND_TV_OUT)
549 self->m_blankingPreventer->blankingProhibit();
553 self->m_blankingPreventer->blankingAllow();
557 /********************************************************************
558 * MafwGstRenderer::screenshotCallback
559 ********************************************************************/
560 void MafwGstRenderer::screenshotCallback(MafwGstRendererWorker *worker,
561 gpointer owner, GstBuffer *buffer,
562 const char *filename, gboolean cancel)
564 qDebug() << __PRETTY_FUNCTION__;
565 MafwGstRenderer *self = static_cast<MafwGstRenderer*>(owner);
569 self->m_screenshot->cancelPauseFrame();
573 if(!self->m_screenshot->savePauseFrame(buffer, filename))
575 worker->taking_screenshot = FALSE;
576 qCritical() << "Failed to create pause frame pipeline";
581 /********************************************************************
582 * MafwGstRenderer::getValue
583 ********************************************************************/
584 QVariant MafwGstRenderer::getValue(const GValue *v)
591 if (G_VALUE_TYPE(v) == G_TYPE_STRING)
593 // tags from GStreamer are always expected to be UTF-8
594 result = QVariant(QString::fromUtf8(g_value_get_string(v)));
596 else if (G_VALUE_TYPE(v) == G_TYPE_UINT)
598 result = QVariant(g_value_get_uint(v));
600 else if (G_VALUE_TYPE(v) == G_TYPE_INT)
602 result = QVariant(g_value_get_int(v));
604 else if (G_VALUE_TYPE(v) == G_TYPE_BOOLEAN)
606 result = QVariant::fromValue<bool>(g_value_get_boolean(v));
608 else if (G_VALUE_TYPE(v) == G_TYPE_DOUBLE)
610 result = QVariant(g_value_get_double(v));
612 else if (G_VALUE_TYPE(v) == G_TYPE_INT64)
614 result = QVariant(g_value_get_int64(v));
616 else if (G_VALUE_TYPE(v) == G_TYPE_FLOAT)
618 result = QVariant(g_value_get_float(v));
620 else if (G_VALUE_TYPE(v) == G_TYPE_VALUE_ARRAY)
622 GValueArray *vals = static_cast<GValueArray*>(g_value_get_boxed(v));
623 if( vals->n_values == 4 )
625 result = QString("%1,%2,%3,%4")
626 .arg(g_value_get_int(g_value_array_get_nth(vals, 0)))
627 .arg(g_value_get_int(g_value_array_get_nth(vals, 1)))
628 .arg(g_value_get_int(g_value_array_get_nth(vals, 2)))
629 .arg(g_value_get_int(g_value_array_get_nth(vals, 3)));
633 qWarning() << "Invalid rect values received? Size:" << vals->n_values;
639 qWarning() << "unsupported value g_type";
647 /********************************************************************
648 * MafwGstRenderer::metadataCallback
649 ********************************************************************/
650 void MafwGstRenderer::metadataCallback(MafwGstRendererWorker *worker,
657 QList<QVariant> results;
661 qDebug() << __PRETTY_FUNCTION__ << key << metadataMap().value(key);
663 MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
665 if (metadataMap().contains(key))
667 if (type == G_TYPE_VALUE_ARRAY)
670 GValueArray *vals = static_cast<GValueArray*>(value);
671 for (i = 0; i < vals->n_values; i++)
673 QVariant v = getValue(g_value_array_get_nth(vals, i));
680 QString mafwMetadataKey = metadataMap().value(key);
682 self->appendRelatedMetadata(mafwMetadataKey, &results);
684 Q_EMIT self->metadataChanged(mafwMetadataKey, results);
685 self->m_currentMetaData.insert(mafwMetadataKey, results);
689 qWarning() << "unsupported g_type";
694 qWarning() << "unknown metadata key:" << key;
698 /********************************************************************
699 * MafwGstRenderer::appendRelatedMetadata
700 ********************************************************************/
701 void MafwGstRenderer::appendRelatedMetadata(const QString key, QList<QVariant>* results)
703 if(key == MAFW_METADATA_KEY_PAUSED_THUMBNAIL_URI)
705 gint position = mafw_gst_renderer_worker_get_position(m_worker);
711 QUrl uri = m_currentContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
712 *results << uri.toEncoded().constData();
713 *results << QVariant(position);
718 // QMafw renderer interface implementation
721 /********************************************************************
722 * MafwGstRenderer::doPlay
723 ********************************************************************/
724 void MafwGstRenderer::doPlay(const MafwContent& content)
726 Q_ASSERT_X(false, "MafwGstRenderer", "Wrong play function called!");
730 /********************************************************************
731 * MafwGstRenderer::doPlay
732 ********************************************************************/
733 void MafwGstRenderer::doPlay(const MafwMediaInfo& mediaInfo)
735 //Preserve m_currentContent for keeping usage count up if the same item is
737 if(mediaInfo.uuid().isEmpty() ||
738 mediaInfo.uuid() != m_currentContent.uuid())
740 m_currentContent = mediaInfo;
742 m_playingItem = MafwBasicRenderer::CurrentUri;
743 m_currentMetaData.clear();
745 const QUrl url = mediaInfo.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
746 qDebug() << __PRETTY_FUNCTION__ << url.toEncoded();
750 if( !m_mmcMonitor->isMounted() && url.toString().startsWith( MafwMmcMonitor::MMC_URI_PREFIX ) )
752 qDebug() << "MafwGstRenderer::doPlay: Can't play MMC not mounted";
753 MafwError mafwError(MafwError::RendererError_MmcNotAvailable, url.toEncoded());
754 Q_EMIT rendererError(mafwError);
758 m_playedPlaylistItem = false;
759 m_playingPlaylistFile = false;
760 if (m_unsupportedTypeError)
762 g_error_free(m_unsupportedTypeError);
763 m_unsupportedTypeError = 0;
770 // Set correct value for the Dolby Headphones Mobile effect plugin
771 set_dolby_music_property(m_worker, m_dolby->getMusicDolbyState());
772 set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyRoom(), TRUE);
773 set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyColor(), FALSE);
774 set_dolby_video_property(m_worker, m_dolby->getVideoDolbyState());
775 set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyRoom(), TRUE);
776 set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyColor(), FALSE);
778 const QString& mimeType = mediaInfo.firstMetaData(MAFW_METADATA_KEY_MIME).toString();
779 if (mimeType == "audio/x-scpls" )
781 if (!m_playlistFileUtil)
783 m_playlistFileUtil = new MafwGstRendererPlaylistFileUtility(this);
784 connect(m_playlistFileUtil, SIGNAL(firstItemParsed()),
785 this, SLOT(startPlayingPlaylistFile()), Qt::QueuedConnection);
786 connect(m_playlistFileUtil, SIGNAL(parsingReady(bool)),
787 this, SLOT(handlePlaylistFileParsingErrors(bool)), Qt::QueuedConnection);
789 m_playlistFileUtil->parsePlaylistFile(url);
794 playURI(url.toEncoded());
796 QVariant startPosition = mediaInfo.firstMetaData(MAFW_METADATA_KEY_START_POSITION);
797 if( startPosition.isValid() )
799 uint pos = startPosition.toUInt();
800 qDebug() << "Immediate seek requested to: " << pos;
801 doSeek(pos, MafwRenderer::SeekAbsolute);
805 QVariant pausePosition = mediaInfo.firstMetaData(MAFW_METADATA_KEY_PAUSED_POSITION);
806 if( pausePosition.isValid() )
808 uint position = pausePosition.toUInt();
809 qDebug() << "Immediate pause requested at:" << position;
810 mafw_gst_renderer_worker_pause_at(m_worker, position);
817 MafwError mafwError(MafwError::RendererError_InvalidURI, url.toString());
818 Q_EMIT rendererError(mafwError);
823 /********************************************************************
824 * MafwGstRenderer::doStop
825 ********************************************************************/
826 void MafwGstRenderer::doStop()
828 qDebug() << __PRETTY_FUNCTION__;
830 mafw_gst_renderer_worker_stop(m_worker);
831 m_currentState = MafwRenderer::Stopped;
832 m_playingItem = MafwBasicRenderer::UnknownUri;
837 Q_EMIT rendererStopped();
840 /********************************************************************
841 * MafwGstRenderer::doPause
842 ********************************************************************/
843 void MafwGstRenderer::doPause()
845 qDebug() << __PRETTY_FUNCTION__;
847 if( m_haltState.isSet() && m_haltState.state() == MafwRenderer::Playing )
849 m_haltState.setState(MafwRenderer::Paused);
850 m_currentState = MafwRenderer::Paused;
851 Q_EMIT rendererPaused();
855 mafw_gst_renderer_worker_pause(m_worker);
859 /********************************************************************
860 * MafwGstRenderer::doResume
861 ********************************************************************/
862 void MafwGstRenderer::doResume()
864 qDebug() << __PRETTY_FUNCTION__;
866 if( m_currentState == MafwRenderer::Paused && m_haltState.isSet() && m_haltState.state() == MafwRenderer::Paused )
868 mafw_gst_renderer_worker_play(m_worker, m_haltState.uri().toAscii().constData());
869 m_currentState = MafwRenderer::Paused;
870 if( m_haltState.position() > 0 )
872 doSeek(m_haltState.position(), MafwRenderer::SeekAbsolute);
877 mafw_gst_renderer_worker_resume(m_worker);
880 if( m_haltState.isSet() )
886 /********************************************************************
887 * MafwGstRenderer::doSeek
888 ********************************************************************/
889 void MafwGstRenderer::doSeek(int position, MafwRenderer::SeekMode seekMode)
893 qDebug() << __PRETTY_FUNCTION__;
895 GstSeekType seekType;
896 if( MafwRenderer::SeekAbsolute == seekMode )
898 seekType = GST_SEEK_TYPE_SET;
900 else if( MafwRenderer::SeekRelative == seekMode )
902 seekType = GST_SEEK_TYPE_CUR;
906 qCritical("MafwGstRenderer: Invalid seek operation requested!");
910 mafw_gst_renderer_worker_set_position(m_worker,
918 mafwError.setCode(MafwError::RendererError_CannotSetPosition);
919 mafwError.setMessage(error->message);
920 Q_EMIT rendererError(mafwError);
926 /********************************************************************
927 * MafwGstRenderer::doNextHint
928 ********************************************************************/
929 bool MafwGstRenderer::doNextHint(const MafwContent& content)
931 Q_ASSERT_X(false, "MafwGstRenderer", "Wrong play function called!");
936 /********************************************************************
937 * MafwGstRenderer::doNextHint
938 ********************************************************************/
939 bool MafwGstRenderer::doNextHint(const MafwMediaInfo& mediaInfo)
941 qDebug() << __PRETTY_FUNCTION__;
943 m_nextContent = mediaInfo;
944 // If we have already reached EOS trigger a new play attempt because the
945 // next content was signalled too late. However, if we have gone from playing
946 // state we can not continue, because we have released resources.
947 if (m_worker->eos && (m_currentState == MafwRenderer::Playing))
949 QTimer::singleShot(0, this, SLOT(playNext()));
954 /********************************************************************
955 * MafwGstRenderer::getPosition
956 ********************************************************************/
957 bool MafwGstRenderer::getPosition(QObject* resultsReceiver,
958 const char* resultsMember)
961 Q_EMIT signalGetPosition(resultsReceiver,
968 /********************************************************************
969 * MafwGstRenderer::setMafwProperty
970 ********************************************************************/
971 bool MafwGstRenderer::setMafwProperty(const QString& name,
972 const QVariant& value)
974 qDebug() << __PRETTY_FUNCTION__ << name;
977 if (name == PROPERTY_VOLUME)
981 m_volume = new MafwGstRendererVolume();
982 connect(m_volume, SIGNAL(volumeChanged(uint)), this, SLOT(handleVolumeChange(uint)));
984 success = m_volume->setVolume(value.toUInt());
986 else if (name == PROPERTY_DOLBY_STATE_MUSIC)
988 success = m_dolby->setMusicDolbyState(value.toUInt());
991 set_dolby_music_property(m_worker, m_dolby->getMusicDolbyState());
994 else if (name == PROPERTY_DOLBY_STATE_MUSIC_ROOM)
996 success = m_dolby->setMusicDolbyState(value.toInt());
999 set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyRoom(), TRUE);
1002 else if (name == PROPERTY_DOLBY_STATE_MUSIC_COLOR)
1004 success = m_dolby->setMusicDolbyState(value.toInt());
1007 set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyColor(), FALSE);
1010 else if (name == PROPERTY_DOLBY_STATE_VIDEO)
1012 success = m_dolby->setVideoDolbyState(value.toUInt());
1015 set_dolby_video_property(m_worker, m_dolby->getVideoDolbyState());
1018 else if (name == PROPERTY_DOLBY_STATE_VIDEO_ROOM)
1020 success = m_dolby->setVideoDolbyState(value.toInt());
1023 set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyRoom(), TRUE);
1026 else if (name == PROPERTY_DOLBY_STATE_VIDEO_COLOR)
1028 success = m_dolby->setVideoDolbyState(value.toInt());
1031 set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyColor(), FALSE);
1034 else if (name == PROPERTY_AUTOPAINT)
1036 mafw_gst_renderer_worker_set_autopaint(m_worker, value.toBool());
1038 else if (name == PROPERTY_XID)
1040 if (rendererPolicy())
1042 rendererPolicy()->setDefaultResources(MafwRendererPolicy::Audio | MafwRendererPolicy::Video);
1046 qCritical() << __PRETTY_FUNCTION__ << "unable to append video to default resources";
1049 mafw_gst_renderer_worker_set_xid(m_worker, value.toUInt());
1051 else if (name == PROPERTY_CURRENT_FRAME_ON_PAUSE)
1053 mafw_gst_renderer_worker_set_current_frame_on_pause(m_worker,
1056 else if (name == PROPERTY_PLAYBACK_SPEED)
1058 success = mafw_gst_renderer_worker_set_playback_speed(m_worker, value.toFloat());
1060 else if (name == PROPERTY_FORCE_ASPECT_RATIO)
1062 mafw_gst_renderer_worker_set_force_aspect_ratio(m_worker, value.toBool());
1064 else if( name == PROPERTY_RENDER_RECT )
1066 if( value.type() != QVariant::String )
1068 qWarning() << "MafwGstRenderer Invalid ("<<PROPERTY_RENDER_RECT<<") value received:" << value;
1072 QString str = value.toString();
1073 QStringList list = str.split(",");
1074 bool success = true;
1075 int array[4]; // x, y, width, height
1076 if( list.size() != 4 )
1082 for( int i = 0; i < 4 && success; ++i )
1084 QString str = list.at(i);
1085 array[i] = str.toInt(&success);
1090 qWarning() << "Invalid property (" << name << ") value received: " << value;
1094 render_rectangle rect = {array[0], array[1], array[2], array[3]};
1095 mafw_gst_renderer_worker_set_render_rectangle(m_worker, &rect);
1101 success = MafwBasicRenderer::setMafwProperty(name, value);
1107 err.setCode(MafwError::RendererError_CannotSetProperty);
1108 Q_EMIT rendererError(err);
1114 /********************************************************************
1115 * MafwGstRenderer::mafwProperty
1116 ********************************************************************/
1117 bool MafwGstRenderer::mafwProperty(QString& name,
1122 qDebug() << __PRETTY_FUNCTION__;
1124 Q_EMIT signalMafwProperty(name, receiver, member);
1130 /********************************************************************
1131 * MafwGstRenderer::mafwProperty
1132 ********************************************************************/
1133 bool MafwGstRenderer::getCurrentMediaInfo(QObject* receiver,
1135 const QString& metadataKey)
1137 qDebug() << __PRETTY_FUNCTION__;
1139 if(m_currentState == MafwRenderer::Playing || m_currentState == MafwRenderer::Paused)
1141 Q_EMIT signalGetCurrentMediaInfo(receiver, member, metadataKey);
1151 /********************************************************************
1152 * MafwGstRenderer::pauseCallback
1153 ********************************************************************/
1154 void MafwGstRenderer::pauseCallback(MafwGstRendererWorker *worker,
1160 qDebug() << __PRETTY_FUNCTION__;
1162 MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
1164 self->m_playedStampTimer.stop();
1166 Q_EMIT self->rendererPaused();
1168 //are we staying in paused after stopped state (pauseAt requested)
1169 //we'll need to inform the MafwBasicRenderer to give the next item to play after current
1170 //if so start fetching next also in this case
1171 if( self->m_currentState == MafwRenderer::Stopped )
1173 Q_EMIT self->rendererReadyForNext(self->m_playingItem);
1176 self->m_currentState = MafwRenderer::Paused;
1179 /********************************************************************
1180 * MafwGstRenderer::eosCallback
1181 * Renderer does not stop here, because there could be set next item to play.
1182 ********************************************************************/
1183 void MafwGstRenderer::eosCallback(MafwGstRendererWorker *worker,
1189 qDebug() << __PRETTY_FUNCTION__;
1191 MafwGstRenderer* self = static_cast<MafwGstRenderer*>(owner);
1193 //this is very special case to restart playing streams of undetermined duration and nonseekable
1194 if( mafw_gst_renderer_worker_get_streaming(worker)
1195 && mafw_gst_renderer_worker_get_last_known_duration(worker) < 0
1196 && !mafw_gst_renderer_worker_get_seekable(worker) )
1198 QTimer::singleShot(0, self, SLOT(restartPlay()));
1202 if( self->m_playedStampTimer.isActive() ) // eos before stamped, stamp now
1204 self->m_playedStampTimer.stop();
1208 if (self->m_playingPlaylistFile) //Try next uri if exists
1210 self->m_playlistNextTimer.start(0);
1214 QTimer::singleShot(0, self, SLOT(playNext()));
1215 Q_EMIT self->rendererEos();
1220 /********************************************************************
1221 * MafwGstRenderer::restartPlay
1222 * Slot to call asynchronously to restart playback (e.g. when internet radio disconnect due to network issues)
1223 ********************************************************************/
1224 void MafwGstRenderer::restartPlay()
1226 //only restart if we're still playing
1227 if( m_currentState == MafwRenderer::Playing )
1229 doPlay(m_currentContent);
1233 /********************************************************************
1234 * MafwGstRenderer::readyStateCallback
1235 * Worker informs via this when it is no longer using any resources when paused
1236 ********************************************************************/
1237 void MafwGstRenderer::readyStateCallback(MafwGstRendererWorker *worker, gpointer owner)
1241 MafwGstRenderer *self = static_cast<MafwGstRenderer*>(owner);
1243 if( self->m_currentState != MafwRenderer::Paused )
1245 qCritical("MafwGstRenderer: Ready state informed, but not in PAUSED state! Not releasing resources!");
1249 MafwRendererPolicy *policy = self->rendererPolicy();
1257 //Private implementation
1260 /********************************************************************
1261 * MafwGstRenderer::slotGetPosition
1262 ********************************************************************/
1263 void MafwGstRenderer::slotGetPosition(QObject* resultsReceiver,
1264 const char* resultsMember)
1270 if(m_currentState == MafwRenderer::Stopped)
1274 else if( m_haltState.isSet() )
1276 pos = m_haltState.position();
1280 /* this returns -1 on failure */
1281 pos = mafw_gst_renderer_worker_get_position(m_worker);
1287 err.setCode(MafwError::RendererError_CannotGetPosition);
1288 Q_EMIT rendererError(err);
1292 methodFound = MafwCallbackHelper::getCallbackMethod(resultsReceiver,
1297 method.invoke(resultsReceiver, Q_ARG(uint, pos)) == false)
1299 qCritical() << "Invoking the get position callback method failed!";
1304 /********************************************************************
1305 * MafwGstRenderer::slotMafwProperty
1306 ********************************************************************/
1307 void MafwGstRenderer::slotMafwProperty(const QString& name,
1316 if (name == PROPERTY_VOLUME)
1320 m_volume = new MafwGstRendererVolume();
1321 connect(m_volume, SIGNAL(volumeChanged(uint)), this, SLOT(handleVolumeChange(uint)));
1324 uint value = m_volume->getVolume();
1325 prop = QVariant(value);
1327 else if (name == PROPERTY_DOLBY_STATE_MUSIC)
1329 uint value = m_dolby->getMusicDolbyState();
1330 prop = QVariant(value);
1332 else if (name == PROPERTY_DOLBY_STATE_VIDEO)
1334 uint value = m_dolby->getVideoDolbyState();
1335 prop = QVariant(value);
1337 else if (name == PROPERTY_AUTOPAINT)
1340 value = mafw_gst_renderer_worker_get_autopaint(m_worker);
1341 prop = QVariant(value);
1343 else if (name == PROPERTY_COLORKEY)
1346 value = mafw_gst_renderer_worker_get_colorkey(m_worker);
1347 prop = QVariant(value);
1349 else if (name == PROPERTY_XID)
1352 value = mafw_gst_renderer_worker_get_xid(m_worker);
1353 prop = QVariant(static_cast<uint>(value));
1355 else if (name == PROPERTY_PLAYBACK_SPEED)
1358 value = mafw_gst_renderer_worker_get_playback_speed(m_worker);
1359 prop = QVariant(value);
1361 else if (name == PROPERTY_FORCE_ASPECT_RATIO)
1364 value = mafw_gst_renderer_worker_get_force_aspect_ratio(m_worker);
1365 prop = QVariant(value);
1367 else if( name == PROPERTY_RENDER_RECT)
1369 const render_rectangle *rect = mafw_gst_renderer_worker_get_render_rectangle(m_worker);
1370 prop = QString("%1,%2,%3,%4")
1371 .arg(rect->x).arg(rect->y).arg(rect->width).arg(rect->height);
1375 qWarning() << "unknown property: " << name;
1378 methodFound = MafwCallbackHelper::getCallbackMethod(receiver,
1382 if (!methodFound || method.invoke(receiver,
1383 Q_ARG(QString, name),
1384 Q_ARG(QVariant, prop)) == false)
1386 qCritical() << "Invoking the callback method failed!";
1391 /********************************************************************
1392 * MafwGstRenderer::slotStamp
1393 ********************************************************************/
1394 void MafwGstRenderer::slotStamp()
1396 qDebug() << __PRETTY_FUNCTION__;
1398 QString uid=m_currentContent.uuid();
1399 if( !uid.isEmpty() )
1401 // create live node from MAFW object ID. Tracker case only implemented
1402 // here. There definitely should be helper function for this.
1403 const QString TRACKER_SOURCE_UUID = "MafwTrackerSource";
1404 const QString MAFW_UUID_SEPARATOR = "::";
1406 QString source = uid.section(MAFW_UUID_SEPARATOR, 0 , 0);
1408 if ( source == TRACKER_SOURCE_UUID )
1410 QString uniqueNodeIdentifier = uid.section(MAFW_UUID_SEPARATOR, 1, 1);
1411 if (uniqueNodeIdentifier.length() > 0)
1413 int counter = m_currentContent.firstMetaData(MAFW_METADATA_KEY_PLAY_COUNT).toInt();
1415 qDebug() << "MafwGstRenderer::slotStamp counter" << counter;
1416 m_currentContent.appendMetaData(MAFW_METADATA_KEY_PLAY_COUNT, QList<QVariant>() << QVariant(counter));
1418 int storedDuration = m_currentContent.firstMetaData(MAFW_METADATA_KEY_DURATION).toInt();
1419 int currentDuration = mafw_gst_renderer_worker_get_duration(m_worker);
1420 int stampDuration = -1;
1421 if( currentDuration >= 0 && storedDuration != currentDuration )
1423 qDebug() << "Will store new duration:" << currentDuration;
1424 stampDuration = currentDuration;
1425 Q_EMIT(metadataChanged(MAFW_METADATA_KEY_DURATION, QList<QVariant>() << stampDuration));
1428 stampIt(uniqueNodeIdentifier, counter, stampDuration);
1432 else // UUID is unknown
1434 const QUrl url = m_currentContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
1436 if( url.isValid() && url.toString().startsWith("file://") )
1438 qDebug() << "MafwGstRenderer::slotStamp query from tracker" << url;
1440 QSparqlQuery query(QString("SELECT ?urn ?usageCount ?duration WHERE { "
1441 "?urn nie:url \"%1\". "
1443 "?urn nie:usageCounter ?usageCount. "
1444 "?urn nfo:duration ?duration } "
1446 .arg(url.toEncoded().constData()));
1448 delete m_urnQueryResult;
1449 m_urnQueryResult = m_sparqlConnection->exec(query);
1450 connect(m_urnQueryResult, SIGNAL(finished()),
1451 this, SLOT(slotStampQueryReady()));
1455 m_playedStamped=true;
1458 /********************************************************************
1459 * MafwGstRenderer::slotStampQueryReady
1460 ********************************************************************/
1461 void MafwGstRenderer::slotStampQueryReady()
1463 m_playedStampTryCounter++;
1464 if( !m_urnQueryResult || m_urnQueryResult->hasError() || !m_urnQueryResult->first() )
1466 qWarning() << "MafwGstRenderer::slotStampQueryReady: surprising result";
1467 if (!m_playedStampTimer.isActive()
1468 && m_currentState == MafwRenderer::Playing
1469 && m_playedStampTryCounter < PLAYED_STAMP_TRIES)
1471 qDebug() << __PRETTY_FUNCTION__ << "restarting timer.";
1472 m_playedStampTimer.start(PLAYED_STAMP_INTERVAL);
1476 qWarning() << __PRETTY_FUNCTION__ << "played stamping didn't succeeded.";
1477 m_playedStamped = false;
1482 QString urn = m_urnQueryResult->stringValue(0);
1483 int usageCount = m_urnQueryResult->stringValue(1).toInt();
1484 int storedDuration = m_urnQueryResult->stringValue(2).toInt();
1486 int currentDuration = mafw_gst_renderer_worker_get_duration(m_worker);
1488 int mediaDuration = -1;
1489 if( storedDuration != currentDuration)
1491 mediaDuration = currentDuration;
1492 Q_EMIT(metadataChanged(MAFW_METADATA_KEY_DURATION, QList<QVariant>() << mediaDuration));
1495 qDebug() << "MafwGstRenderer::slotStampQueryReady" << urn << usageCount << mediaDuration;
1497 stampIt(urn, usageCount+1, mediaDuration);
1501 delete m_urnQueryResult;
1502 m_urnQueryResult = 0;
1505 /********************************************************************
1506 * MafwGstRenderer::stopTimers
1507 ********************************************************************/
1508 void MafwGstRenderer::stopTimers()
1510 m_playlistNextTimer.stop();
1511 if (m_playlistFileUtil)
1513 m_playlistFileUtil->takePendingError();
1515 m_playedStampTimer.stop();
1518 /********************************************************************
1519 * MafwGstRenderer::stampIt
1520 ********************************************************************/
1521 void MafwGstRenderer::stampIt(const QString& urn, int usageCount, int mediaDuration)
1523 QString isoDate=QDateTime::currentDateTime().toUTC().toString(Qt::ISODate);
1524 // Add UTC mark "Z" if it is missing (Qt behaviour has changed it seems to add it nowadays)
1525 if( isoDate.length()==ISO_DATE_BASE_LENGTH )
1527 isoDate.append("Z");
1530 QSparqlQuery update;
1531 if( mediaDuration > -1 )
1533 update.setQuery(QString(
1534 " DELETE { <%1> nie:contentAccessed ?old } "
1535 " WHERE { <%1> nie:contentAccessed ?old } "
1536 " DELETE { <%1> nie:usageCounter ?oldu } "
1537 " WHERE { <%1> nie:usageCounter ?oldu } "
1538 " DELETE { <%1> nfo:duration ?oldd } "
1539 " WHERE { <%1> nfo:duration ?oldd } "
1540 " INSERT { <%1> nie:contentAccessed \"%2\" . "
1541 " <%1> nie:usageCounter \"%3\" . "
1542 " <%1> nfo:duration \"%4\" }")
1546 .arg(mediaDuration));
1550 update.setQuery(QString(
1551 "DELETE { <%1> nie:contentAccessed ?old } "
1552 " WHERE { <%1> nie:contentAccessed ?old } "
1553 "DELETE { <%1> nie:usageCounter ?oldu } "
1554 " WHERE { <%1> nie:usageCounter ?oldu } "
1555 "INSERT { <%1> nie:contentAccessed \"%2\" . "
1556 " <%1> nie:usageCounter \"%3\"}")
1562 update.setType(QSparqlQuery::InsertStatement);
1565 delete m_stampItResult;
1566 m_stampItResult = m_sparqlConnection->exec(update);
1567 connect(m_stampItResult, SIGNAL(finished()),
1568 this, SLOT(slotStampItDone()));
1571 /********************************************************************
1572 * MafwGstRenderer::slotStampItDone()
1573 ********************************************************************/
1574 void MafwGstRenderer::slotStampItDone()
1576 if( !m_stampItResult )
1578 qWarning() << "Stampit cannot be done without stmapit result! Invalid slot call?";
1582 if( m_stampItResult->hasError() )
1584 qWarning() << "Stampit failed:" << m_stampItResult->lastError().message();
1586 delete m_stampItResult;
1587 m_stampItResult = 0;
1590 /********************************************************************
1591 * MafwGstRenderer::slotRouteChanged()
1592 ********************************************************************/
1593 void MafwGstRenderer::slotRouteChanged()
1598 // 1. add audio route(s) to the route set
1599 route = m_audioRoute->value().toString();
1600 qDebug() << "audio route is:" << route;
1601 if (audioRouteMap().contains(route))
1603 Q_FOREACH (int value, audioRouteMap().value(route))
1610 // TODO: Is it ok to use NULL here?
1611 qWarning() << "adding null route (audio)";
1612 set.insert(WORKER_OUTPUT_NULL);
1615 // 2. add video route(s) to the route set
1616 route = m_videoRoute->value().toString();
1617 qDebug() << "video route is:" << route;
1618 if (videoRouteMap().contains(route))
1620 Q_FOREACH (int value, videoRouteMap().value(route))
1627 // TODO: Is it ok to use NULL here?
1628 qWarning() << "adding null route (video)";
1629 set.insert(WORKER_OUTPUT_NULL);
1632 // 3. finally notify the worker about the current routes
1633 GSList *destinations = NULL;
1634 Q_FOREACH (int value, set)
1636 destinations = g_slist_append(destinations, GINT_TO_POINTER(value));
1638 mafw_gst_renderer_worker_notify_media_destination(this->m_worker,
1640 g_slist_free(destinations);
1644 /********************************************************************
1645 * MafwGstRenderer::playURI
1646 ********************************************************************/
1647 void MafwGstRenderer::playURI(const QString& uri)
1649 m_playedStamped = false;
1650 m_playedStampTryCounter = 0;
1652 //little hack to get pause-to-play transition to be signalled
1653 //correctly, in case different URI is asked to be played.
1654 //So it's not resume transition
1655 m_currentState = MafwRenderer::Stopped;
1656 mafw_gst_renderer_worker_play(m_worker, uri.toAscii().constData());
1657 m_nextContent = MafwMediaInfo();
1660 /********************************************************************
1661 * MafwGstRenderer::startPlayingPlaylistFile
1662 ********************************************************************/
1663 void MafwGstRenderer::startPlayingPlaylistFile()
1665 m_playlistNextTimer.stop();
1666 QString uri = QString();
1667 if (m_playlistFileUtil)
1669 uri = m_playlistFileUtil->takeFirstUri();
1670 m_playlistFileUtil->takePendingError();
1674 qCritical() << __PRETTY_FUNCTION__ << "playlist file util is NULL!";
1679 qDebug() << __PRETTY_FUNCTION__ << uri;
1681 if( !m_mmcMonitor->isMounted() && uri.startsWith( MafwMmcMonitor::MMC_URI_PREFIX ) )
1683 qDebug() << "MafwGstRenderer::startPlayingPlaylistFile: Can't play MMC not mounted";
1684 MafwError mafwError(MafwError::RendererError_MmcNotAvailable, uri);
1685 Q_EMIT rendererError(mafwError);
1689 m_playingPlaylistFile = true;
1690 mafw_gst_renderer_worker_play(m_worker, uri.toAscii().constData());
1691 QList<QVariant> metadataValue;
1692 metadataValue << uri;
1693 Q_EMIT metadataChanged(MAFW_METADATA_KEY_URI, metadataValue);
1698 err.setCode(MafwError::RendererError_PlaylistParsing);
1699 Q_EMIT rendererError(err);
1704 /********************************************************************
1705 * MafwGstRenderer::handlePlaylistFileParsingErrors
1706 ********************************************************************/
1707 void MafwGstRenderer::handlePlaylistFileParsingErrors(bool succeeded)
1709 qDebug() << __PRETTY_FUNCTION__;
1713 if (m_unsupportedTypeError)
1715 errorCallback(m_worker, this, m_unsupportedTypeError);
1716 g_error_free(m_unsupportedTypeError);
1717 m_unsupportedTypeError = 0;
1722 err.setCode(MafwError::RendererError_PlaylistParsing);
1723 Q_EMIT rendererError(err);
1726 else if (!m_playingPlaylistFile)
1728 qDebug() << __PRETTY_FUNCTION__ << "waiting for playlist file items...";
1730 err.setCode(MafwError::RendererError_NoPlaylist);
1731 m_playlistFileUtil->setPendingError(err);
1732 m_playlistNextTimer.start(1000);
1736 /********************************************************************
1737 * MafwGstRenderer::playNext
1738 ********************************************************************/
1739 void MafwGstRenderer::playNext()
1741 qDebug() << __PRETTY_FUNCTION__;
1742 m_playingPlaylistFile = false;
1743 m_playedPlaylistItem = false;
1745 //Preserve m_currentContent for keeping usage count up if the same item is
1747 if( !m_nextContent.uuid().isEmpty() && (m_nextContent.uuid() == m_currentContent.uuid()) )
1749 m_nextContent = m_currentContent;
1752 const QUrl nextURI = m_nextContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
1753 if( !nextURI.isEmpty() )
1755 m_playingItem = MafwBasicRenderer::NextUri;
1756 m_currentContent = m_nextContent;
1757 m_nextContent = MafwMediaInfo();
1759 playURI(nextURI.toEncoded());
1763 /********************************************************************
1764 * MafwGstRenderer::playNextURIFromPlaylist
1765 ********************************************************************/
1766 void MafwGstRenderer::playNextURIFromPlaylist()
1768 qDebug() << __PRETTY_FUNCTION__;
1769 QString uri = m_playlistFileUtil->takeFirstUri();
1776 else if( !m_mmcMonitor->isMounted() && uri.startsWith( MafwMmcMonitor::MMC_URI_PREFIX ) )
1778 qDebug() << "MafwGstRenderer::playNextURIFromPlaylist: Can't play MMC not mounted";
1779 MafwError mafwError(MafwError::RendererError_MmcNotAvailable, uri);
1780 m_playlistFileUtil->setPendingError( mafwError );
1786 m_playlistFileUtil->takePendingError(); // clear it, we have a new candidate
1787 qDebug() << "Trying next uri: " << uri;
1788 mafw_gst_renderer_worker_play(m_worker, uri.toAscii().constData());
1789 QList<QVariant> metadataValue;
1790 metadataValue << uri;
1791 Q_EMIT metadataChanged(MAFW_METADATA_KEY_URI, metadataValue);
1795 m_playingPlaylistFile = false;
1797 if (m_playedPlaylistItem)
1799 Q_EMIT rendererEos();
1801 m_playedPlaylistItem = false;
1804 MafwError mafwError = m_playlistFileUtil->takePendingError();
1805 if ( mafwError.code() != MafwError::NoError)
1807 Q_EMIT rendererError(mafwError);
1809 MafwRendererPolicy *policy = rendererPolicy();
1818 /********************************************************************
1819 * MafwGstRenderer::slotCurrentMediaInfo
1820 ********************************************************************/
1821 void MafwGstRenderer::slotGetCurrentMediaInfo(QObject* receiver, const char* member, const QString& metadataKey)
1823 MafwMediaInfo info(m_currentContent.uuid());
1826 if(metadataKey.isEmpty())
1828 info.setMetaData(m_currentMetaData);
1833 QMap<QString, QList<QVariant> >::const_iterator iter = m_currentMetaData.find(metadataKey);
1834 if (iter != m_currentMetaData.end())
1836 info.appendMetaData(iter.key(), iter.value());
1840 sendMediaInfo(info, receiver, member);
1843 /********************************************************************
1844 * MafwGstRenderer::handleVolumeChange
1845 ********************************************************************/
1846 void MafwGstRenderer::handleVolumeChange(uint level)
1848 qDebug() << "MafwGstRenderer::handleVolumeChange: " << level;
1849 Q_EMIT mafwPropertyChanged(PROPERTY_VOLUME, level);
1852 /********************************************************************
1853 * MafwGstRenderer::stopStreaming
1854 ********************************************************************/
1855 void MafwGstRenderer::stopStreaming()
1857 qDebug() << __PRETTY_FUNCTION__;
1858 if( mafw_gst_renderer_worker_get_streaming(m_worker) )
1860 mafw_gst_renderer_worker_stop(m_worker);
1864 // emit error and stop for real, only if no valid halt state is set
1865 if( !m_haltState.isSet() )
1869 error.setCode(MafwError::RendererError_StreamDisconnected);
1870 Q_EMIT rendererError(error);
1874 /********************************************************************
1875 * MafwGstRenderer::haltStreaming
1876 ********************************************************************/
1877 void MafwGstRenderer::haltStreaming()
1879 qDebug() << __PRETTY_FUNCTION__;
1880 if( mafw_gst_renderer_worker_get_streaming(m_worker) )
1883 if( m_playlistNextTimer.isActive() )
1885 uri = m_playlistFileUtil->takeFirstUri();
1889 uri = mafw_gst_renderer_worker_get_uri(m_worker);
1893 if( mafw_gst_renderer_worker_get_seekable(m_worker) )
1895 position = mafw_gst_renderer_worker_get_position(m_worker);
1898 qWarning() << "Cannot resume to correct position after networkchange!";
1902 //make sure we've uri to resume, the playlist parser may have been trying to parse something
1903 if( uri.length() > 0 )
1905 m_haltState = MafwGstRendererHaltState(uri, m_currentState, position);
1906 //valid haltstate constructed, clear the possible pending error in playlist handling
1907 if( m_playlistFileUtil )
1909 m_playlistFileUtil->takePendingError();
1915 m_haltState.clear();
1918 //now actually stop, and depending on the haltstate validity it will also emit error
1923 qDebug() << "Not streaming!";
1927 /********************************************************************
1928 * MafwGstRenderer::continueStreaming
1929 ********************************************************************/
1930 void MafwGstRenderer::continueStreaming()
1932 if( mafw_gst_renderer_worker_get_streaming(m_worker) || m_haltState.isSet() )
1934 //if not yet halted, do it now
1935 if( !m_haltState.isSet() )
1940 m_playingItem = MafwBasicRenderer::CurrentUri;
1942 if( m_haltState.state() == MafwRenderer::Playing )
1944 mafw_gst_renderer_worker_play(m_worker, m_haltState.uri().toAscii().constData());
1945 int pausePos = m_haltState.position() > 0 ? m_haltState.position() : 0;
1947 if( m_haltState.state() == MafwRenderer::Playing && pausePos > 0 )
1949 qDebug() << "Resuming streaming from position: " << m_haltState.position();
1950 doSeek(m_haltState.position(), MafwRenderer::SeekAbsolute);
1952 m_haltState.clear();
1957 /********************************************************************
1958 * MafwGstRenderer::handlePropertyChanged
1959 ********************************************************************/
1960 void MafwGstRenderer::handlePropertyChanged(const QString& name,
1961 const QVariant& value)
1963 // This is a way to check if the policy is on. We need to set the
1964 // PAUSED-to-READY timeout to zero, since we need to be sure that the
1965 // resources really get released by the GStreamer. It is unfortunate that
1966 // a doPause() and PAUSED state is not enough, e.g. in case of XVideo.
1967 if (name == MAFW_RENDERER_PROPERTY_POLICY_OVERRIDE)
1970 if (value.toBool() == true)
1976 timeout = MAFW_GST_RENDERER_WORKER_READY_TIMEOUT;
1978 mafw_gst_renderer_worker_set_ready_timeout(m_worker, timeout);
1982 /********************************************************************
1983 * MafwGstRenderer::handleDHMMusicPropertyChanged
1984 ********************************************************************/
1985 void MafwGstRenderer::handleDHMMusicPropertyChanged()
1989 qDebug() << "MafwGstRenderer::handleDHMMusicPropertyChanged set_dolby_music_property" << m_dolby->getMusicDolbyState();
1990 set_dolby_music_property(m_worker, m_dolby->getMusicDolbyState());
1991 set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyRoom(), TRUE);
1992 set_dolby_music_sound_property(m_worker, m_dolby->getMusicDolbyColor(), FALSE);
1996 /********************************************************************
1997 * MafwGstRenderer::handleDHMVideoPropertyChanged
1998 ********************************************************************/
1999 void MafwGstRenderer::handleDHMVideoPropertyChanged()
2003 qDebug() << "MafwGstRenderer::handleDHMVideoPropertyChanged set_dolby_video_property" << m_dolby->getVideoDolbyState();
2004 set_dolby_video_property(m_worker, m_dolby->getVideoDolbyState());
2005 set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyRoom(), TRUE);
2006 set_dolby_video_sound_property(m_worker, m_dolby->getVideoDolbyColor(), FALSE);
2010 /********************************************************************
2011 * MafwGstRenderer::handleScreenshot
2012 ********************************************************************/
2013 void MafwGstRenderer::handleScreenshot(char *location, GError *error)
2017 QList<QVariant> results;
2018 results << location;
2020 QString mafwMetadataKey = MAFW_METADATA_KEY_PAUSED_THUMBNAIL_URI;
2022 appendRelatedMetadata(mafwMetadataKey, &results);
2023 Q_EMIT metadataChanged(mafwMetadataKey, results);
2024 m_currentMetaData.insert(mafwMetadataKey, results);
2028 qCritical() << error->message;
2031 m_worker->taking_screenshot = FALSE;
2034 /********************************************************************
2035 * MafwGstRenderer::cancelScreenshot
2036 ********************************************************************/
2037 void MafwGstRenderer::cancelScreenshot()
2041 m_worker->taking_screenshot = FALSE;
2045 /********************************************************************
2046 * MafwGstRenderer::sendMediaInfo
2047 ********************************************************************/
2048 void MafwGstRenderer::sendMediaInfo(const MafwMediaInfo& info, QObject* receiver, const char* member)
2053 methodFound = MafwCallbackHelper::getCallbackMethod(receiver, member, method);
2058 err.setCode(MafwError::CallbackSlotNotFound);
2061 //actual result callback call is inside this if()
2062 else if( !method.invoke(receiver, Q_ARG(MafwMediaInfo, info)) )
2065 err.setCode(MafwError::CallbackCouldNotInvoke);
2070 /********************************************************************
2071 * MafwGstRenderer::mmcPreUnmount
2072 ********************************************************************/
2073 void MafwGstRenderer::mmcPreUnmount()
2075 qDebug() << "MafwGstRenderer::mmcPreUnmount" << m_currentState;
2077 if( m_currentState!=MafwRenderer::Stopped )
2079 const QUrl url = m_currentContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
2080 if( url.toString().startsWith(MafwMmcMonitor::MMC_URI_PREFIX) )
2082 qDebug() << "MafwGstRenderer::mmcPreUnmount: playing from MMC, going to stop";
2084 MafwError mafwError(MafwError::RendererError_MmcNotAvailable, url.toEncoded());
2085 Q_EMIT rendererError(mafwError);
2090 /********************************************************************
2091 * MafwGstRenderer::connectNameOwnerChanged
2092 ********************************************************************/
2093 bool MafwGstRenderer::connectNameOwnerChanged()
2095 QStringList argumentMatch;
2096 argumentMatch << DBUS_NAME_PCFD;
2098 QDBusConnection connection = QDBusConnection::systemBus();
2099 return connection.connect( QString(),
2101 DBUS_INTERFACE_DBUS,
2102 DBUS_SIGNAL_NAME_OWNER_CHANGED,
2106 SLOT(handleContextProviderRemoval(QDBusMessage) ) );
2109 /********************************************************************
2110 * MafwGstRenderer::handleContextProviderRemoval
2111 ********************************************************************/
2112 void MafwGstRenderer::handleContextProviderRemoval( const QDBusMessage& message )
2114 QList<QVariant> arguments;
2119 arguments= message.arguments();
2121 if ( message.type() == QDBusMessage::SignalMessage && arguments.size()==3 )
2124 name = arguments.at(0).toString();
2125 oldName = arguments.at(1).toString();
2126 newName = arguments.at(2).toString();
2128 if ( oldName.length() && newName.length()==0 )
2130 qDebug() << "MafwGstRenderer::handleContextProviderRemoval context provider died";
2133 GSList *destinations = NULL;
2134 destinations = g_slist_append(destinations,
2135 GINT_TO_POINTER(WORKER_OUTPUT_NULL));
2136 mafw_gst_renderer_worker_notify_media_destination(this->m_worker,
2138 g_slist_free(destinations);
2143 /********************************************************************
2144 * MafwGstRenderer::handleResolutionError
2145 ********************************************************************/
2146 void MafwGstRenderer::handleResolutionError(MafwError &error)
2148 qDebug() << __PRETTY_FUNCTION__;
2149 const QUrl url = m_currentContent.firstMetaData(MAFW_METADATA_KEY_URI).toUrl();
2150 MafwError::Code errorCode = MafwError::RendererError_UnsuppertedType;
2152 if( url.isValid() && url.toString().startsWith("file://") )
2154 qDebug() << __PRETTY_FUNCTION__ << url;
2156 QSparqlQuery query(QString("SELECT ?height ?width WHERE { "
2157 "?_u nie:url \"%1\" ."
2158 "?_u nfo:height ?height . "
2159 "?_u nfo:width ?width }")
2160 .arg(QString(url.toEncoded())));
2162 QSparqlResult *result = m_sparqlConnection->syncExec(query);
2164 if( result->hasError() )
2166 qWarning() << __PRETTY_FUNCTION__ << " surprising result";
2167 qWarning() << result->lastError().message();
2169 else if( result->first() )
2171 int height = result->stringValue(0).toInt();
2172 int width = result->stringValue(1).toInt();
2174 if (height > MAX_SUPPORTED_HEIGHT || width > MAX_SUPPORTED_WIDTH)
2176 errorCode = MafwError::RendererError_UnsupportedResolution;
2181 error.setCode(errorCode);
2184 /********************************************************************
2185 * MafwGstRenderer::setConfiguration
2186 ********************************************************************/
2187 void MafwGstRenderer::setConfiguration(QSettings *settings)
2189 //if no settings use "factory" configuration
2195 configuration *defaultconfig = mafw_gst_renderer_worker_create_default_configuration(m_worker);
2198 settings->beginGroup("pipeline");
2199 QVariant value = readSettingsValue(settings, "audio-sink", defaultconfig->asink);
2200 qFree(defaultconfig->asink);
2201 defaultconfig->asink = g_strdup(value.toString().toAscii());
2203 value = readSettingsValue(settings, "video-sink", defaultconfig->vsink);
2204 qFree(defaultconfig->vsink);
2205 defaultconfig->vsink = g_strdup(value.toString().toAscii());
2207 value = readSettingsValue(settings, "flags", defaultconfig->flags);
2208 defaultconfig->flags = value.toInt();
2210 value = readSettingsValue(settings, "use_dhmmixer", defaultconfig->use_dhmmixer);
2211 defaultconfig->use_dhmmixer = value.toBool();
2213 value = readSettingsValue(settings, "buffer-time", defaultconfig->buffer_time);
2214 defaultconfig->buffer_time = value.toULongLong();
2216 value = readSettingsValue(settings, "latency-time", defaultconfig->latency_time);
2217 defaultconfig->latency_time = value.toULongLong();
2219 value = readSettingsValue(settings, "autoload_subtitles", defaultconfig->autoload_subtitles);
2220 defaultconfig->autoload_subtitles = value.toBool();
2222 value = readSettingsValue(settings, "subtitle_encoding", defaultconfig->subtitle_encoding);
2223 qFree(defaultconfig->subtitle_encoding);
2224 defaultconfig->subtitle_encoding = g_strdup(value.toString().toAscii());
2226 value = readSettingsValue(settings, "subtitle_font", defaultconfig->subtitle_font);
2227 qFree(defaultconfig->subtitle_font);
2228 defaultconfig->subtitle_font = g_strdup(value.toString().toAscii());
2229 settings->endGroup();
2232 settings->beginGroup("timers");
2233 value = readSettingsValue(settings, "pause-frame", defaultconfig->milliseconds_to_pause_frame);
2234 defaultconfig->milliseconds_to_pause_frame = value.toUInt();
2236 value = readSettingsValue(settings, "pause-to-ready", defaultconfig->seconds_to_pause_to_ready);
2237 defaultconfig->seconds_to_pause_to_ready = value.toUInt();
2238 settings->endGroup();
2241 settings->beginGroup("dhmmixer");
2242 value = readSettingsValue(settings, "dhm-music-surround", defaultconfig->mobile_surround_music.state);
2243 defaultconfig->mobile_surround_music.state = value.toUInt();
2245 value = readSettingsValue(settings, "dhm-music-color", defaultconfig->mobile_surround_music.color);
2246 defaultconfig->mobile_surround_music.color = value.toInt();
2248 value = readSettingsValue(settings, "dhm-music-room-size", defaultconfig->mobile_surround_music.room);
2249 defaultconfig->mobile_surround_music.room = value.toInt();
2251 value = readSettingsValue(settings, "dhm-video-surround", defaultconfig->mobile_surround_video.state);
2252 defaultconfig->mobile_surround_video.state = value.toUInt();
2254 value = readSettingsValue(settings, "dhm-video-color", defaultconfig->mobile_surround_video.color);
2255 defaultconfig->mobile_surround_video.color = value.toInt();
2257 value = readSettingsValue(settings, "dhm-video-room-size", defaultconfig->mobile_surround_video.room);
2258 defaultconfig->mobile_surround_video.room = value.toInt();
2259 settings->endGroup();
2261 mafw_gst_renderer_worker_set_configuration(m_worker, defaultconfig);
2264 /********************************************************************
2265 * MafwGstRenderer::readSettingsValue
2266 ********************************************************************/
2267 QVariant MafwGstRenderer::readSettingsValue(QSettings *settings,
2268 const QString &valueName,
2269 const QVariant &defaultValue) const
2271 QVariant value = settings->value(valueName, defaultValue);
2272 if( !settings->contains(valueName) )
2274 qWarning() << "No value for: (" << valueName << ") in configuration file! Using factory default";
2279 /********************************************************************
2280 * MafwGstRenderer::errorMap
2281 ********************************************************************/
2282 const QHash<int, MafwError::Code>& MafwGstRenderer::errorMap()
2285 static QHash<int, MafwError::Code> map;
2289 /* initialize error map */
2290 map[WORKER_ERROR_PLAYBACK] =
2291 MafwError::RendererError_Playback;
2292 map[WORKER_ERROR_VIDEO_CODEC_NOT_FOUND] =
2293 MafwError::RendererError_VideoCodeNotFound;
2294 map[WORKER_ERROR_AUDIO_CODEC_NOT_FOUND] =
2295 MafwError::RendererError_AudioCodecNotFound;
2296 map[WORKER_ERROR_CODEC_NOT_FOUND] =
2297 MafwError::RendererError_CodecNotFound;
2298 map[WORKER_ERROR_UNSUPPORTED_TYPE] =
2299 MafwError::RendererError_UnsuppertedType;
2300 map[WORKER_ERROR_POSSIBLY_PLAYLIST_TYPE] =
2301 MafwError::RendererError_UnsuppertedType;
2302 map[WORKER_ERROR_UNABLE_TO_PERFORM] =
2303 MafwError::RendererError_UnableToPerform;
2304 map[WORKER_ERROR_CANNOT_SET_POSITION] =
2305 MafwError::RendererError_CannotSetPosition;
2306 map[WORKER_ERROR_PLAYLIST_PARSING] =
2307 MafwError::RendererError_PlaylistParsing;
2308 map[WORKER_ERROR_DRM_NO_LICENSE] =
2309 MafwError::RendererError_DRMNoLicense;
2310 map[WORKER_ERROR_DRM_NOT_ALLOWED] =
2311 MafwError::RendererError_DRMNotAllowed;
2312 map[WORKER_ERROR_DRM_OTHER] =
2313 MafwError::RendererError_DRMOther;
2314 map[WORKER_ERROR_STREAM_DISCONNECTED] =
2315 MafwError::RendererError_StreamDisconnected;
2316 map[WORKER_ERROR_INVALID_URI] =
2317 MafwError::RendererError_InvalidURI;
2318 map[WORKER_ERROR_MEDIA_NOT_FOUND] =
2319 MafwError::RendererError_MediaNotFound;
2320 map[WORKER_ERROR_CORRUPTED_FILE] =
2321 MafwError::RendererError_CorruptedFile;
2322 map[WORKER_ERROR_TYPE_NOT_AVAILABLE] =
2323 MafwError::RendererError_TypeNotAvailable;
2330 /********************************************************************
2331 * MafwGstRenderer::metadataMap
2332 ********************************************************************/
2333 const QHash<int, QString>& MafwGstRenderer::metadataMap()
2336 static QHash<int, QString> map;
2340 /* initialize metadata key map */
2341 map[WORKER_METADATA_KEY_TITLE] =
2342 MAFW_METADATA_KEY_TITLE;
2343 map[WORKER_METADATA_KEY_ARTIST] =
2344 MAFW_METADATA_KEY_ARTIST;
2345 map[WORKER_METADATA_KEY_AUDIO_CODEC] =
2346 MAFW_METADATA_KEY_AUDIO_CODEC;
2347 map[WORKER_METADATA_KEY_VIDEO_CODEC] =
2348 MAFW_METADATA_KEY_VIDEO_CODEC;
2349 map[WORKER_METADATA_KEY_BITRATE] =
2350 MAFW_METADATA_KEY_BITRATE;
2351 map[WORKER_METADATA_KEY_ENCODING] =
2352 MAFW_METADATA_KEY_ENCODING;
2353 map[WORKER_METADATA_KEY_ALBUM] =
2354 MAFW_METADATA_KEY_ALBUM;
2355 map[WORKER_METADATA_KEY_GENRE] =
2356 MAFW_METADATA_KEY_GENRE;
2357 map[WORKER_METADATA_KEY_TRACK] =
2358 MAFW_METADATA_KEY_TRACK;
2359 map[WORKER_METADATA_KEY_ORGANIZATION] =
2360 MAFW_METADATA_KEY_ORGANIZATION;
2361 map[WORKER_METADATA_KEY_RENDERER_ART_URI] =
2362 MAFW_METADATA_KEY_RENDERER_ART_URI;
2363 map[WORKER_METADATA_KEY_RES_X] =
2364 MAFW_METADATA_KEY_RES_X;
2365 map[WORKER_METADATA_KEY_RES_Y] =
2366 MAFW_METADATA_KEY_RES_Y;
2367 map[WORKER_METADATA_KEY_VIDEO_FRAMERATE] =
2368 MAFW_METADATA_KEY_VIDEO_FRAMERATE;
2369 map[WORKER_METADATA_KEY_DURATION] =
2370 MAFW_METADATA_KEY_DURATION;
2371 map[WORKER_METADATA_KEY_IS_SEEKABLE] =
2372 MAFW_METADATA_KEY_IS_SEEKABLE;
2373 map[WORKER_METADATA_KEY_PAUSED_THUMBNAIL_URI] =
2374 MAFW_METADATA_KEY_PAUSED_THUMBNAIL_URI;
2375 map[WORKER_METADATA_KEY_URI] =
2376 MAFW_METADATA_KEY_URI;
2383 /********************************************************************
2384 * MafwGstRenderer::audioRouteMap
2385 ********************************************************************/
2386 const QHash<QString, QList<int> >& MafwGstRenderer::audioRouteMap()
2389 static QHash<QString, QList<int> > map;
2393 map[AUDIO_ROUTE_NULL] = QList<int>() << WORKER_OUTPUT_NULL;
2394 map[AUDIO_ROUTE_IHF] = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS;
2395 map[AUDIO_ROUTE_FMRADIO] = QList<int>() << WORKER_OUTPUT_FM_RADIO;
2396 map[AUDIO_ROUTE_IHF_AND_FMRADIO] = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_FM_RADIO;
2398 // earpiece is intentionally handled as builtdin speaker, well it kinda is
2399 map[AUDIO_ROUTE_EARPIECE] = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS;
2400 map[AUDIO_ROUTE_EARPIECE_AND_TVOUT] = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_TVOUT;
2402 map[AUDIO_ROUTE_TV_OUT] = QList<int>() << WORKER_OUTPUT_HEADPHONE_JACK;
2403 map[AUDIO_ROUTE_IHF_AND_TV_OUT] = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_TVOUT;
2404 map[AUDIO_ROUTE_HEADPHONE] = QList<int>() << WORKER_OUTPUT_HEADPHONE_JACK;
2405 map[AUDIO_ROUTE_HEADSET] = QList<int>() << WORKER_OUTPUT_HEADPHONE_JACK;
2406 map[AUDIO_ROUTE_BTHSP] = QList<int>() << WORKER_OUTPUT_BLUETOOTH_AUDIO;
2407 map[AUDIO_ROUTE_BTA2DP] = QList<int>() << WORKER_OUTPUT_BLUETOOTH_AUDIO;
2408 map[AUDIO_ROUTE_IHF_AND_HEADSET] = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_HEADPHONE_JACK;
2409 map[AUDIO_ROUTE_IHF_AND_HEADPHONE] = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_HEADPHONE_JACK;
2410 map[AUDIO_ROUTE_IHF_AND_BTHSP] = QList<int>() << WORKER_OUTPUT_BUILTIN_SPEAKERS << WORKER_OUTPUT_BLUETOOTH_AUDIO;
2411 map[AUDIO_ROUTE_TV_OUT_AND_BTHSP] = QList<int>() << WORKER_OUTPUT_HEADPHONE_JACK << WORKER_OUTPUT_BLUETOOTH_AUDIO;
2412 map[AUDIO_ROUTE_TV_OUT_AND_BTA2DP] = QList<int>() << WORKER_OUTPUT_HEADPHONE_JACK << WORKER_OUTPUT_BLUETOOTH_AUDIO;
2419 /********************************************************************
2420 * MafwGstRenderer::videoRouteMap
2421 ********************************************************************/
2422 const QHash<QString, QList<int> >& MafwGstRenderer::videoRouteMap()
2425 static QHash<QString, QList<int> > map;
2429 map[VIDEO_ROUTE_TV_OUT] = QList<int>() << WORKER_OUTPUT_TVOUT;
2430 map[VIDEO_ROUTE_BUILT_IN] = QList<int>() << WORKER_OUTPUT_BUILTIN_DISPLAY;
2431 map[VIDEO_ROUTE_BUILT_IN_AND_TV_OUT] = QList<int>() << WORKER_OUTPUT_BUILTIN_DISPLAY << WORKER_OUTPUT_TVOUT;