-#include <msp/io/print.h>
+#include <msp/strings/format.h>
#include "xineengine.h"
#include "xinestream.h"
XineStream::XineStream(XineEngine &e, const string &mrl):
engine(e),
- state(STOPPED)
+ state(STOPPED),
+ current_audio(0),
+ current_spu(OFF),
+ 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);
- check_info();
+ update_channels();
+ update_info();
engine.add_stream(*this);
}
xine_dispose(stream);
}
+void XineStream::select_audio_channel(int i)
+{
+ if(i>=0 && static_cast<unsigned>(i)>=audio_channels.size())
+ throw out_of_range("XineStream::set_audio_channel");
+
+ if(i<0)
+ i = OFF;
+ xine_set_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, (i==OFF ? -2 : i));
+}
+
+void XineStream::select_spu_channel(int i)
+{
+ if(i>=0 && static_cast<unsigned>(i)>=spu_channels.size())
+ throw out_of_range("XineStream::set_spu_channel");
+
+ if(i<0)
+ i = OFF;
+ xine_set_param(stream, XINE_PARAM_SPU_CHANNEL, (i==OFF ? -2 : i));
+}
+
void XineStream::play()
{
if(state==STOPPED)
if(s==state)
return;
+ MutexLock lock(mutex);
state = s;
signal_state_changed.emit(state);
}
xine_event_free(event);
}
- check_info();
+ if(channels_changed)
+ {
+ channels_changed = false;
+ update_channels();
+ }
+
+ update_info();
}
-void XineStream::check_info()
+void XineStream::update_info()
{
const char *xt = xine_get_meta_info(stream, XINE_META_INFO_TITLE);
- if(xt)
+ if((xt && title.compare(xt)) || (!xt && !title.empty()))
{
- if(title.compare(xt))
- {
- title = xt;
- signal_title_changed.emit(title);
- }
- }
- else if(!title.empty())
- {
- title.clear();
+ MutexLock lock(mutex);
+ title = (xt ? xt : string());
signal_title_changed.emit(title);
}
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);
}
+
+ int audio = xine_get_param(stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
+ if(audio==-1 && !audio_channels.empty())
+ audio = 0;
+ else if(audio<0)
+ audio = OFF;
+ if(audio!=current_audio)
+ {
+ MutexLock lock(mutex);
+ current_audio = audio;
+ signal_current_audio_channel_changed.emit(current_audio);
+ }
+
+ int spu = xine_get_param(stream, XINE_PARAM_SPU_CHANNEL);
+ if(spu<0)
+ spu = OFF;
+ if(spu!=current_spu)
+ {
+ MutexLock lock(mutex);
+ current_spu = spu;
+ signal_current_spu_channel_changed.emit(current_spu);
+ }
+}
+
+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<n_audio; ++i)
+ {
+ xine_get_audio_lang(stream, i, langbuf);
+ audio_channels[i].assign(langbuf);
+ }
+
+ unsigned n_spu = xine_get_stream_info(stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
+ spu_channels.resize(n_spu);
+ for(unsigned i=0; i<n_spu; ++i)
+ {
+ xine_get_spu_lang(stream, i, langbuf);
+ spu_channels[i].assign(langbuf);
+ }
+
+ signal_channels_changed.emit();
}
void XineStream::handle_event(const xine_event_t &event)
{
case XINE_EVENT_UI_PLAYBACK_FINISHED:
set_state(STOPPED);
+ signal_finished.emit();
break;
- 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_CHANNELS_CHANGED:
+ channels_changed = true;
break;
}
}