89 m_busHelper = new QGstreamerBusHelper(m_bus, this); |
88 m_busHelper = new QGstreamerBusHelper(m_bus, this); |
90 connect(m_busHelper, SIGNAL(message(QGstreamerMessage)), SLOT(busMessage(QGstreamerMessage))); |
89 connect(m_busHelper, SIGNAL(message(QGstreamerMessage)), SLOT(busMessage(QGstreamerMessage))); |
91 m_busHelper->installSyncEventFilter(this); |
90 m_busHelper->installSyncEventFilter(this); |
92 |
91 |
93 m_nullVideoOutput = gst_element_factory_make("fakesink", NULL); |
92 m_nullVideoOutput = gst_element_factory_make("fakesink", NULL); |
|
93 gst_object_ref(GST_OBJECT(m_nullVideoOutput)); |
94 g_object_set(G_OBJECT(m_playbin), "video-sink", m_nullVideoOutput, NULL); |
94 g_object_set(G_OBJECT(m_playbin), "video-sink", m_nullVideoOutput, NULL); |
95 |
95 |
96 // Initial volume |
96 // Initial volume |
97 double volume = 1.0; |
97 double volume = 1.0; |
98 g_object_get(G_OBJECT(m_playbin), "volume", &volume, NULL); |
98 g_object_get(G_OBJECT(m_playbin), "volume", &volume, NULL); |
106 stop(); |
106 stop(); |
107 |
107 |
108 delete m_busHelper; |
108 delete m_busHelper; |
109 gst_object_unref(GST_OBJECT(m_bus)); |
109 gst_object_unref(GST_OBJECT(m_bus)); |
110 gst_object_unref(GST_OBJECT(m_playbin)); |
110 gst_object_unref(GST_OBJECT(m_playbin)); |
|
111 gst_object_unref(GST_OBJECT(m_nullVideoOutput)); |
111 } |
112 } |
112 } |
113 } |
113 |
114 |
114 void QGstreamerPlayerSession::load(const QUrl &url) |
115 void QGstreamerPlayerSession::load(const QUrl &url) |
115 { |
116 { |
116 m_url = url; |
117 m_url = url; |
|
118 |
117 if (m_playbin) { |
119 if (m_playbin) { |
118 m_tags.clear(); |
120 m_tags.clear(); |
119 emit tagsChanged(); |
121 emit tagsChanged(); |
120 |
122 |
121 g_object_set(G_OBJECT(m_playbin), "uri", m_url.toString().toLocal8Bit().constData(), NULL); |
123 g_object_set(G_OBJECT(m_playbin), "uri", m_url.toEncoded().constData(), NULL); |
122 |
124 |
123 if (!m_streamTypes.isEmpty()) { |
125 if (!m_streamTypes.isEmpty()) { |
124 m_streamProperties.clear(); |
126 m_streamProperties.clear(); |
125 m_streamTypes.clear(); |
127 m_streamTypes.clear(); |
126 |
128 |
256 bool QGstreamerPlayerSession::isSeekable() const |
258 bool QGstreamerPlayerSession::isSeekable() const |
257 { |
259 { |
258 return m_seekable; |
260 return m_seekable; |
259 } |
261 } |
260 |
262 |
261 void QGstreamerPlayerSession::play() |
263 bool QGstreamerPlayerSession::play() |
262 { |
264 { |
263 if (m_playbin) { |
265 if (m_playbin) { |
264 if (gst_element_set_state(m_playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { |
266 if (gst_element_set_state(m_playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { |
265 qWarning() << "GStreamer; Unable to play -" << m_url.toString(); |
267 qWarning() << "GStreamer; Unable to play -" << m_url.toString(); |
|
268 m_state = QMediaPlayer::StoppedState; |
|
269 |
|
270 emit stateChanged(m_state); |
|
271 emit error(int(QMediaPlayer::ResourceError), tr("Unable to play %1").arg(m_url.path())); |
|
272 } else |
|
273 return true; |
|
274 } |
|
275 |
|
276 return false; |
|
277 } |
|
278 |
|
279 bool QGstreamerPlayerSession::pause() |
|
280 { |
|
281 if (m_playbin) { |
|
282 if (gst_element_set_state(m_playbin, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { |
|
283 qWarning() << "GStreamer; Unable to play -" << m_url.toString(); |
266 m_state = QMediaPlayer::StoppedState; |
284 m_state = QMediaPlayer::StoppedState; |
267 m_mediaStatus = QMediaPlayer::InvalidMedia; |
|
268 |
285 |
269 emit stateChanged(m_state); |
286 emit stateChanged(m_state); |
270 emit mediaStatusChanged(m_mediaStatus); |
287 emit error(int(QMediaPlayer::ResourceError), tr("Unable to play %1").arg(m_url.path())); |
271 } |
288 } else |
272 } |
289 return true; |
273 } |
290 } |
274 |
291 |
275 void QGstreamerPlayerSession::pause() |
292 return false; |
276 { |
|
277 if (m_playbin) |
|
278 gst_element_set_state(m_playbin, GST_STATE_PAUSED); |
|
279 } |
293 } |
280 |
294 |
281 void QGstreamerPlayerSession::stop() |
295 void QGstreamerPlayerSession::stop() |
282 { |
296 { |
283 if (m_playbin) { |
297 if (m_playbin) { |
287 if (m_state != QMediaPlayer::StoppedState) |
301 if (m_state != QMediaPlayer::StoppedState) |
288 emit stateChanged(m_state = QMediaPlayer::StoppedState); |
302 emit stateChanged(m_state = QMediaPlayer::StoppedState); |
289 } |
303 } |
290 } |
304 } |
291 |
305 |
292 void QGstreamerPlayerSession::seek(qint64 ms) |
306 bool QGstreamerPlayerSession::seek(qint64 ms) |
293 { |
307 { |
294 if (m_playbin && m_state != QMediaPlayer::StoppedState) { |
308 if (m_playbin && m_state != QMediaPlayer::StoppedState) { |
295 gint64 position = (gint64)ms * 1000000; |
309 gint64 position = (gint64)ms * 1000000; |
296 gst_element_seek_simple(m_playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, position); |
310 return gst_element_seek_simple(m_playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, position); |
297 } |
311 } |
|
312 |
|
313 return false; |
298 } |
314 } |
299 |
315 |
300 void QGstreamerPlayerSession::setVolume(int volume) |
316 void QGstreamerPlayerSession::setVolume(int volume) |
301 { |
317 { |
302 m_volume = volume; |
318 if (m_volume != volume) { |
303 emit volumeChanged(m_volume); |
319 m_volume = volume; |
304 |
320 |
305 if (!m_muted && m_playbin) |
321 if (m_playbin) { |
306 g_object_set(G_OBJECT(m_playbin), "volume", m_volume/100.0, NULL); |
322 #ifndef USE_PLAYBIN2 |
307 |
323 if(!m_muted) |
|
324 #endif |
|
325 g_object_set(G_OBJECT(m_playbin), "volume", m_volume/100.0, NULL); |
|
326 } |
|
327 |
|
328 emit volumeChanged(m_volume); |
|
329 } |
308 } |
330 } |
309 |
331 |
310 void QGstreamerPlayerSession::setMuted(bool muted) |
332 void QGstreamerPlayerSession::setMuted(bool muted) |
311 { |
333 { |
312 m_muted = muted; |
334 if (m_muted != muted) { |
313 |
335 m_muted = muted; |
314 g_object_set(G_OBJECT(m_playbin), "volume", (m_muted ? 0 : m_volume/100.0), NULL); |
336 |
315 |
337 #ifdef USE_PLAYBIN2 |
316 emit mutedStateChanged(m_muted); |
338 g_object_set(G_OBJECT(m_playbin), "mute", m_muted, NULL); |
|
339 #else |
|
340 g_object_set(G_OBJECT(m_playbin), "volume", (m_muted ? 0 : m_volume/100.0), NULL); |
|
341 #endif |
|
342 emit mutedStateChanged(m_muted); |
|
343 } |
317 } |
344 } |
318 |
345 |
319 static void addTagToMap(const GstTagList *list, |
346 static void addTagToMap(const GstTagList *list, |
320 const gchar *tag, |
347 const gchar *tag, |
321 gpointer user_data) |
348 gpointer user_data) |
420 if (newPos/1000 != m_lastPosition) { |
439 if (newPos/1000 != m_lastPosition) { |
421 m_lastPosition = newPos/1000; |
440 m_lastPosition = newPos/1000; |
422 emit positionChanged(newPos); |
441 emit positionChanged(newPos); |
423 } |
442 } |
424 |
443 |
|
444 double volume = 1.0; |
|
445 g_object_get(G_OBJECT(m_playbin), "volume", &volume, NULL); |
|
446 if (m_volume != int(volume*100)) { |
|
447 m_volume = int(volume*100); |
|
448 emit volumeChanged(m_volume); |
|
449 } |
|
450 |
425 } else { |
451 } else { |
426 //tag message comes from elements inside playbin, not from playbin itself |
452 //tag message comes from elements inside playbin, not from playbin itself |
427 if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_TAG) { |
453 if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_TAG) { |
428 //qDebug() << "tag message"; |
454 //qDebug() << "tag message"; |
429 GstTagList *tag_list; |
455 GstTagList *tag_list; |
457 .arg(states[pending]);*/ |
480 .arg(states[pending]);*/ |
458 |
481 |
459 switch (newState) { |
482 switch (newState) { |
460 case GST_STATE_VOID_PENDING: |
483 case GST_STATE_VOID_PENDING: |
461 case GST_STATE_NULL: |
484 case GST_STATE_NULL: |
462 setMediaStatus(QMediaPlayer::UnknownMediaStatus); |
|
463 setSeekable(false); |
485 setSeekable(false); |
464 if (m_state != QMediaPlayer::StoppedState) |
486 if (m_state != QMediaPlayer::StoppedState) |
465 emit stateChanged(m_state = QMediaPlayer::StoppedState); |
487 emit stateChanged(m_state = QMediaPlayer::StoppedState); |
466 break; |
488 break; |
467 case GST_STATE_READY: |
489 case GST_STATE_READY: |
468 setMediaStatus(QMediaPlayer::LoadedMedia); |
|
469 setSeekable(false); |
490 setSeekable(false); |
470 if (m_state != QMediaPlayer::StoppedState) |
491 if (m_state != QMediaPlayer::StoppedState) |
471 emit stateChanged(m_state = QMediaPlayer::StoppedState); |
492 emit stateChanged(m_state = QMediaPlayer::StoppedState); |
472 break; |
493 break; |
473 case GST_STATE_PAUSED: |
494 case GST_STATE_PAUSED: |
474 //don't emit state changes for intermediate states |
495 if (m_state != QMediaPlayer::PausedState) |
475 if (m_state != QMediaPlayer::PausedState && pending == GST_STATE_VOID_PENDING) |
|
476 emit stateChanged(m_state = QMediaPlayer::PausedState); |
496 emit stateChanged(m_state = QMediaPlayer::PausedState); |
477 |
|
478 setMediaStatus(QMediaPlayer::LoadedMedia); |
|
479 |
497 |
480 //check for seekable |
498 //check for seekable |
481 if (oldState == GST_STATE_READY) { |
499 if (oldState == GST_STATE_READY) { |
482 /* |
500 /* |
483 //gst_element_seek_simple doesn't work reliably here, have to find a better solution |
501 //gst_element_seek_simple doesn't work reliably here, have to find a better solution |
508 if (oldState == GST_STATE_PAUSED) |
526 if (oldState == GST_STATE_PAUSED) |
509 getStreamsInfo(); |
527 getStreamsInfo(); |
510 |
528 |
511 if (m_state != QMediaPlayer::PlayingState) |
529 if (m_state != QMediaPlayer::PlayingState) |
512 emit stateChanged(m_state = QMediaPlayer::PlayingState); |
530 emit stateChanged(m_state = QMediaPlayer::PlayingState); |
|
531 |
513 break; |
532 break; |
514 } |
533 } |
515 } |
534 } |
516 break; |
535 break; |
517 |
536 |
518 case GST_MESSAGE_EOS: |
537 case GST_MESSAGE_EOS: |
519 if (m_state != QMediaPlayer::StoppedState) |
|
520 emit stateChanged(m_state = QMediaPlayer::StoppedState); |
|
521 |
|
522 setMediaStatus(QMediaPlayer::EndOfMedia); |
|
523 |
|
524 emit playbackFinished(); |
538 emit playbackFinished(); |
525 break; |
539 break; |
526 |
540 |
527 case GST_MESSAGE_TAG: |
541 case GST_MESSAGE_TAG: |
528 case GST_MESSAGE_STREAM_STATUS: |
542 case GST_MESSAGE_STREAM_STATUS: |
529 case GST_MESSAGE_UNKNOWN: |
543 case GST_MESSAGE_UNKNOWN: |
|
544 break; |
530 case GST_MESSAGE_ERROR: |
545 case GST_MESSAGE_ERROR: |
|
546 { |
|
547 GError *err; |
|
548 gchar *debug; |
|
549 gst_message_parse_error (gm, &err, &debug); |
|
550 emit error(int(QMediaPlayer::ResourceError), QString::fromUtf8(err->message)); |
|
551 qWarning() << "Error:" << QString::fromUtf8(err->message); |
|
552 g_error_free (err); |
|
553 g_free (debug); |
|
554 } |
|
555 break; |
531 case GST_MESSAGE_WARNING: |
556 case GST_MESSAGE_WARNING: |
532 case GST_MESSAGE_INFO: |
557 case GST_MESSAGE_INFO: |
533 break; |
558 break; |
534 case GST_MESSAGE_BUFFERING: |
559 case GST_MESSAGE_BUFFERING: |
535 setMediaStatus(QMediaPlayer::BufferingMedia); |
560 { |
|
561 int progress = 0; |
|
562 gst_message_parse_buffering(gm, &progress); |
|
563 emit bufferingProgressChanged(progress); |
|
564 } |
536 break; |
565 break; |
537 case GST_MESSAGE_STATE_DIRTY: |
566 case GST_MESSAGE_STATE_DIRTY: |
538 case GST_MESSAGE_STEP_DONE: |
567 case GST_MESSAGE_STEP_DONE: |
539 case GST_MESSAGE_CLOCK_PROVIDE: |
568 case GST_MESSAGE_CLOCK_PROVIDE: |
540 case GST_MESSAGE_CLOCK_LOST: |
569 case GST_MESSAGE_CLOCK_LOST: |
541 case GST_MESSAGE_NEW_CLOCK: |
570 case GST_MESSAGE_NEW_CLOCK: |
542 case GST_MESSAGE_STRUCTURE_CHANGE: |
571 case GST_MESSAGE_STRUCTURE_CHANGE: |
543 case GST_MESSAGE_APPLICATION: |
572 case GST_MESSAGE_APPLICATION: |
544 case GST_MESSAGE_ELEMENT: |
573 case GST_MESSAGE_ELEMENT: |
|
574 break; |
545 case GST_MESSAGE_SEGMENT_START: |
575 case GST_MESSAGE_SEGMENT_START: |
|
576 { |
|
577 const GstStructure *structure = gst_message_get_structure(gm); |
|
578 qint64 position = g_value_get_int64(gst_structure_get_value(structure, "position")); |
|
579 position /= 1000000; |
|
580 m_lastPosition = position; |
|
581 emit positionChanged(position); |
|
582 } |
|
583 break; |
546 case GST_MESSAGE_SEGMENT_DONE: |
584 case GST_MESSAGE_SEGMENT_DONE: |
|
585 break; |
|
586 case GST_MESSAGE_DURATION: |
|
587 { |
|
588 GstFormat format = GST_FORMAT_TIME; |
|
589 gint64 duration = 0; |
|
590 |
|
591 if (gst_element_query_duration(m_playbin, &format, &duration)) { |
|
592 int newDuration = duration / 1000000; |
|
593 if (m_duration != newDuration) { |
|
594 m_duration = newDuration; |
|
595 emit durationChanged(m_duration); |
|
596 } |
|
597 } |
|
598 } |
|
599 break; |
547 case GST_MESSAGE_LATENCY: |
600 case GST_MESSAGE_LATENCY: |
548 #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 13) |
601 #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 13) |
549 case GST_MESSAGE_ASYNC_START: |
602 case GST_MESSAGE_ASYNC_START: |
550 case GST_MESSAGE_ASYNC_DONE: |
603 case GST_MESSAGE_ASYNC_DONE: |
551 #if GST_VERSION_MICRO >= 23 |
604 #if GST_VERSION_MICRO >= 23 |