X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/884a9bb30ff4a4715e96207269d149c304ecfc1d..b643641e2c6288eff61d0346a3dda82bd820b3b7:/lib/service/servicemp3.cpp diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 7d5901e2..e684e393 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -17,12 +17,6 @@ /* for subtitles */ #include -#ifndef GST_SEEK_FLAG_SKIP -#warning Compiling for legacy gstreamer, things will break -#define GST_SEEK_FLAG_SKIP 0 -#define GST_TAG_HOMEPAGE "" -#endif - // eServiceFactoryMP3 eServiceFactoryMP3::eServiceFactoryMP3() @@ -40,6 +34,7 @@ eServiceFactoryMP3::eServiceFactoryMP3() extensions.push_back("vob"); extensions.push_back("wav"); extensions.push_back("wave"); + extensions.push_back("m4v"); extensions.push_back("mkv"); extensions.push_back("avi"); extensions.push_back("divx"); @@ -48,7 +43,6 @@ eServiceFactoryMP3::eServiceFactoryMP3() extensions.push_back("mp4"); extensions.push_back("mov"); extensions.push_back("m4a"); - extensions.push_back("m2ts"); sc->addServiceFactory(eServiceFactoryMP3::id, this, extensions); } @@ -200,7 +194,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) m_seekTimeout = eTimer::create(eApp); m_subtitle_sync_timer = eTimer::create(eApp); m_stream_tags = 0; - m_currentAudioStream = 0; + m_currentAudioStream = -1; m_currentSubtitleStream = 0; m_subtitle_widget = 0; m_currentTrickRatio = 0; @@ -242,7 +236,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) sourceinfo.containertype = ctAVI; sourceinfo.is_video = TRUE; } - else if ( strcasecmp(ext, ".mp4") == 0 || strcasecmp(ext, ".mov") == 0) + else if ( strcasecmp(ext, ".mp4") == 0 || strcasecmp(ext, ".mov") == 0 || strcasecmp(ext, ".m4v") == 0) { sourceinfo.containertype = ctMP4; sourceinfo.is_video = TRUE; @@ -308,7 +302,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink"); else { - g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); + m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL); } @@ -341,16 +335,28 @@ eServiceMP3::eServiceMP3(eServiceReference ref) m_gst_playbin = 0; } - gst_element_set_state (m_gst_playbin, GST_STATE_PLAYING); setBufferSize(m_buffer_size); } eServiceMP3::~eServiceMP3() { + // disconnect subtitle callback + GstElement *sink; + g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL); + if (sink) + { + g_signal_handler_disconnect (sink, m_subs_to_pull_handler_id); + gst_object_unref(sink); + } + delete m_subtitle_widget; + + // disconnect sync handler callback + gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), NULL, NULL); + if (m_state == stRunning) stop(); - + if (m_stream_tags) gst_tag_list_free(m_stream_tags); @@ -361,7 +367,7 @@ eServiceMP3::~eServiceMP3() } } -DEFINE_REF(eServiceMP3); +DEFINE_REF(eServiceMP3); RESULT eServiceMP3::connectEvent(const Slot2 &event, ePtr &connection) { @@ -372,25 +378,30 @@ RESULT eServiceMP3::connectEvent(const Slot2 &event, RESULT eServiceMP3::start() { ASSERT(m_state == stIdle); - + m_state = stRunning; if (m_gst_playbin) { eDebug("eServiceMP3::starting pipeline"); gst_element_set_state (m_gst_playbin, GST_STATE_PLAYING); } + m_event(this, evStart); + return 0; } RESULT eServiceMP3::stop() { ASSERT(m_state != stIdle); + if (m_state == stStopped) return -1; + eDebug("eServiceMP3::stop %s", m_ref.path.c_str()); gst_element_set_state(m_gst_playbin, GST_STATE_NULL); m_state = stStopped; + return 0; } @@ -446,24 +457,19 @@ RESULT eServiceMP3::pause() { if (!m_gst_playbin || m_state != stRunning) return -1; - GstStateChangeReturn res = gst_element_set_state(m_gst_playbin, GST_STATE_PAUSED); - if (res == GST_STATE_CHANGE_ASYNC) - { - pts_t ppos; - getPlayPosition(ppos); - seekTo(ppos); - } + + gst_element_set_state(m_gst_playbin, GST_STATE_PAUSED); + return 0; } RESULT eServiceMP3::unpause() { - m_subtitle_pages.clear(); if (!m_gst_playbin || m_state != stRunning) return -1; - GstStateChangeReturn res; - res = gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); + gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING); + return 0; } @@ -478,9 +484,10 @@ RESULT eServiceMP3::getLength(pts_t &pts) { if (!m_gst_playbin) return -1; + if (m_state != stRunning) return -1; - + GstFormat fmt = GST_FORMAT_TIME; gint64 len; @@ -492,13 +499,8 @@ RESULT eServiceMP3::getLength(pts_t &pts) return 0; } -RESULT eServiceMP3::seekTo(pts_t to) +RESULT eServiceMP3::seekToImpl(pts_t to) { - if (!m_gst_playbin) - return -1; - - eSingleLocker l(m_subs_to_pull_lock); // this is needed to dont handle incomming subtitles during seek! - /* convert pts to nanoseconds */ gint64 time_nanoseconds = to * 11111LL; if (!gst_element_seek (m_gst_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, @@ -509,12 +511,26 @@ RESULT eServiceMP3::seekTo(pts_t to) return -1; } - m_subtitle_pages.clear(); - m_subs_to_pull = 0; - return 0; } +RESULT eServiceMP3::seekTo(pts_t to) +{ + RESULT ret = -1; + + if (m_gst_playbin) { + eSingleLocker l(m_subs_to_pull_lock); // this is needed to dont handle incomming subtitles during seek! + if (!(ret = seekToImpl(to))) + { + m_subtitle_pages.clear(); + m_subs_to_pull = 0; + } + } + + return ret; +} + + RESULT eServiceMP3::trickSeek(gdouble ratio) { if (!m_gst_playbin) @@ -523,11 +539,11 @@ RESULT eServiceMP3::trickSeek(gdouble ratio) return seekRelative(0, 0); GstEvent *s_event; - GstSeekFlags flags; + int flags; flags = GST_SEEK_FLAG_NONE; - flags |= GstSeekFlags (GST_SEEK_FLAG_FLUSH); + flags |= GST_SEEK_FLAG_FLUSH; // flags |= GstSeekFlags (GST_SEEK_FLAG_ACCURATE); - flags |= GstSeekFlags (GST_SEEK_FLAG_KEY_UNIT); + flags |= GST_SEEK_FLAG_KEY_UNIT; // flags |= GstSeekFlags (GST_SEEK_FLAG_SEGMENT); // flags |= GstSeekFlags (GST_SEEK_FLAG_SKIP); @@ -538,13 +554,13 @@ RESULT eServiceMP3::trickSeek(gdouble ratio) if ( ratio >= 0 ) { - s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, len); + s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, (GstSeekFlags)flags, GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, len); eDebug("eServiceMP3::trickSeek with rate %lf to %" GST_TIME_FORMAT " ", ratio, GST_TIME_ARGS (pos)); } else { - s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, GST_SEEK_FLAG_SKIP|GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1); + s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_SKIP|GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1); } if (!gst_element_send_event ( GST_ELEMENT (m_gst_playbin), s_event)) @@ -619,7 +635,31 @@ RESULT eServiceMP3::setTrickmode(int trick) RESULT eServiceMP3::isCurrentlySeekable() { - return 1; + int ret = 3; // seeking and fast/slow winding possible + GstElement *sink; + + if (!m_gst_playbin) + return 0; + if (m_state != stRunning) + return 0; + + g_object_get (G_OBJECT (m_gst_playbin), "video-sink", &sink, NULL); + + // disable fast winding yet when a dvbvideosink or dvbaudiosink is used + // for this we must do some changes on different places.. (gstreamer.. our sinks.. enigma2) + if (sink) { + ret &= ~2; // only seeking possible + gst_object_unref(sink); + } + else { + g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL); + if (sink) { + ret &= ~2; // only seeking possible + gst_object_unref(sink); + } + } + + return ret; } RESULT eServiceMP3::info(ePtr&i) @@ -900,10 +940,7 @@ PyObject *eServiceMP3::getInfoObject(int w) default: break; } - gdouble value; - if ( !tag || !m_stream_tags ) - value = 0.0; - PyObject *pyValue; + if ( isBuffer ) { const GValue *gv_buffer = gst_tag_list_get_value_index(m_stream_tags, tag, 0); @@ -911,16 +948,17 @@ PyObject *eServiceMP3::getInfoObject(int w) { GstBuffer *buffer; buffer = gst_value_get_buffer (gv_buffer); - pyValue = PyBuffer_FromMemory(GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); + return PyBuffer_FromMemory(GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); } } else { + gdouble value = 0.0; gst_tag_list_get_double(m_stream_tags, tag, &value); - pyValue = PyFloat_FromDouble(value); + return PyFloat_FromDouble(value); } - return pyValue; + return 0; } RESULT eServiceMP3::audioChannel(ePtr &ptr) @@ -948,16 +986,24 @@ int eServiceMP3::getNumberOfTracks() int eServiceMP3::getCurrentTrack() { + if (m_currentAudioStream == -1) + g_object_get (G_OBJECT (m_gst_playbin), "current-audio", &m_currentAudioStream, NULL); return m_currentAudioStream; } RESULT eServiceMP3::selectTrack(unsigned int i) { - int ret = selectAudioStream(i); - /* flush */ pts_t ppos; getPlayPosition(ppos); - seekTo(ppos); + ppos -= 90000; + if (ppos < 0) + ppos = 0; + + int ret = selectAudioStream(i); + if (!ret) { + /* flush */ + seekTo(ppos); + } return ret; } @@ -1182,8 +1228,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) if (!caps) continue; GstStructure* str = gst_caps_get_structure(caps, 0); - gchar *g_type; - g_type = gst_structure_get_name(str); + const gchar *g_type = gst_structure_get_name(str); eDebug("AUDIO STRUCT=%s", g_type); audio.type = gstCheckAudioPad(str); g_codec = g_strdup(g_type); @@ -1374,8 +1419,8 @@ void eServiceMP3::pullSubtitle() { eSingleLocker l(m_subs_to_pull_lock); --m_subs_to_pull; + g_signal_emit_by_name (sink, "pull-buffer", &buffer); } - g_signal_emit_by_name (sink, "pull-buffer", &buffer); if (buffer) { gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer); @@ -1471,9 +1516,9 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) if (m_currentSubtitleStream != pid) { + eSingleLocker l(m_subs_to_pull_lock); g_object_set (G_OBJECT (m_gst_playbin), "current-text", pid, NULL); m_currentSubtitleStream = pid; - eSingleLocker l(m_subs_to_pull_lock); m_subs_to_pull = 0; m_subtitle_pages.clear(); } @@ -1486,7 +1531,6 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple) eDebug ("eServiceMP3::switched to subtitle stream %i", text_pid); - return 0; error_out: