1 #include <msp/strings/format.h>
2 #include "xineengine.h"
3 #include "xinestream.h"
8 XineStream::XineStream(XineEngine &e, const string &mrl):
10 filename(mrl.substr(mrl.rfind('/')+1)),
15 channels_changed(false)
17 stream = xine_stream_new(engine.get_engine(), engine.get_audio_driver(), engine.get_video_driver());
18 queue = xine_event_new_queue(stream);
19 xine_open(stream, mrl.c_str());
24 engine.add_stream(*this);
27 const string &XineStream::get_title() const
29 return title.empty() ? filename : title;
32 XineStream::~XineStream()
34 engine.remove_stream(*this);
37 xine_event_dispose_queue(queue);
41 void XineStream::play()
44 xine_play(stream, 0, 0);
45 else if(state==PAUSED)
46 xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
51 void XineStream::seek(const Time::TimeDelta &time)
53 xine_play(stream, 0, time/Time::msec);
56 xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
61 void XineStream::pause()
65 xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
70 void XineStream::stop()
76 void XineStream::set_state(State s)
81 MutexLock lock(mutex);
83 signal_state_changed.emit(state);
86 void XineStream::select_audio_channel(int i)
88 if(i>=0 && static_cast<unsigned>(i)>=audio_channels.size())
89 throw out_of_range("XineStream::set_audio_channel");
93 xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, (i==OFF ? -2 : i));
96 void XineStream::select_spu_channel(int i)
98 if(i>=0 && static_cast<unsigned>(i)>=spu_channels.size())
99 throw out_of_range("XineStream::set_spu_channel");
103 xine_set_param(stream, XINE_PARAM_SPU_CHANNEL, (i==OFF ? -2 : i));
106 void XineStream::tick()
108 while(xine_event_t *event = xine_event_get(queue))
110 handle_event(*event);
111 xine_event_free(event);
116 channels_changed = false;
123 void XineStream::update_info()
125 const char *xt = xine_get_meta_info(stream, XINE_META_INFO_TITLE);
126 if((xt && title.compare(xt)) || (!xt && !title.empty()))
128 MutexLock lock(mutex);
129 title = (xt ? xt : string());
130 signal_title_changed.emit(get_title());
133 int dur_msec, pos_msec;
134 xine_get_pos_length(stream, 0, &pos_msec, &dur_msec);
135 Time::TimeDelta dur = dur_msec*Time::msec;
136 Time::TimeDelta pos = pos_msec*Time::msec;
139 MutexLock lock(mutex);
141 signal_duration_changed.emit(duration);
145 MutexLock lock(mutex);
147 signal_position_changed.emit(position);
150 int audio = xine_get_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
151 if(audio==-1 && !audio_channels.empty())
155 if(audio!=current_audio)
157 MutexLock lock(mutex);
158 current_audio = audio;
159 signal_current_audio_channel_changed.emit(current_audio);
162 int spu = xine_get_param(stream, XINE_PARAM_SPU_CHANNEL);
167 MutexLock lock(mutex);
169 signal_current_spu_channel_changed.emit(current_spu);
173 void XineStream::update_channels()
175 MutexLock lock(mutex);
176 char langbuf[XINE_LANG_MAX];
178 unsigned n_audio = xine_get_stream_info(stream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL);
179 audio_channels.resize(n_audio);
180 for(unsigned i=0; i<n_audio; ++i)
182 if(xine_get_audio_lang(stream, i, langbuf))
183 audio_channels[i].assign(langbuf);
185 audio_channels[i].assign("unknown");
188 unsigned n_spu = xine_get_stream_info(stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
189 spu_channels.resize(n_spu);
190 for(unsigned i=0; i<n_spu; ++i)
192 if(xine_get_spu_lang(stream, i, langbuf))
193 spu_channels[i].assign(langbuf);
195 spu_channels[i].assign("unknown");
198 signal_channels_changed.emit();
201 void XineStream::handle_event(const xine_event_t &event)
205 case XINE_EVENT_UI_PLAYBACK_FINISHED:
207 signal_finished.emit();
209 case XINE_EVENT_UI_CHANNELS_CHANGED:
210 channels_changed = true;
216 void operator<<(LexicalConverter &conv, XineStream::State state)
220 case XineStream::STOPPED: conv.result("STOPPED"); return;
221 case XineStream::PAUSED: conv.result("PAUSED"); return;
222 case XineStream::PLAYING: conv.result("PLAYING"); return;
223 default: conv.result(format("State(%d)", static_cast<int>(state))); return;
227 void operator>>(const LexicalConverter &conv, XineStream::State &state)
229 const string &str = conv.get();
231 state = XineStream::STOPPED;
232 else if(str=="PAUSED")
233 state = XineStream::PAUSED;
234 else if(str=="PLAYING")
235 state = XineStream::PLAYING;
237 throw lexical_error(format("Conversion of '%s' to XineStream::State", str));