From: Felix Domke Date: Mon, 2 Oct 2006 02:20:56 +0000 (+0000) Subject: alternative media decoder based on libxine X-Git-Tag: 2.6.0~3029 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/809c14e3d31fab1d4224412cbfaa3c475a8f1808?hp=6ea51518b9a6196dea58078ac37ba084f7068202 alternative media decoder based on libxine --- diff --git a/lib/service/servicexine.cpp b/lib/service/servicexine.cpp new file mode 100644 index 00000000..b2ef7f7f --- /dev/null +++ b/lib/service/servicexine.cpp @@ -0,0 +1,358 @@ +#define HAVE_XINE +#ifdef HAVE_XINE + +/* yes, it's xine, not Xine. But eServicexine looks odd. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static xine_t *xine; /* TODO: move this into a static class */ + +// eServiceFactoryXine + +eServiceFactoryXine::eServiceFactoryXine() +{ + ePtr sc; + + eServiceCenter::getPrivInstance(sc); + if (sc) + sc->addServiceFactory(eServiceFactoryXine::id, this); + + m_service_info = new eStaticServiceXineInfo(); +} + +eServiceFactoryXine::~eServiceFactoryXine() +{ + ePtr sc; + + eServiceCenter::getPrivInstance(sc); + if (sc) + sc->removeServiceFactory(eServiceFactoryXine::id); +} + +DEFINE_REF(eServiceFactoryXine) + + // iServiceHandler +RESULT eServiceFactoryXine::play(const eServiceReference &ref, ePtr &ptr) +{ + // check resources... + ptr = new eServiceXine(ref.path.c_str()); + return 0; +} + +RESULT eServiceFactoryXine::record(const eServiceReference &ref, ePtr &ptr) +{ + ptr=0; + return -1; +} + +RESULT eServiceFactoryXine::list(const eServiceReference &, ePtr &ptr) +{ + ptr=0; + return -1; +} + +RESULT eServiceFactoryXine::info(const eServiceReference &ref, ePtr &ptr) +{ + ptr = m_service_info; + return 0; +} + +RESULT eServiceFactoryXine::offlineOperations(const eServiceReference &, ePtr &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 &event, ePtr &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 &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 &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&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 init_eXine(eAutoInitNumbers::service, "libxine"); +eAutoInitPtr 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 index 00000000..4a50b11f --- /dev/null +++ b/lib/service/servicexine.h @@ -0,0 +1,117 @@ +#ifndef __servicemp3_h +#define __servicemp3_h + +#define HAVE_XINE +#ifdef HAVE_XINE +#include +#include + +#include +#include + +class eStaticServiceXineInfo; + +class eServiceFactoryXine: public iServiceHandler +{ +DECLARE_REF(eServiceFactoryXine); +public: + eServiceFactoryXine(); + virtual ~eServiceFactoryXine(); + enum { id = 0x1010 }; + + // iServiceHandler + RESULT play(const eServiceReference &, ePtr &ptr); + RESULT record(const eServiceReference &, ePtr &ptr); + RESULT list(const eServiceReference &, ePtr &ptr); + RESULT info(const eServiceReference &, ePtr &ptr); + RESULT offlineOperations(const eServiceReference &, ePtr &ptr); +private: + ePtr 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 &event, ePtr &connection); + RESULT start(); + RESULT stop(); + RESULT setTarget(int target); + + RESULT pause(ePtr &ptr); + RESULT setSlowMotion(int ratio); + RESULT setFastForward(int ratio); + + RESULT seek(ePtr &ptr); + + // not implemented (yet) + RESULT audioChannel(ePtr &ptr) { ptr = 0; return -1; } + RESULT audioTracks(ePtr &ptr) { ptr = 0; return -1; } + RESULT frontendInfo(ePtr &ptr) { ptr = 0; return -1; } + RESULT subServices(ePtr &ptr) { ptr = 0; return -1; } + RESULT timeshift(ePtr &ptr) { ptr = 0; return -1; } + RESULT cueSheet(ePtr &ptr) { ptr = 0; return -1; } + RESULT subtitle(ePtr &ptr) { ptr = 0; return -1; } + RESULT audioDelay(ePtr &ptr) { ptr = 0; return -1; } + RESULT radioText(ePtr &ptr) { ptr = 0; return -1; } + + // iPausableService + RESULT pause(); + RESULT unpause(); + + RESULT info(ePtr&); + + // 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 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 m_pump; +}; +#endif + +#endif