#include <msp/fs/dir.h>
#include <msp/fs/stat.h>
+#include <msp/strings/format.h>
#include "client.h"
#include "xinema.h"
+#include "xinestream.h"
using namespace std;
using namespace Msp;
{
socket->signal_data_available.connect(sigc::mem_fun(this, &Client::data_available));
socket->signal_end_of_file.connect(sigc::mem_fun(this, &Client::end_of_stream));
+
+ xinema.signal_stream_created.connect(sigc::mem_fun(this, &Client::stream_created));
}
void Client::data_available()
send_reply("file "+*i);
}
}
+
+void Client::stream_created(XineStream &stream)
+{
+ stream.signal_duration_changed.connect(sigc::mem_fun(this, &Client::stream_duration_changed));
+ stream.signal_position_changed.connect(sigc::mem_fun(this, &Client::stream_position_changed));
+ string title = stream.get_title();
+ if(!title.empty())
+ send_reply("title "+title);
+}
+
+void Client::stream_duration_changed(const Time::TimeDelta &dur)
+{
+ send_reply(format("duration %.3f", dur/Time::sec));
+}
+
+void Client::stream_position_changed(const Time::TimeDelta &pos)
+{
+ if(abs(pos-last_position)>=Time::sec)
+ {
+ send_reply(format("position %.3f", pos/Time::sec));
+ last_position = pos;
+ }
+}
#ifndef CLIENT_H_
#define CLIENT_H_
+#include <sigc++/trackable.h>
#include <msp/fs/path.h>
#include <msp/net/streamsocket.h>
+#include <msp/time/timedelta.h>
+class XineStream;
class Xinema;
-class Client
+class Client: public sigc::trackable
{
private:
Xinema &xinema;
Msp::Net::StreamSocket *socket;
std::string buffer;
+ Msp::Time::TimeDelta last_position;
bool stale;
public:
void process_command(const std::string &);
void send_reply(const std::string &);
void list_directory(const Msp::FS::Path &);
+
+ void stream_created(XineStream &);
+ void stream_duration_changed(const Msp::Time::TimeDelta &);
+ void stream_position_changed(const Msp::Time::TimeDelta &);
};
#endif
void Xinema::tick()
{
+ bool new_stream = false;
+
{
MutexLock lock(command_mutex);
if(!pending_mrl.empty())
stream = new XineStream(*engine, pending_mrl);
stream->play();
pending_mrl.clear();
+ new_stream = true;
}
}
+ if(new_stream)
+ signal_stream_created.emit(*stream);
+
{
MutexLock lock(display_mutex);
display.tick();
class Xinema: public Msp::RegisteredApplication<Xinema>
{
+public:
+ sigc::signal<void, XineStream &> signal_stream_created;
+
private:
Msp::Graphics::Display display;
Msp::Mutex display_mutex;
xine_dispose(stream);
}
+string XineStream::get_title() const
+{
+ const char *title = xine_get_meta_info(stream, XINE_META_INFO_TITLE);
+ return (title ? title : string());
+}
+
void XineStream::play()
{
xine_play(stream, 0, 0);
handle_event(*event);
xine_event_free(event);
}
+
+ 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)
+ {
+ duration = dur;
+ signal_duration_changed.emit(duration);
+ }
+ if(pos!=position)
+ {
+ position = pos;
+ signal_position_changed.emit(position);
+ }
}
void XineStream::handle_event(const xine_event_t &event)
#include <string>
#include <xine.h>
+#include <msp/time/timedelta.h>
class XineEngine;
class XineStream
{
+public:
+ sigc::signal<void, const Msp::Time::TimeDelta &> signal_duration_changed;
+ sigc::signal<void, const Msp::Time::TimeDelta &> signal_position_changed;
+
private:
XineEngine &engine;
xine_stream_t *stream;
xine_event_queue_t *queue;
+ Msp::Time::TimeDelta duration;
+ Msp::Time::TimeDelta position;
public:
XineStream(XineEngine &, const std::string &);
~XineStream();
+ const Msp::Time::TimeDelta &get_duration() const { return duration; }
+ const Msp::Time::TimeDelta &get_position() const { return position; }
+ std::string get_title() const;
+
void play();
void stop();