?? helix-sp.cpp
字號:
/* ********** * * This software is released under the provisions of the GPL version 2. * see file "COPYING". If that file is not available, the full statement * of the license can be found at * * http://www.fsf.org/licensing/licenses/gpl.txt * * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. * Portions Copyright (c) Paul Cifarelli 2005 * * ********** */#include <stdlib.h>#include <stdarg.h>#include "hxcomm.h"#include "hxcore.h"#include "hxclsnk.h"#include "hxerror.h"#include "hxauth.h"#include "hxprefs.h"#include "hxstrutl.h"#include "hxvsrc.h"#include "hxresult.h"#include "hxplugn.h"#include "hspadvisesink.h"#include "hsperror.h"#include "hspauthmgr.h"#include "hspcontext.h"#include <X11/Xlib.h>#include <dlfcn.h>#include <errno.h>#include <fcntl.h>#include <sys/ioctl.h>#include "hxausvc.h"#include "dllpath.h"#include <config.h>#include "helix-sp.h"#include "hspvoladvise.h"#include "utils.h"#include "hsphook.h"#include "hxfiles.h"#ifdef USE_HELIX_ALSA#include <alsa/asoundlib.h>#include "hspalsadevice.h"#endif#ifdef HX_LOG_SUBSYSTEM#include "hxtlogutil.h"#endif#ifdef __FreeBSD__#define PTHREAD_MUTEX_FAST_NP PTHREAD_MUTEX_NORMAL#endif#if !defined(__NetBSD__) && !defined(__OpenBSD__) #include <sys/soundcard.h>#else #include <soundcard.h>#endiftypedef HX_RESULT (HXEXPORT_PTR FPRMSETDLLACCESSPATH) (const char*);class HelixSimplePlayerAudioStreamInfoResponse : public IHXAudioStreamInfoResponse{public: HelixSimplePlayerAudioStreamInfoResponse(HelixSimplePlayer *player, int playerIndex) : m_Player(player), m_index(playerIndex), m_lRefCount(0) {} virtual ~HelixSimplePlayerAudioStreamInfoResponse() {} /* * IUnknown methods */ STDMETHOD(QueryInterface) (THIS_ REFIID riid, void** ppvObj); STDMETHOD_(ULONG32,AddRef) (THIS); STDMETHOD_(ULONG32,Release) (THIS); /* * IHXAudioStreamInfoResponse methods */ STDMETHOD(OnStream) (THIS_ IHXAudioStream *pAudioStream );private: HelixSimplePlayer *m_Player; IHXAudioStream *m_Stream; int m_index; LONG32 m_lRefCount; HXAudioFormat m_audiofmt;};STDMETHODIMPHelixSimplePlayerAudioStreamInfoResponse::QueryInterface(REFIID riid, void**ppvObj){ if(IsEqualIID(riid, IID_IUnknown)) { AddRef(); *ppvObj = (IUnknown*)(IHXAudioStreamInfoResponse *)this; return HXR_OK; } else if(IsEqualIID(riid, IID_IHXAudioStreamInfoResponse)) { AddRef(); *ppvObj = (IHXAudioStreamInfoResponse*)this; return HXR_OK; } *ppvObj = NULL; return HXR_NOINTERFACE;}STDMETHODIMP_(UINT32)HelixSimplePlayerAudioStreamInfoResponse::AddRef(){ return InterlockedIncrement(&m_lRefCount);}STDMETHODIMP_(UINT32)HelixSimplePlayerAudioStreamInfoResponse::Release(){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return 0;}STDMETHODIMP HelixSimplePlayerAudioStreamInfoResponse::OnStream(IHXAudioStream *pAudioStream){ m_Player->print2stderr("Stream Added on player %d, stream duration %ld, sources %d\n", m_index, m_Player->duration(m_index), m_Player->ppctrl[m_index]->pPlayer->GetSourceCount()); m_Player->ppctrl[m_index]->pStream = pAudioStream; m_Player->ppctrl[m_index]->pPreMixHook = new HSPPreMixAudioHook(m_Player, m_index, pAudioStream, m_Player->ppctrl[m_index]->bFadeIn, m_Player->ppctrl[m_index]->ulFadeLength); // addpremixhook adds another ref pAudioStream->AddPreMixHook(m_Player->ppctrl[m_index]->pPreMixHook, false); m_Player->ppctrl[m_index]->pPreMixHook->Release(); // release the ref added in the premixhook constructor m_Player->ppctrl[m_index]->bStarting = false; return HXR_OK;}// Constantsconst int DEFAULT_TIME_DELTA = 2000;const int DEFAULT_STOP_TIME = -1;const int SLEEP_TIME = 10;const int GUID_LEN = 64;// *** IUnknown methods ***/////////////////////////////////////////////////////////////////////////// Method:// IUnknown::QueryInterface// Purpose:// Implement this to export the interfaces supported by your// object.//STDMETHODIMP HelixSimplePlayerVolumeAdvice::QueryInterface(REFIID riid, void** ppvObj){ if (IsEqualIID(riid, IID_IUnknown)) { AddRef(); *ppvObj = (IUnknown*)(IHXClientAdviseSink*)this; return HXR_OK; } else if (IsEqualIID(riid, IID_IHXVolumeAdviseSink)) { AddRef(); *ppvObj = (IHXVolumeAdviseSink*)this; return HXR_OK; } *ppvObj = NULL; return HXR_NOINTERFACE;}/////////////////////////////////////////////////////////////////////////// Method:// IUnknown::AddRef// Purpose:// Everyone usually implements this the same... feel free to use// this implementation.//STDMETHODIMP_(ULONG32) HelixSimplePlayerVolumeAdvice::AddRef(){ return InterlockedIncrement(&m_lRefCount);}/////////////////////////////////////////////////////////////////////////// Method:// IUnknown::Release// Purpose:// Everyone usually implements this the same... feel free to use// this implementation.//STDMETHODIMP_(ULONG32) HelixSimplePlayerVolumeAdvice::Release(){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return 0;}STDMETHODIMP HelixSimplePlayerVolumeAdvice::OnVolumeChange(const UINT16 /*uVolume*/){ m_Player->onVolumeChange(m_index);#ifdef HELIX_SW_VOLUME_INTERFACE m_Player->ppctrl[m_index]->volume = uVolume;#endif return HXR_OK;}STDMETHODIMP HelixSimplePlayerVolumeAdvice::OnMuteChange(const BOOL bMute){ m_Player->onMuteChange(m_index); m_Player->ppctrl[m_index]->ismute = bMute; return HXR_OK;}int HelixSimplePlayer::print2stdout(const char *fmt, ...){ va_list args; char buf[1024]; va_start(args, fmt); int ret = vsprintf(buf, fmt, args); std::cout << buf; va_end(args); return ret;}int HelixSimplePlayer::print2stderr(const char *fmt, ...){ va_list args; char buf[1024]; va_start(args, fmt); int ret = vsprintf(buf, fmt, args); std::cerr << buf; va_end(args); return ret;}void HelixSimplePlayer::setFadeout(bool fadeout, unsigned long fadelength, int playerIndex ){ if (playerIndex == ALL_PLAYERS) { for (int i = 0; i<nNumPlayers; i++) setFadeout(fadeout, fadelength, i); } else { if (playerIndex >=0 && playerIndex < nNumPlayers && ppctrl[playerIndex]->pPreMixHook) { ppctrl[playerIndex]->ulFadeLength = fadelength; ((HSPPreMixAudioHook *)ppctrl[playerIndex]->pPreMixHook)->setFadelength(ppctrl[playerIndex]->ulFadeLength); ((HSPPreMixAudioHook *)ppctrl[playerIndex]->pPreMixHook)->setFadeout(fadeout); } }}void HelixSimplePlayer::cleanUpStream(int playerIndex){ //print2stderr("CLEANUPSTREAM\n"); stop(playerIndex);}void HelixSimplePlayer::updateEQgains(){ for (int i = 0; i<nNumPlayers; i++) if (pFinalAudioHook && isEQenabled()) ((HSPFinalAudioHook *)pFinalAudioHook)->updateEQgains(m_preamp, m_equalizerGains);}/* * handle one event */void HelixSimplePlayer::DoEvent(){ struct _HXxEvent *pNothing = 0x0; struct timeval mtime; mtime.tv_sec = 0; mtime.tv_usec = SLEEP_TIME * 1000; usleep(SLEEP_TIME*1000); pEngine->EventOccurred(pNothing);}/* * handle events for at most nTimeDelta milliseconds */void HelixSimplePlayer::DoEvents(int){ DoEvent();}/* * return the number of milliseconds since the epoch */UINT32 HelixSimplePlayer::GetTime(){ timeval t; gettimeofday(&t, NULL); // FIXME: // the fact that the result is bigger than a UINT32 is really irrelevant; // we can still play a stream for many many years... return (UINT32)((t.tv_sec * 1000) + (t.tv_usec / 1000));}char* HelixSimplePlayer::RemoveWrappingQuotes(char* str){ int len = strlen(str); if (len > 0) { if (str[len-1] == '"') str[--len] = 0; if (str[0] == '"') {int i = 0; do { str[i] = str[i+1]; ++i; } while(--len); } } return str;}HelixSimplePlayer::HelixSimplePlayer() : theErr(HXR_FAILED), pErrorSink(NULL), pErrorSinkControl(NULL), pPluginE(0), pPlugin2Handler(0), ppctrl(NULL), bURLFound(false), nNumPlayers(0), nNumPlayRepeats(1), nTimeDelta(DEFAULT_TIME_DELTA), nStopTime(DEFAULT_STOP_TIME), bStopTime(true), bStopping(false), nPlay(0), bEnableAdviceSink(false), bEnableVerboseMode(false), pEngine(NULL), pEngineContext(NULL), m_pszUsername(NULL), m_pszPassword(NULL), m_pszGUIDFile(NULL), m_pszGUIDList(NULL), m_Error(0), m_ulNumSecondsPlayed(0), mimehead(0), mimelistlen(0), m_preamp(0), m_outputsink(OSS), m_device(0),#ifdef USE_HELIX_ALSA m_direct(ALSA), // TODO: out why my alsa direct HW reader doesn't pickup changes in kmix (the whole purpose of this!)#else m_direct(OSS),#endif m_AlsaCapableCore(false), m_nDevID(-1), m_pAlsaMixerHandle(NULL), m_pAlsaMasterMixerElem(NULL), m_pAlsaPCMMixerElem(NULL), m_alsaDevice("default"), m_urlchanged(0), m_volBefore(-1), m_volAtStart(-1), m_MvolBefore(-1), m_MvolAtStart(-1){ pthread_mutexattr_t ma; pthread_mutexattr_init(&ma); pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_FAST_NP); // note this is not portable outside linux and a few others pthread_mutex_init(&m_engine_m, &ma);}void HelixSimplePlayer::init(const char *corelibhome, const char *pluginslibhome, const char *codecshome, int numPlayers){ int i; theErr = HXR_OK; FPRMCREATEENGINE fpCreateEngine; FPRMSETDLLACCESSPATH fpSetDLLAccessPath; SafeSprintf(mCoreLibPath, MAX_PATH, "%s/%s", corelibhome, "clntcore.so"); // Allocate arrays to keep track of players and client // context pointers ppctrl = new struct playerCtrl *[MAX_PLAYERS]; memset(ppctrl, 0, sizeof(struct playerCtrl *) * MAX_PLAYERS); if (!ppctrl) { print2stderr("Error: Out of Memory.\n"); theErr = HXR_UNEXPECTED; return; } fpCreateEngine = NULL; // prepare/load the HXCore module //print2stdout("Simpleplayer is looking for the client core at %s\n", mCoreLibPath ); core_handle = dlopen(mCoreLibPath, RTLD_LAZY | RTLD_GLOBAL); if (!core_handle) { print2stderr("splayer: failed to open corelib, errno %d\n", errno); theErr = HXR_FAILED; return; } fpCreateEngine = (FPRMCREATEENGINE) dlsym(core_handle, "CreateEngine"); fpSetDLLAccessPath = (FPRMSETDLLACCESSPATH) dlsym(core_handle, "SetDLLAccessPath"); if (fpCreateEngine == NULL || fpSetDLLAccessPath == NULL ) { theErr = HXR_FAILED; return; } //Now tell the client core where to find the plugins and codecs it //will be searching for. if (NULL != fpSetDLLAccessPath) { //Create a null delimited, double-null terminated string //containing the paths to the encnet library (DT_Common) and //the sdpplin library (DT_Plugins)... char pPaths[256]; /* Flawfinder: ignore */ char* pPathNextPosition = pPaths; memset(pPaths, 0, 256); UINT32 ulBytesLeft = 256; char* pNextPath = new char[256]; memset(pNextPath, 0, 256); SafeSprintf(pNextPath, 256, "DT_Common=%s", corelibhome); //print2stderr("Common DLL path %s\n", pNextPath ); UINT32 ulBytesToCopy = strlen(pNextPath) + 1; if (ulBytesToCopy <= ulBytesLeft) { memcpy(pPathNextPosition, pNextPath, ulBytesToCopy); pPathNextPosition += ulBytesToCopy; ulBytesLeft -= ulBytesToCopy; } SafeSprintf(pNextPath, 256, "DT_Plugins=%s", pluginslibhome); //print2stderr("Plugin path %s\n", pNextPath ); ulBytesToCopy = strlen(pNextPath) + 1; if (ulBytesToCopy <= ulBytesLeft) { memcpy(pPathNextPosition, pNextPath, ulBytesToCopy); pPathNextPosition += ulBytesToCopy; ulBytesLeft -= ulBytesToCopy; } SafeSprintf(pNextPath, 256, "DT_Codecs=%s", codecshome); //print2stderr("Codec path %s\n", pNextPath ); ulBytesToCopy = strlen(pNextPath) + 1; if (ulBytesToCopy <= ulBytesLeft) { memcpy(pPathNextPosition, pNextPath, ulBytesToCopy); pPathNextPosition += ulBytesToCopy; ulBytesLeft -= ulBytesToCopy; *pPathNextPosition='\0'; } fpSetDLLAccessPath((char*)pPaths); HX_VECTOR_DELETE(pNextPath); } // create client engine if (HXR_OK != fpCreateEngine((IHXClientEngine**)&pEngine)) { theErr = HXR_FAILED; return; } pCommonClassFactory = 0; // get the common class factory pEngine->QueryInterface(IID_IHXCommonClassFactory, (void **) &pCommonClassFactory); if (!pCommonClassFactory) print2stderr("no CommonClassFactory\n"); // get the engine setup interface IHXClientEngineSetup *pEngineSetup = 0; pEngine->QueryInterface(IID_IHXClientEngineSetup, (void **) &pEngineSetup); if (!pEngineSetup) print2stderr("no engine setup interface\n"); else { pEngineContext = new HSPEngineContext(this, pCommonClassFactory); pEngineContext->AddRef();#ifdef HX_LOG_SUBSYSTEM HX_ENABLE_LOGGING(pEngineContext);#endif pEngineSetup->Setup(pEngineContext); pEngineSetup->Release();
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -