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)),
18 channels_changed(false)
20 stream = xine_stream_new(engine.get_engine(), engine.get_audio_driver(), engine.get_video_driver());
21 queue = xine_event_new_queue(stream);
22 xine_open(stream, mrl.c_str());
27 engine.add_stream(*this);
30 const string &XineStream::get_title() const
32 return title.empty() ? filename : title;
35 XineStream::~XineStream()
37 engine.remove_stream(*this);
40 xine_event_dispose_queue(queue);
44 void XineStream::play()
47 xine_play(stream, 0, 0);
48 else if(state==PAUSED)
49 xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
54 void XineStream::seek(const Time::TimeDelta &time)
56 xine_play(stream, 0, time/Time::msec);
59 xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
64 void XineStream::pause()
68 xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
73 void XineStream::stop()
79 void XineStream::set_state(State s)
84 MutexLock lock(mutex);
86 signal_state_changed.emit(state);
89 void XineStream::select_audio_channel(int i)
91 if(i>=0 && static_cast<unsigned>(i)>=audio_channels.size())
92 throw out_of_range("XineStream::set_audio_channel");
96 xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, (i==OFF ? -2 : i));
99 void XineStream::select_spu_channel(int i)
101 if(i>=0 && static_cast<unsigned>(i)>=spu_channels.size())
102 throw out_of_range("XineStream::set_spu_channel");
106 xine_set_param(stream, XINE_PARAM_SPU_CHANNEL, (i==OFF ? -2 : i));
109 void XineStream::tick()
111 while(xine_event_t *event = xine_event_get(queue))
113 handle_event(*event);
114 xine_event_free(event);
119 channels_changed = false;
126 bool XineStream::equals(const string &s1, const char *s2)
130 return !s1.compare(s2);
133 void XineStream::update_info()
135 const char *xt = xine_get_meta_info(stream, XINE_META_INFO_TITLE);
136 if(!equals(title, xt))
138 MutexLock lock(mutex);
139 title = (xt ? xt : string());
140 signal_title_changed.emit(get_title());
143 unsigned w = xine_get_stream_info(stream, XINE_STREAM_INFO_VIDEO_WIDTH);
144 unsigned h = xine_get_stream_info(stream, XINE_STREAM_INFO_VIDEO_HEIGHT);
145 if(w!=video_width || h!=video_height)
147 MutexLock lock(mutex);
150 signal_video_size_changed.emit(video_width, video_height);
153 float fps = 90000.0f/xine_get_stream_info(stream, XINE_STREAM_INFO_FRAME_DURATION);
156 MutexLock lock(mutex);
158 signal_framerate_changed.emit(framerate);
161 const char *xvc = xine_get_meta_info(stream, XINE_META_INFO_VIDEOCODEC);
162 const char *xac = xine_get_meta_info(stream, XINE_META_INFO_AUDIOCODEC);
163 if(!equals(video_codec, xvc) || !equals(audio_codec, xac))
165 MutexLock lock(mutex);
166 video_codec = (xvc ? xvc : string());
167 audio_codec = (xac ? xac : string());
168 signal_codecs_changed.emit(video_codec, audio_codec);
171 int dur_msec, pos_msec;
172 xine_get_pos_length(stream, 0, &pos_msec, &dur_msec);
173 Time::TimeDelta dur = dur_msec*Time::msec;
174 Time::TimeDelta pos = pos_msec*Time::msec;
177 MutexLock lock(mutex);
179 signal_duration_changed.emit(duration);
183 MutexLock lock(mutex);
185 signal_position_changed.emit(position);
188 int audio = xine_get_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
189 if(audio==-1 && !audio_channels.empty())
193 if(audio!=current_audio)
195 MutexLock lock(mutex);
196 current_audio = audio;
197 signal_current_audio_channel_changed.emit(current_audio);
200 int spu = xine_get_param(stream, XINE_PARAM_SPU_CHANNEL);
205 MutexLock lock(mutex);
207 signal_current_spu_channel_changed.emit(current_spu);
211 void XineStream::update_channels()
213 MutexLock lock(mutex);
214 char langbuf[XINE_LANG_MAX];
216 unsigned n_audio = xine_get_stream_info(stream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL);
217 audio_channels.resize(n_audio);
218 for(unsigned i=0; i<n_audio; ++i)
220 if(xine_get_audio_lang(stream, i, langbuf))
221 audio_channels[i].assign(langbuf);
223 audio_channels[i].assign("unknown");
226 unsigned n_spu = xine_get_stream_info(stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
227 spu_channels.resize(n_spu);
228 for(unsigned i=0; i<n_spu; ++i)
230 if(xine_get_spu_lang(stream, i, langbuf))
231 spu_channels[i].assign(langbuf);
233 spu_channels[i].assign("unknown");
236 signal_channels_changed.emit();
239 void XineStream::handle_event(const xine_event_t &event)
243 case XINE_EVENT_UI_PLAYBACK_FINISHED:
245 signal_finished.emit();
247 case XINE_EVENT_UI_CHANNELS_CHANGED:
248 channels_changed = true;
254 void operator<<(LexicalConverter &conv, XineStream::State state)
258 case XineStream::STOPPED: conv.result("STOPPED"); return;
259 case XineStream::PAUSED: conv.result("PAUSED"); return;
260 case XineStream::PLAYING: conv.result("PLAYING"); return;
261 default: conv.result(format("State(%d)", static_cast<int>(state))); return;
265 void operator>>(const LexicalConverter &conv, XineStream::State &state)
267 const string &str = conv.get();
269 state = XineStream::STOPPED;
270 else if(str=="PAUSED")
271 state = XineStream::PAUSED;
272 else if(str=="PLAYING")
273 state = XineStream::PLAYING;
275 throw lexical_error(format("Conversion of '%s' to XineStream::State", str));