alternative media decoder based on libxine
authorFelix Domke <tmbinc@elitedvb.net>
Mon, 2 Oct 2006 02:20:56 +0000 (02:20 +0000)
committerFelix Domke <tmbinc@elitedvb.net>
Mon, 2 Oct 2006 02:20:56 +0000 (02:20 +0000)
lib/service/servicexine.cpp [new file with mode: 0644]
lib/service/servicexine.h [new file with mode: 0644]

diff --git a/lib/service/servicexine.cpp b/lib/service/servicexine.cpp
new file mode 100644 (file)
index 0000000..b2ef7f7
--- /dev/null
@@ -0,0 +1,358 @@
+#define HAVE_XINE
+#ifdef HAVE_XINE
+
+/* yes, it's xine, not Xine. But eServicexine looks odd. */
+
+#include <lib/base/eerror.h>
+#include <lib/base/object.h>
+#include <lib/base/ebase.h>
+#include <string>
+#include <lib/service/servicexine.h>
+#include <lib/service/service.h>
+#include <lib/base/init_num.h>
+#include <lib/base/init.h>
+
+static xine_t *xine; /* TODO: move this into a static class */
+
+// eServiceFactoryXine
+
+eServiceFactoryXine::eServiceFactoryXine()
+{
+       ePtr<eServiceCenter> sc;
+       
+       eServiceCenter::getPrivInstance(sc);
+       if (sc)
+               sc->addServiceFactory(eServiceFactoryXine::id, this);
+
+       m_service_info = new eStaticServiceXineInfo();
+}
+
+eServiceFactoryXine::~eServiceFactoryXine()
+{
+       ePtr<eServiceCenter> sc;
+       
+       eServiceCenter::getPrivInstance(sc);
+       if (sc)
+               sc->removeServiceFactory(eServiceFactoryXine::id);
+}
+
+DEFINE_REF(eServiceFactoryXine)
+
+       // iServiceHandler
+RESULT eServiceFactoryXine::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
+{
+               // check resources...
+       ptr = new eServiceXine(ref.path.c_str());
+       return 0;
+}
+
+RESULT eServiceFactoryXine::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
+{
+       ptr=0;
+       return -1;
+}
+
+RESULT eServiceFactoryXine::list(const eServiceReference &, ePtr<iListableService> &ptr)
+{
+       ptr=0;
+       return -1;
+}
+
+RESULT eServiceFactoryXine::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
+{
+       ptr = m_service_info;
+       return 0;
+}
+
+RESULT eServiceFactoryXine::offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr)
+{
+       ptr = 0;
+       return -1;
+}
+
+
+// eStaticServiceXineInfo
+
+
+DEFINE_REF(eStaticServiceXineInfo)
+
+eStaticServiceXineInfo::eStaticServiceXineInfo()
+{
+}
+
+RESULT eStaticServiceXineInfo::getName(const eServiceReference &ref, std::string &name)
+{
+       size_t last = ref.path.rfind('/');
+       if (last != std::string::npos)
+               name = ref.path.substr(last+1);
+       else
+               name = ref.path;
+       return 0;
+}
+
+int eStaticServiceXineInfo::getLength(const eServiceReference &ref)
+{
+       return -1;
+}
+
+// eServiceXine
+
+eServiceXine::eServiceXine(const char *filename): m_filename(filename), m_pump(eApp, 1)
+{
+       m_state = stError;
+       stream = 0;
+       event_queue = 0;
+       ao_port = 0;
+       vo_port = 0;
+       
+       
+       if ((vo_port = xine_open_video_driver(xine, "fb", XINE_VISUAL_TYPE_FB, NULL)) == NULL)
+       {
+               eWarning("cannot open xine video driver");
+       }
+
+       if ((ao_port = xine_open_audio_driver(xine , "alsa", NULL)) == NULL)
+       {
+               eWarning("cannot open xine audio driver");
+       }
+       stream = xine_stream_new(xine, ao_port, vo_port);
+       event_queue = xine_event_new_queue(stream);
+       xine_event_create_listener_thread(event_queue, eventListenerWrap, this);
+
+//     CONNECT(m_pump.recv_msg, eServiceXine::gstPoll);
+       m_state = stIdle;
+}
+
+eServiceXine::~eServiceXine()
+{
+       if (m_state == stRunning)
+               stop();
+
+       if (stream)
+               xine_close(stream);
+       if (event_queue)
+               xine_event_dispose_queue(event_queue);
+       if (stream)
+               xine_dispose(stream);
+       if (ao_port)
+               xine_close_audio_driver(xine, ao_port); 
+       if (vo_port)
+               xine_close_video_driver(xine, vo_port); 
+}
+
+DEFINE_REF(eServiceXine);      
+
+void eServiceXine::eventListenerWrap(void *user_data, const xine_event_t *event)
+{
+       eServiceXine *e = (eServiceXine*)user_data;
+       e->eventListener(event);
+}
+
+void eServiceXine::eventListener(const xine_event_t *event)
+{
+       eDebug("handle %d", event->type);
+       switch(event->type) { 
+       case XINE_EVENT_UI_PLAYBACK_FINISHED:
+               break;
+       }
+}
+
+RESULT eServiceXine::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
+{
+       connection = new eConnection((iPlayableService*)this, m_event.connect(event));
+       return 0;
+}
+
+RESULT eServiceXine::start()
+{
+       if (m_state == stError)
+               return -1;
+
+       assert(m_state == stIdle);
+       assert(stream);
+       
+       if (!xine_open(stream, m_filename.c_str()))
+       {
+               eWarning("xine_open failed!");
+               return -1;
+       }
+       
+       if (!xine_play(stream, 0, 0))
+       {
+               eWarning("xine_play failed!");
+               return -1;
+       }
+
+       m_state = stRunning;
+       
+       m_event(this, evStart);
+       return 0;
+}
+
+RESULT eServiceXine::stop()
+{
+       if (m_state == stError)
+               return -1;
+
+       assert(m_state != stIdle);
+       assert(stream);
+       if (m_state == stStopped)
+               return -1;
+       printf("Xine: %s stop\n", m_filename.c_str());
+       xine_stop(stream);
+       // STOP
+       m_state = stStopped;
+       return 0;
+}
+
+RESULT eServiceXine::setTarget(int target)
+{
+       return -1;
+}
+
+RESULT eServiceXine::pause(ePtr<iPauseableService> &ptr)
+{
+       ptr=this;
+       return 0;
+}
+
+RESULT eServiceXine::setSlowMotion(int ratio)
+{
+       return -1;
+}
+
+RESULT eServiceXine::setFastForward(int ratio)
+{
+       return -1;
+}
+  
+               // iPausableService
+RESULT eServiceXine::pause()
+{
+       // PAUSE
+       return 0;
+}
+
+RESULT eServiceXine::unpause()
+{
+       // PLAY
+       return 0;
+}
+
+       /* iSeekableService */
+RESULT eServiceXine::seek(ePtr<iSeekableService> &ptr)
+{
+       ptr = this;
+       return 0;
+}
+
+RESULT eServiceXine::getLength(pts_t &pts)
+{
+               // LENGTH
+       return 0;
+}
+
+RESULT eServiceXine::seekTo(pts_t to)
+{
+               // SEEK
+       return 0;
+}
+
+RESULT eServiceXine::seekRelative(int direction, pts_t to)
+{
+               // SEEK RELATIVE
+       return 0;
+}
+
+RESULT eServiceXine::getPlayPosition(pts_t &pts)
+{
+               // GET POSITION
+       return 0;
+}
+
+RESULT eServiceXine::setTrickmode(int trick)
+{
+               /* trickmode currently doesn't make any sense for us. */
+       return -1;
+}
+
+RESULT eServiceXine::isCurrentlySeekable()
+{
+       return 1;
+}
+
+RESULT eServiceXine::info(ePtr<iServiceInformation>&i)
+{
+       i = this;
+       return 0;
+}
+
+RESULT eServiceXine::getName(std::string &name)
+{
+       name = "xine File: " + m_filename;
+       return 0;
+}
+
+int eServiceXine::getInfo(int w)
+{
+       switch (w)
+       {
+       case sTitle:
+       case sArtist:
+       case sAlbum:
+       case sComment:
+       case sTracknumber:
+       case sGenre:
+               return resIsString;
+
+       default:
+               return resNA;
+       }
+}
+
+std::string eServiceXine::getInfoString(int w)
+{
+       return "";
+}
+
+class eXine
+{
+public:
+       eXine()
+       {
+                       /* this should be done once. */
+
+               if(!xine_check_version(1, 1, 0))
+               {
+                       int major, minor, sub;
+                       xine_get_version (&major, &minor, &sub);
+                       eWarning("Require xine library version 1.1.0, found %d.%d.%d.\n",
+                                               major, minor,sub);
+                       return;
+               } else {
+                       int major, minor, sub;
+                       eDebug("Built with xine library %d.%d.%d (%s)\n",
+                                                XINE_MAJOR_VERSION, XINE_MINOR_VERSION, XINE_SUB_VERSION, XINE_VERSION);
+               
+                       xine_get_version (&major, &minor, &sub);
+
+                       eDebug("Found xine library version: %d.%d.%d (%s).\n", 
+                                                major, minor, sub, xine_get_version_string());
+               }
+       
+               xine = xine_new();
+               xine_engine_set_param(xine, XINE_ENGINE_PARAM_VERBOSITY, 1);
+               xine_init(xine);
+       }
+       ~eXine()
+       {
+               if (xine)
+                       xine_exit(xine);
+       }
+};
+
+eAutoInitP0<eXine> init_eXine(eAutoInitNumbers::service, "libxine");
+eAutoInitPtr<eServiceFactoryXine> init_eServiceFactoryXine(eAutoInitNumbers::service+1, "eServiceFactoryXine");
+#else
+#warning xine not available
+#endif
diff --git a/lib/service/servicexine.h b/lib/service/servicexine.h
new file mode 100644 (file)
index 0000000..4a50b11
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef __servicemp3_h
+#define __servicemp3_h
+
+#define HAVE_XINE
+#ifdef HAVE_XINE
+#include <lib/base/message.h>
+#include <lib/service/iservice.h>
+
+#include <xine.h>
+#include <xine/xineutils.h>
+
+class eStaticServiceXineInfo;
+
+class eServiceFactoryXine: public iServiceHandler
+{
+DECLARE_REF(eServiceFactoryXine);
+public:
+       eServiceFactoryXine();
+       virtual ~eServiceFactoryXine();
+       enum { id = 0x1010 };
+
+               // iServiceHandler
+       RESULT play(const eServiceReference &, ePtr<iPlayableService> &ptr);
+       RESULT record(const eServiceReference &, ePtr<iRecordableService> &ptr);
+       RESULT list(const eServiceReference &, ePtr<iListableService> &ptr);
+       RESULT info(const eServiceReference &, ePtr<iStaticServiceInformation> &ptr);
+       RESULT offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr);
+private:
+       ePtr<eStaticServiceXineInfo> m_service_info;
+};
+
+class eStaticServiceXineInfo: public iStaticServiceInformation
+{
+       DECLARE_REF(eStaticServiceXineInfo);
+       friend class eServiceFactoryXine;
+       eStaticServiceXineInfo();
+public:
+       RESULT getName(const eServiceReference &ref, std::string &name);
+       int getLength(const eServiceReference &ref);
+};
+
+typedef struct _GstElement GstElement;
+
+class eServiceXine: public iPlayableService, public iPauseableService, 
+       public iServiceInformation, public iSeekableService, public Object
+{
+DECLARE_REF(eServiceXine);
+public:
+       virtual ~eServiceXine();
+
+               // iPlayableService
+       RESULT connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection);
+       RESULT start();
+       RESULT stop();
+       RESULT setTarget(int target);
+       
+       RESULT pause(ePtr<iPauseableService> &ptr);
+       RESULT setSlowMotion(int ratio);
+       RESULT setFastForward(int ratio);
+
+       RESULT seek(ePtr<iSeekableService> &ptr);
+
+               // not implemented (yet)
+       RESULT audioChannel(ePtr<iAudioChannelSelection> &ptr) { ptr = 0; return -1; }
+       RESULT audioTracks(ePtr<iAudioTrackSelection> &ptr) { ptr = 0; return -1; }
+       RESULT frontendInfo(ePtr<iFrontendInformation> &ptr) { ptr = 0; return -1; }
+       RESULT subServices(ePtr<iSubserviceList> &ptr) { ptr = 0; return -1; }
+       RESULT timeshift(ePtr<iTimeshiftService> &ptr) { ptr = 0; return -1; }
+       RESULT cueSheet(ePtr<iCueSheet> &ptr) { ptr = 0; return -1; }
+       RESULT subtitle(ePtr<iSubtitleOutput> &ptr) { ptr = 0; return -1; }
+       RESULT audioDelay(ePtr<iAudioDelay> &ptr) { ptr = 0; return -1; }
+       RESULT radioText(ePtr<iRadioText> &ptr) { ptr = 0; return -1; }
+
+               // iPausableService
+       RESULT pause();
+       RESULT unpause();
+       
+       RESULT info(ePtr<iServiceInformation>&);
+       
+               // iSeekableService
+       RESULT getLength(pts_t &SWIG_OUTPUT);
+       RESULT seekTo(pts_t to);
+       RESULT seekRelative(int direction, pts_t to);
+       RESULT getPlayPosition(pts_t &SWIG_OUTPUT);
+       RESULT setTrickmode(int trick);
+       RESULT isCurrentlySeekable();
+       
+               // iServiceInformation
+       RESULT getName(std::string &name);
+       int getInfo(int w);
+       std::string getInfoString(int w);
+private:
+       friend class eServiceFactoryXine;
+       std::string m_filename;
+       eServiceXine(const char *filename);     
+       Signal2<void,iPlayableService*,int> m_event;
+
+       xine_stream_t *stream;
+       xine_video_port_t *vo_port;
+       xine_audio_port_t *ao_port;
+       xine_event_queue_t *event_queue;
+
+       enum
+       {
+               stError, stIdle, stRunning, stStopped,
+       };
+       int m_state;
+       
+       static void eventListenerWrap(void *user_data, const xine_event_t *event);
+       void eventListener(const xine_event_t *event);
+       
+
+       eFixedMessagePump<int> m_pump;
+};
+#endif
+
+#endif