]> git.tdb.fi Git - xinema.git/blobdiff - source/xinestream.cpp
Implement basic playback controls
[xinema.git] / source / xinestream.cpp
index d152f518e2cb34941d24521d0e205ed04d532e1e..619ec5800872e7d1c843f4eddde41c50178c1193 100644 (file)
@@ -6,13 +6,16 @@ using namespace std;
 using namespace Msp;
 
 XineStream::XineStream(XineEngine &e, const string &mrl):
-       engine(e)
+       engine(e),
+       state(STOPPED)
 {
        stream = xine_stream_new(engine.get_engine(), engine.get_audio_driver(), engine.get_video_driver());
        xine_open(stream, mrl.c_str());
 
        queue = xine_event_new_queue(stream);
 
+       check_info();
+
        engine.add_stream(*this);
 }
 
@@ -25,20 +28,48 @@ XineStream::~XineStream()
        xine_dispose(stream);
 }
 
-string XineStream::get_title() const
+void XineStream::play()
 {
-       const char *title = xine_get_meta_info(stream, XINE_META_INFO_TITLE);
-       return (title ? title : string());
+       if(state==STOPPED)
+               xine_play(stream, 0, 0);
+       else if(state==PAUSED)
+               xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
+
+       set_state(PLAYING);
 }
 
-void XineStream::play()
+void XineStream::seek(const Time::TimeDelta &time)
+{
+       xine_play(stream, 0, time/Time::msec);
+       if(state!=PLAYING)
+       {
+               xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
+               set_state(PAUSED);
+       }
+}
+
+void XineStream::pause()
 {
-       xine_play(stream, 0, 0);
+       if(state==PLAYING)
+       {
+               xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
+               set_state(PAUSED);
+       }
 }
 
 void XineStream::stop()
 {
        xine_stop(stream);
+       set_state(STOPPED);
+}
+
+void XineStream::set_state(State s)
+{
+       if(s==state)
+               return;
+
+       state = s;
+       signal_state_changed.emit(state);
 }
 
 void XineStream::tick()
@@ -49,6 +80,26 @@ void XineStream::tick()
                xine_event_free(event);
        }
 
+       check_info();
+}
+
+void XineStream::check_info()
+{
+       const char *xt = xine_get_meta_info(stream, XINE_META_INFO_TITLE);
+       if(xt)
+       {
+               if(title.compare(xt))
+               {
+                       title = xt;
+                       signal_title_changed.emit(title);
+               }
+       }
+       else if(!title.empty())
+       {
+               title.clear();
+               signal_title_changed.emit(title);
+       }
+
        int dur_msec, pos_msec;
        xine_get_pos_length(stream, 0, &pos_msec, &dur_msec);
        Time::TimeDelta dur = dur_msec*Time::msec;
@@ -69,6 +120,9 @@ void XineStream::handle_event(const xine_event_t &event)
 {
        switch(event.type)
        {
+       case XINE_EVENT_UI_PLAYBACK_FINISHED:
+               set_state(STOPPED);
+               break;
        case XINE_EVENT_PROGRESS:
                {
                        xine_progress_data_t *data = reinterpret_cast<xine_progress_data_t *>(event.data);
@@ -77,3 +131,28 @@ void XineStream::handle_event(const xine_event_t &event)
                break;
        }
 }
+
+
+void operator<<(LexicalConverter &conv, XineStream::State state)
+{
+       switch(state)
+       {
+       case XineStream::STOPPED: conv.result("STOPPED"); return;
+       case XineStream::PAUSED: conv.result("PAUSED"); return;
+       case XineStream::PLAYING: conv.result("PLAYING"); return;
+       default: conv.result(format("State(%d)", static_cast<int>(state))); return;
+       }
+}
+
+void operator>>(const LexicalConverter &conv, XineStream::State &state)
+{
+       const string &str = conv.get();
+       if(str=="STOPPED")
+               state = XineStream::STOPPED;
+       else if(str=="PAUSED")
+               state = XineStream::PAUSED;
+       else if(str=="PLAYING")
+               state = XineStream::PLAYING;
+       else
+               throw lexical_error(format("Conversion of '%s' to XineStream::State", str));
+}