X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fxinestream.cpp;h=a702b28b335e66ce0ed840c1d11f68da83aa22aa;hb=a4982bb4d3fd9908aa01c824ac6202ac8618ac24;hp=fd2c6224fb9e6aea49551af343f829b4881d37fe;hpb=4157ae2c48c539a3bbe609ab143d4c1454fd1748;p=xinema.git diff --git a/source/xinestream.cpp b/source/xinestream.cpp index fd2c622..a702b28 100644 --- a/source/xinestream.cpp +++ b/source/xinestream.cpp @@ -1,33 +1,104 @@ -#include +#include #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), + channels_changed(false) { 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); + + update_info(); + update_channels(); + + engine.add_stream(*this); } XineStream::~XineStream() { + engine.remove_stream(*this); + xine_close(stream); xine_event_dispose_queue(queue); xine_dispose(stream); } +void XineStream::set_audio_channel(unsigned i) +{ + if(i>=audio_channels.size()) + throw out_of_range("XineStream::set_audio_channel"); + + xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, i); +} + +void XineStream::set_audio_off() +{ + xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -2); +} + +void XineStream::set_spu_channel(unsigned i) +{ + if(i>=spu_channels.size()) + throw out_of_range("XineStream::set_spu_channel"); + + xine_set_param(stream, XINE_PARAM_SPU_CHANNEL, i); +} + +void XineStream::set_spu_off() +{ + xine_set_param(stream, XINE_PARAM_SPU_CHANNEL, -2); +} + 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() @@ -37,17 +108,103 @@ void XineStream::tick() handle_event(*event); xine_event_free(event); } + + update_info(); + + if(channels_changed) + { + channels_changed = false; + update_channels(); + } +} + +void XineStream::update_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::update_channels() +{ + MutexLock lock(mutex); + char langbuf[XINE_LANG_MAX]; + + unsigned n_audio = xine_get_stream_info(stream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL); + audio_channels.resize(n_audio); + for(unsigned i=0; i(event.data); - IO::print("%s [%d%%]\n", data->description, data->percent); - } + case XINE_EVENT_UI_PLAYBACK_FINISHED: + set_state(STOPPED); + signal_finished.emit(); break; + case XINE_EVENT_UI_CHANNELS_CHANGED: + channels_changed = true; + 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(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)); +}