193 void MediaObject::noMorePadsAvailable () |
204 void MediaObject::noMorePadsAvailable () |
194 { |
205 { |
195 if (m_missingCodecs.size() > 0) { |
206 if (m_missingCodecs.size() > 0) { |
196 bool canPlay = (m_hasAudio || m_videoStreamFound); |
207 bool canPlay = (m_hasAudio || m_videoStreamFound); |
197 Phonon::ErrorType error = canPlay ? Phonon::NormalError : Phonon::FatalError; |
208 Phonon::ErrorType error = canPlay ? Phonon::NormalError : Phonon::FatalError; |
|
209 #ifdef PLUGIN_INSTALL_API |
|
210 GstInstallPluginsContext *ctx = gst_install_plugins_context_new (); |
|
211 gchar *details[2]; |
|
212 details[0] = m_missingCodecs[0].toLocal8Bit().data(); |
|
213 details[1] = NULL; |
|
214 GstInstallPluginsReturn status; |
|
215 |
|
216 status = gst_install_plugins_async( details, ctx, pluginInstallationDone, NULL ); |
|
217 gst_install_plugins_context_free ( ctx ); |
|
218 |
|
219 if ( status != GST_INSTALL_PLUGINS_STARTED_OK ) |
|
220 { |
|
221 if( status == GST_INSTALL_PLUGINS_HELPER_MISSING ) |
|
222 setError(QString(tr("Missing codec helper script assistant.")), Phonon::FatalError ); |
|
223 else |
|
224 setError(QString(tr("Plugin codec installation failed for codec: %0")) |
|
225 .arg(m_missingCodecs[0].split("|")[3]), error); |
|
226 } |
|
227 m_missingCodecs.clear(); |
|
228 #else |
|
229 QString codecs = m_missingCodecs.join(", "); |
|
230 |
198 if (error == Phonon::NormalError && m_hasVideo && !m_videoStreamFound) { |
231 if (error == Phonon::NormalError && m_hasVideo && !m_videoStreamFound) { |
199 m_hasVideo = false; |
232 m_hasVideo = false; |
200 emit hasVideoChanged(false); |
233 emit hasVideoChanged(false); |
201 } |
234 } |
202 QString codecs = m_missingCodecs.join(", "); |
|
203 setError(QString(tr("A required codec is missing. You need to install the following codec(s) to play this content: %0")).arg(codecs), error); |
235 setError(QString(tr("A required codec is missing. You need to install the following codec(s) to play this content: %0")).arg(codecs), error); |
204 m_missingCodecs.clear(); |
236 m_missingCodecs.clear(); |
|
237 #endif |
205 } |
238 } |
206 } |
239 } |
207 |
240 |
208 void MediaObject::cb_no_more_pads (GstElement * decodebin, gpointer data) |
241 void MediaObject::cb_no_more_pads (GstElement * decodebin, gpointer data) |
209 { |
242 { |
307 gst_element_set_state(m_videoGraph, currentState == GST_STATE_PLAYING ? GST_STATE_PLAYING : GST_STATE_PAUSED); |
349 gst_element_set_state(m_videoGraph, currentState == GST_STATE_PLAYING ? GST_STATE_PLAYING : GST_STATE_PAUSED); |
308 m_videoStreamFound = true; |
350 m_videoStreamFound = true; |
309 m_backend->logMessage("Video track connected", Backend::Info, this); |
351 m_backend->logMessage("Video track connected", Backend::Info, this); |
310 // Note that the notify::caps _must_ be installed after linking to work with Dapper |
352 // Note that the notify::caps _must_ be installed after linking to work with Dapper |
311 m_capsHandler = g_signal_connect(pad, "notify::caps", G_CALLBACK(notifyVideoCaps), this); |
353 m_capsHandler = g_signal_connect(pad, "notify::caps", G_CALLBACK(notifyVideoCaps), this); |
312 |
354 |
313 if (!m_loading && !m_hasVideo) { |
355 if (!m_loading && !m_hasVideo) { |
314 m_hasVideo = m_videoStreamFound; |
356 m_hasVideo = m_videoStreamFound; |
315 emit hasVideoChanged(m_hasVideo); |
357 emit hasVideoChanged(m_hasVideo); |
316 } |
358 } |
317 } |
359 } |
386 if (m_source.discType() == Phonon::Cd |
431 if (m_source.discType() == Phonon::Cd |
387 && (g_object_class_find_property (G_OBJECT_GET_CLASS (m_datasource), "read-speed"))) { |
432 && (g_object_class_find_property (G_OBJECT_GET_CLASS (m_datasource), "read-speed"))) { |
388 g_object_set (G_OBJECT (m_datasource), "read-speed", 2, (const char*)NULL); |
433 g_object_set (G_OBJECT (m_datasource), "read-speed", 2, (const char*)NULL); |
389 m_backend->logMessage(QString("new device speed : 2X"), Backend::Info, this); |
434 m_backend->logMessage(QString("new device speed : 2X"), Backend::Info, this); |
390 } |
435 } |
|
436 } |
|
437 |
|
438 /* make HTTP sources send extra headers so we get icecast |
|
439 * metadata in case the stream is an icecast stream */ |
|
440 if (encoded_cstr_url.startsWith("http://") |
|
441 && g_object_class_find_property (G_OBJECT_GET_CLASS (m_datasource), "iradio-mode")) { |
|
442 g_object_set (m_datasource, "iradio-mode", TRUE, NULL); |
|
443 m_isStream = true; |
391 } |
444 } |
392 |
445 |
393 // Link data source into pipeline |
446 // Link data source into pipeline |
394 gst_bin_add(GST_BIN(m_pipeline), m_datasource); |
447 gst_bin_add(GST_BIN(m_pipeline), m_datasource); |
395 if (!gst_element_link(m_datasource, m_decodebin)) { |
448 if (!gst_element_link(m_datasource, m_decodebin)) { |
440 { |
493 { |
441 m_pipeline = gst_pipeline_new (NULL); |
494 m_pipeline = gst_pipeline_new (NULL); |
442 gst_object_ref (GST_OBJECT (m_pipeline)); |
495 gst_object_ref (GST_OBJECT (m_pipeline)); |
443 gst_object_sink (GST_OBJECT (m_pipeline)); |
496 gst_object_sink (GST_OBJECT (m_pipeline)); |
444 |
497 |
445 m_decodebin = gst_element_factory_make ("decodebin", NULL); |
498 m_decodebin = gst_element_factory_make ("decodebin2", NULL); |
446 g_signal_connect (m_decodebin, "new-decoded-pad", G_CALLBACK (&cb_newpad), this); |
499 g_signal_connect (m_decodebin, "new-decoded-pad", G_CALLBACK (&cb_newpad), this); |
447 g_signal_connect (m_decodebin, "unknown-type", G_CALLBACK (&cb_unknown_type), this); |
500 g_signal_connect (m_decodebin, "unknown-type", G_CALLBACK (&cb_unknown_type), this); |
448 g_signal_connect (m_decodebin, "no-more-pads", G_CALLBACK (&cb_no_more_pads), this); |
501 g_signal_connect (m_decodebin, "no-more-pads", G_CALLBACK (&cb_no_more_pads), this); |
449 |
502 |
450 gst_bin_add(GST_BIN(m_pipeline), m_decodebin); |
503 gst_bin_add(GST_BIN(m_pipeline), m_decodebin); |
644 m_backend->logMessage("phonon state request: Playing", Backend::Info, this); |
697 m_backend->logMessage("phonon state request: Playing", Backend::Info, this); |
645 if (m_atEndOfStream) { |
698 if (m_atEndOfStream) { |
646 m_backend->logMessage("EOS already reached", Backend::Info, this); |
699 m_backend->logMessage("EOS already reached", Backend::Info, this); |
647 } else if (currentState == GST_STATE_PLAYING) { |
700 } else if (currentState == GST_STATE_PLAYING) { |
648 changeState(Phonon::PlayingState); |
701 changeState(Phonon::PlayingState); |
649 } else if (!m_atEndOfStream && gst_element_set_state(m_pipeline, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) { |
702 } else if (gst_element_set_state(m_pipeline, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) { |
650 m_pendingState = Phonon::PlayingState; |
703 m_pendingState = Phonon::PlayingState; |
651 } else { |
704 } else { |
652 m_backend->logMessage("phonon state request failed", Backend::Info, this); |
705 m_backend->logMessage("phonon state request failed", Backend::Info, this); |
653 } |
706 } |
654 break; |
707 break; |
859 // We have to reset the state completely here, otherwise |
914 // We have to reset the state completely here, otherwise |
860 // remnants of the old pipeline can result in strangenes |
915 // remnants of the old pipeline can result in strangenes |
861 // such as failing duration queries etc |
916 // such as failing duration queries etc |
862 GstState state; |
917 GstState state; |
863 gst_element_set_state(m_pipeline, GST_STATE_NULL); |
918 gst_element_set_state(m_pipeline, GST_STATE_NULL); |
864 gst_element_get_state (m_pipeline, &state, NULL, 2000); |
919 gst_element_get_state(m_pipeline, &state, NULL, 2000); |
865 |
920 |
866 m_source = source; |
921 m_source = source; |
867 emit currentSourceChanged(m_source); |
922 emit currentSourceChanged(m_source); |
868 m_previousTickTime = -1; |
923 m_previousTickTime = -1; |
869 m_missingCodecs.clear(); |
924 m_missingCodecs.clear(); |
870 |
925 |
871 // Go into to loading state |
926 // Go into to loading state |
872 changeState(Phonon::LoadingState); |
927 changeState(Phonon::LoadingState); |
873 m_loading = true; |
928 m_loading = true; |
874 m_resetNeeded = false; |
929 // IMPORTANT: Honor the m_resetNeeded flag as it currently stands. |
|
930 // See https://qa.mandriva.com/show_bug.cgi?id=56807 |
|
931 //m_resetNeeded = false; |
875 m_resumeState = false; |
932 m_resumeState = false; |
876 m_pendingState = Phonon::StoppedState; |
933 m_pendingState = Phonon::StoppedState; |
877 |
934 |
878 // Make sure we start out unconnected |
935 // Make sure we start out unconnected |
879 if (GST_ELEMENT_PARENT(m_audioGraph)) |
936 if (GST_ELEMENT_PARENT(m_audioGraph)) |
882 gst_bin_remove(GST_BIN(m_pipeline), m_videoGraph); |
939 gst_bin_remove(GST_BIN(m_pipeline), m_videoGraph); |
883 |
940 |
884 // Clear any existing errors |
941 // Clear any existing errors |
885 m_aboutToFinishEmitted = false; |
942 m_aboutToFinishEmitted = false; |
886 m_error = NoError; |
943 m_error = NoError; |
887 m_errorString = QString(); |
944 m_errorString.clear(); |
888 |
945 |
889 m_bufferPercent = 0; |
946 m_bufferPercent = 0; |
890 m_prefinishMarkReachedNotEmitted = true; |
947 m_prefinishMarkReachedNotEmitted = true; |
891 m_aboutToFinishEmitted = false; |
948 m_aboutToFinishEmitted = false; |
892 m_hasAudio = false; |
949 m_hasAudio = false; |
893 m_videoStreamFound = false; |
950 m_videoStreamFound = false; |
894 setTotalTime(-1); |
951 setTotalTime(-1); |
895 m_atEndOfStream = false; |
952 m_atEndOfStream = false; |
896 |
953 |
897 // Clear exising meta tags |
954 m_availableTitles = 0; |
|
955 m_pendingTitle = 1; |
|
956 m_currentTitle = 1; |
|
957 |
|
958 // Clear existing meta tags |
898 m_metaData.clear(); |
959 m_metaData.clear(); |
|
960 m_isStream = false; |
899 |
961 |
900 switch (source.type()) { |
962 switch (source.type()) { |
901 case MediaSource::Url: { |
963 case MediaSource::Url: { |
902 if (createPipefromURL(source.url())) |
964 if (!createPipefromURL(source.url())) |
903 m_loading = true; |
|
904 else |
|
905 setError(tr("Could not open media source.")); |
965 setError(tr("Could not open media source.")); |
906 } |
966 } |
907 break; |
967 break; |
908 |
968 |
909 case MediaSource::LocalFile: { |
969 case MediaSource::LocalFile: { |
910 if (createPipefromURL(QUrl::fromLocalFile(source.fileName()))) |
970 if (!createPipefromURL(QUrl::fromLocalFile(source.fileName()))) |
911 m_loading = true; |
|
912 else |
|
913 setError(tr("Could not open media source.")); |
971 setError(tr("Could not open media source.")); |
914 } |
972 } |
915 break; |
973 break; |
916 |
974 |
917 case MediaSource::Invalid: |
975 case MediaSource::Invalid: |
1002 if (m_videoStreamFound != m_hasVideo) { |
1055 if (m_videoStreamFound != m_hasVideo) { |
1003 m_hasVideo = m_videoStreamFound; |
1056 m_hasVideo = m_videoStreamFound; |
1004 emit hasVideoChanged(m_hasVideo); |
1057 emit hasVideoChanged(m_hasVideo); |
1005 } |
1058 } |
1006 |
1059 |
1007 m_availableTitles = 1; |
1060 if (m_source.discType() == Phonon::Cd) { |
1008 gint64 titleCount; |
1061 gint64 titleCount; |
1009 GstFormat format = gst_format_get_by_nick("track"); |
1062 GstFormat format = gst_format_get_by_nick("track"); |
1010 if (gst_element_query_duration (m_pipeline, &format, &titleCount)) { |
1063 if (gst_element_query_duration (m_pipeline, &format, &titleCount)) { |
1011 //check if returned format is still "track", |
1064 //check if returned format is still "track", |
1012 //gstreamer sometimes returns the total time, if tracks information is not available. |
1065 //gstreamer sometimes returns the total time, if tracks information is not available. |
1013 if (qstrcmp(gst_format_get_name(format), "track") == 0) { |
1066 if (qstrcmp(gst_format_get_name(format), "track") == 0) { |
1014 int oldAvailableTitles = m_availableTitles; |
1067 int oldAvailableTitles = m_availableTitles; |
1015 m_availableTitles = (int)titleCount; |
1068 m_availableTitles = (int)titleCount; |
1016 if (m_availableTitles != oldAvailableTitles) { |
1069 if (m_availableTitles != oldAvailableTitles) { |
1017 emit availableTitlesChanged(m_availableTitles); |
1070 emit availableTitlesChanged(m_availableTitles); |
1018 m_backend->logMessage(QString("Available titles changed: %0").arg(m_availableTitles), Backend::Info, this); |
1071 m_backend->logMessage(QString("Available titles changed: %0").arg(m_availableTitles), Backend::Info, this); |
|
1072 } |
1019 } |
1073 } |
1020 } |
1074 } |
1021 } |
1075 } |
1022 |
|
1023 } |
1076 } |
1024 |
1077 |
1025 void MediaObject::setPrefinishMark(qint32 newPrefinishMark) |
1078 void MediaObject::setPrefinishMark(qint32 newPrefinishMark) |
1026 { |
1079 { |
1027 m_prefinishMark = newPrefinishMark; |
1080 m_prefinishMark = newPrefinishMark; |
1096 qint64 currentTime = getPipelinePos(); |
1149 qint64 currentTime = getPipelinePos(); |
1097 qint64 totalTime = m_totalTime; |
1150 qint64 totalTime = m_totalTime; |
1098 |
1151 |
1099 if (m_tickInterval > 0 && currentTime != m_previousTickTime) { |
1152 if (m_tickInterval > 0 && currentTime != m_previousTickTime) { |
1100 emit tick(currentTime); |
1153 emit tick(currentTime); |
1101 m_previousTickTime = currentTime; |
1154 m_previousTickTime = currentTime; |
1102 } |
1155 } |
1103 if (m_state == Phonon::PlayingState) { |
1156 if (m_state == Phonon::PlayingState) { |
1104 if (currentTime >= totalTime - m_prefinishMark) { |
1157 if (currentTime >= totalTime - m_prefinishMark) { |
1105 if (m_prefinishMarkReachedNotEmitted) { |
1158 if (m_prefinishMarkReachedNotEmitted) { |
1106 m_prefinishMarkReachedNotEmitted = false; |
1159 m_prefinishMarkReachedNotEmitted = false; |
1107 emit prefinishMarkReached(totalTime - currentTime); |
1160 emit prefinishMarkReached(totalTime - currentTime); |
1108 } |
1161 } |
1109 } |
1162 } |
1110 // Prepare load of next source |
1163 // Prepare load of next source |
1111 if (currentTime >= totalTime - ABOUT_TO_FINNISH_TIME) { |
1164 if (currentTime >= totalTime - ABOUT_TO_FINNISH_TIME) { |
1112 if (!m_aboutToFinishEmitted) { |
1165 if (m_source.type() == MediaSource::Disc && |
|
1166 m_autoplayTitles && |
|
1167 m_availableTitles > 1 && |
|
1168 m_currentTitle < m_availableTitles) { |
|
1169 m_aboutToFinishEmitted = false; |
|
1170 } else if (!m_aboutToFinishEmitted) { |
1113 m_aboutToFinishEmitted = true; // track is about to finish |
1171 m_aboutToFinishEmitted = true; // track is about to finish |
1114 emit aboutToFinish(); |
1172 emit aboutToFinish(); |
1115 } |
1173 } |
1116 } |
1174 } |
1117 } |
1175 } |
1211 m_backend->logMessage(msgString, Backend::Debug, this); |
1269 m_backend->logMessage(msgString, Backend::Debug, this); |
1212 } |
1270 } |
1213 |
1271 |
1214 switch (GST_MESSAGE_TYPE (gstMessage)) { |
1272 switch (GST_MESSAGE_TYPE (gstMessage)) { |
1215 |
1273 |
1216 case GST_MESSAGE_EOS: |
1274 case GST_MESSAGE_EOS: |
1217 m_backend->logMessage("EOS recieved", Backend::Info, this); |
1275 m_backend->logMessage("EOS received", Backend::Info, this); |
1218 handleEndOfStream(); |
1276 handleEndOfStream(); |
1219 break; |
1277 break; |
1220 |
1278 |
1221 case GST_MESSAGE_TAG: { |
1279 case GST_MESSAGE_TAG: { |
1222 GstTagList* tag_list = 0; |
1280 GstTagList* tag_list = 0; |
1223 gst_message_parse_tag(gstMessage, &tag_list); |
1281 gst_message_parse_tag(gstMessage, &tag_list); |
1224 if (tag_list) { |
1282 if (tag_list) { |
|
1283 TagMap newTags; |
|
1284 gst_tag_list_foreach (tag_list, &foreach_tag_function, &newTags); |
|
1285 gst_tag_list_free(tag_list); |
|
1286 |
|
1287 // Determine if we should no fake the album/artist tags. |
|
1288 // This is a little confusing as we want to fake it on initial |
|
1289 // connection where title, album and artist are all missing. |
|
1290 // There are however times when we get just other information, |
|
1291 // e.g. codec, and so we want to only do clever stuff if we |
|
1292 // have a commonly available tag (ORGANIZATION) or we have a |
|
1293 // change in title |
|
1294 bool fake_it = |
|
1295 (m_isStream |
|
1296 && ((!newTags.contains("TITLE") |
|
1297 && newTags.contains("ORGANIZATION")) |
|
1298 || (newTags.contains("TITLE") |
|
1299 && m_metaData.value("TITLE") != newTags.value("TITLE"))) |
|
1300 && !newTags.contains("ALBUM") |
|
1301 && !newTags.contains("ARTIST")); |
|
1302 |
1225 TagMap oldMap = m_metaData; // Keep a copy of the old one for reference |
1303 TagMap oldMap = m_metaData; // Keep a copy of the old one for reference |
1226 // Append any new meta tags to the existing tag list |
1304 |
1227 gst_tag_list_foreach (tag_list, &foreach_tag_function, &m_metaData); |
1305 // Now we've checked the new data, append any new meta tags to the existing tag list |
|
1306 // We cannot use TagMap::iterator as this is a multimap and when streaming data |
|
1307 // could in theory be lost. |
|
1308 QList<QString> keys = newTags.keys(); |
|
1309 for (QList<QString>::iterator i = keys.begin(); i != keys.end(); ++i) { |
|
1310 QString key = *i; |
|
1311 if (m_isStream) { |
|
1312 // If we're streaming, we need to remove data in m_metaData |
|
1313 // in order to stop it filling up indefinitely (as it's a multimap) |
|
1314 m_metaData.remove(key); |
|
1315 } |
|
1316 QList<QString> values = newTags.values(key); |
|
1317 for (QList<QString>::iterator j = values.begin(); j != values.end(); ++j) { |
|
1318 QString value = *j; |
|
1319 QString currVal = m_metaData.value(key); |
|
1320 if (!m_metaData.contains(key) || currVal != value) { |
|
1321 m_metaData.insert(key, value); |
|
1322 } |
|
1323 } |
|
1324 } |
|
1325 |
1228 m_backend->logMessage("Meta tags found", Backend::Info, this); |
1326 m_backend->logMessage("Meta tags found", Backend::Info, this); |
1229 if (oldMap != m_metaData && !m_loading) |
1327 if (oldMap != m_metaData) { |
1230 emit metaDataChanged(m_metaData); |
1328 // This is a bit of a hack to ensure that stream metadata is |
1231 gst_tag_list_free(tag_list); |
1329 // returned. We get as much as we can from the Shoutcast server's |
1232 } |
1330 // StreamTitle= header. If further info is decoded from the stream |
|
1331 // itself later, then it will overwrite this info. |
|
1332 if (m_isStream && fake_it) { |
|
1333 m_metaData.remove("ALBUM"); |
|
1334 m_metaData.remove("ARTIST"); |
|
1335 |
|
1336 // Detect whether we want to "fill in the blanks" |
|
1337 QString str; |
|
1338 if (m_metaData.contains("TITLE")) |
|
1339 { |
|
1340 str = m_metaData.value("TITLE"); |
|
1341 int splitpoint; |
|
1342 // Check to see if our title matches "%s - %s" |
|
1343 // Where neither %s are empty... |
|
1344 if ((splitpoint = str.indexOf(" - ")) > 0 |
|
1345 && str.size() > (splitpoint+3)) { |
|
1346 m_metaData.insert("ARTIST", str.left(splitpoint)); |
|
1347 m_metaData.replace("TITLE", str.mid(splitpoint+3)); |
|
1348 } |
|
1349 } else { |
|
1350 str = m_metaData.value("GENRE"); |
|
1351 if (!str.isEmpty()) |
|
1352 m_metaData.insert("TITLE", str); |
|
1353 else |
|
1354 m_metaData.insert("TITLE", "Streaming Data"); |
|
1355 } |
|
1356 if (!m_metaData.contains("ARTIST")) { |
|
1357 str = m_metaData.value("LOCATION"); |
|
1358 if (!str.isEmpty()) |
|
1359 m_metaData.insert("ARTIST", str); |
|
1360 else |
|
1361 m_metaData.insert("ARTIST", "Streaming Data"); |
|
1362 } |
|
1363 str = m_metaData.value("ORGANIZATION"); |
|
1364 if (!str.isEmpty()) |
|
1365 m_metaData.insert("ALBUM", str); |
|
1366 else |
|
1367 m_metaData.insert("ALBUM", "Streaming Data"); |
|
1368 } |
|
1369 // As we manipulate the title, we need to recompare |
|
1370 // oldMap and m_metaData here... |
|
1371 if (oldMap != m_metaData && !m_loading) |
|
1372 emit metaDataChanged(m_metaData); |
|
1373 } |
|
1374 } |
1233 } |
1375 } |
1234 break; |
1376 break; |
1235 |
1377 |
1236 case GST_MESSAGE_STATE_CHANGED : { |
1378 case GST_MESSAGE_STATE_CHANGED : { |
1237 |
1379 |
1288 case GST_STATE_READY : |
1433 case GST_STATE_READY : |
1289 if (!m_loading && m_pendingState == Phonon::StoppedState) |
1434 if (!m_loading && m_pendingState == Phonon::StoppedState) |
1290 changeState(Phonon::StoppedState); |
1435 changeState(Phonon::StoppedState); |
1291 m_backend->logMessage("gstreamer: pipeline state set to ready", Backend::Debug, this); |
1436 m_backend->logMessage("gstreamer: pipeline state set to ready", Backend::Debug, this); |
1292 m_tickTimer->stop(); |
1437 m_tickTimer->stop(); |
|
1438 if ((m_source.type() == MediaSource::Disc) && (m_currentTitle != m_pendingTitle)) { |
|
1439 setTrack(m_pendingTitle); |
|
1440 } |
1293 break; |
1441 break; |
1294 |
1442 |
1295 case GST_STATE_VOID_PENDING : |
1443 case GST_STATE_VOID_PENDING : |
1296 m_backend->logMessage("gstreamer: pipeline state set to pending (void)", Backend::Debug, this); |
1444 m_backend->logMessage("gstreamer: pipeline state set to pending (void)", Backend::Debug, this); |
1297 m_tickTimer->stop(); |
1445 m_tickTimer->stop(); |
1500 return m_currentTitle; |
1657 return m_currentTitle; |
1501 } |
1658 } |
1502 |
1659 |
1503 void MediaObject::_iface_setCurrentTitle(int title) |
1660 void MediaObject::_iface_setCurrentTitle(int title) |
1504 { |
1661 { |
|
1662 m_backend->logMessage(QString("setCurrentTitle %0").arg(title), Backend::Info, this); |
|
1663 if ((title == m_currentTitle) || (title == m_pendingTitle)) |
|
1664 return; |
|
1665 |
|
1666 m_pendingTitle = title; |
|
1667 |
|
1668 if (m_state == Phonon::PlayingState || m_state == Phonon::StoppedState) { |
|
1669 setTrack(m_pendingTitle); |
|
1670 } else { |
|
1671 setState(Phonon::StoppedState); |
|
1672 } |
|
1673 } |
|
1674 |
|
1675 void MediaObject::setTrack(int title) |
|
1676 { |
|
1677 if (((m_state != Phonon::PlayingState) && (m_state != Phonon::StoppedState)) || (title < 1) || (title > m_availableTitles)) |
|
1678 return; |
|
1679 |
|
1680 |
|
1681 //let's seek to the beginning of the song |
1505 GstFormat trackFormat = gst_format_get_by_nick("track"); |
1682 GstFormat trackFormat = gst_format_get_by_nick("track"); |
1506 m_backend->logMessage(QString("setCurrentTitle %0").arg(title), Backend::Info, this); |
1683 m_backend->logMessage(QString("setTrack %0").arg(title), Backend::Info, this); |
1507 if ((title == m_currentTitle) || (title < 1) || (title > m_availableTitles)) |
1684 if (gst_element_seek_simple(m_pipeline, trackFormat, GST_SEEK_FLAG_FLUSH, title - 1)) { |
1508 return; |
1685 m_currentTitle = title; |
1509 |
|
1510 m_currentTitle = title; |
|
1511 |
|
1512 //let's seek to the beginning of the song |
|
1513 if (gst_element_seek_simple(m_pipeline, trackFormat, GST_SEEK_FLAG_FLUSH, m_currentTitle - 1)) { |
|
1514 updateTotalTime(); |
1686 updateTotalTime(); |
1515 m_atEndOfStream = false; |
1687 m_atEndOfStream = false; |
1516 emit titleChanged(title); |
1688 emit titleChanged(title); |
1517 emit totalTimeChanged(totalTime()); |
1689 emit totalTimeChanged(totalTime()); |
1518 } |
1690 } |