-#include <msp/io/print.h>
+#include <msp/strings/format.h>
#include "xineengine.h"
#include "xinestream.h"
using namespace std;
using namespace Msp;
-XineStream::XineStream(XineEngine &engine, const string &mrl)
+XineStream::XineStream(XineEngine &e, const string &mrl):
+ 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);
}
XineStream::~XineStream()
{
+ engine.remove_stream(*this);
+
xine_close(stream);
xine_event_dispose_queue(queue);
xine_dispose(stream);
void XineStream::play()
{
- xine_play(stream, 0, 0);
+ 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::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()
+{
+ 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;
+
+ MutexLock lock(mutex);
+ state = s;
+ signal_state_changed.emit(state);
}
void XineStream::tick()
handle_event(*event);
xine_event_free(event);
}
+
+ check_info();
+}
+
+void XineStream::check_info()
+{
+ const char *xt = xine_get_meta_info(stream, XINE_META_INFO_TITLE);
+ if((xt && title.compare(xt)) || (!xt && !title.empty()))
+ {
+ MutexLock lock(mutex);
+ title = (xt ? xt : string());
+ 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;
+ Time::TimeDelta pos = pos_msec*Time::msec;
+ if(dur!=duration)
+ {
+ MutexLock lock(mutex);
+ duration = dur;
+ signal_duration_changed.emit(duration);
+ }
+ if(pos!=position)
+ {
+ MutexLock lock(mutex);
+ position = pos;
+ signal_position_changed.emit(position);
+ }
}
void XineStream::handle_event(const xine_event_t &event)
{
switch(event.type)
{
- case XINE_EVENT_PROGRESS:
- {
- xine_progress_data_t *data = reinterpret_cast<xine_progress_data_t *>(event.data);
- IO::print("%s [%d%%]\n", data->description, data->percent);
- }
+ case XINE_EVENT_UI_PLAYBACK_FINISHED:
+ set_state(STOPPED);
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));
+}