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 unsigned frame_dur = xine_get_stream_info(stream, XINE_STREAM_INFO_FRAME_DURATION);
154 float fps = (frame_dur ? 90000.0f/frame_dur : 0.0f);
157 MutexLock lock(mutex);
159 signal_framerate_changed.emit(framerate);
162 const char *xvc = xine_get_meta_info(stream, XINE_META_INFO_VIDEOCODEC);
163 const char *xac = xine_get_meta_info(stream, XINE_META_INFO_AUDIOCODEC);
164 if(!equals(video_codec, xvc) || !equals(audio_codec, xac))
166 MutexLock lock(mutex);
167 video_codec = (xvc ? xvc : string());
168 audio_codec = (xac ? xac : string());
169 signal_codecs_changed.emit(video_codec, audio_codec);
172 int dur_msec, pos_msec;
173 xine_get_pos_length(stream, 0, &pos_msec, &dur_msec);
174 Time::TimeDelta dur = dur_msec*Time::msec;
175 Time::TimeDelta pos = pos_msec*Time::msec;
178 MutexLock lock(mutex);
180 signal_duration_changed.emit(duration);
184 MutexLock lock(mutex);
186 signal_position_changed.emit(position);
189 int audio = xine_get_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
190 if(audio==-1 && !audio_channels.empty())
194 if(audio!=current_audio)
196 MutexLock lock(mutex);
197 current_audio = audio;
198 signal_current_audio_channel_changed.emit(current_audio);
201 int spu = xine_get_param(stream, XINE_PARAM_SPU_CHANNEL);
206 MutexLock lock(mutex);
208 signal_current_spu_channel_changed.emit(current_spu);
212 void XineStream::update_channels()
214 MutexLock lock(mutex);
215 char langbuf[XINE_LANG_MAX];
217 unsigned n_audio = xine_get_stream_info(stream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL);
218 audio_channels.resize(n_audio);
219 for(unsigned i=0; i<n_audio; ++i)
221 if(xine_get_audio_lang(stream, i, langbuf))
222 audio_channels[i].assign(langbuf);
224 audio_channels[i].assign("unknown");
227 unsigned n_spu = xine_get_stream_info(stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
228 spu_channels.resize(n_spu);
229 for(unsigned i=0; i<n_spu; ++i)
231 if(xine_get_spu_lang(stream, i, langbuf))
232 spu_channels[i].assign(langbuf);
234 spu_channels[i].assign("unknown");
237 signal_channels_changed.emit();
240 void XineStream::handle_event(const xine_event_t &event)
244 case XINE_EVENT_UI_PLAYBACK_FINISHED:
246 signal_finished.emit();
248 case XINE_EVENT_UI_CHANNELS_CHANGED:
249 channels_changed = true;
255 void operator<<(LexicalConverter &conv, XineStream::State state)
259 case XineStream::STOPPED: conv.result("STOPPED"); return;
260 case XineStream::PAUSED: conv.result("PAUSED"); return;
261 case XineStream::PLAYING: conv.result("PLAYING"); return;
262 default: conv.result(format("State(%d)", static_cast<int>(state))); return;
266 void operator>>(const LexicalConverter &conv, XineStream::State &state)
268 const string &str = conv.get();
270 state = XineStream::STOPPED;
271 else if(str=="PAUSED")
272 state = XineStream::PAUSED;
273 else if(str=="PLAYING")
274 state = XineStream::PLAYING;
276 throw lexical_error(format("Conversion of '%s' to XineStream::State", str));