helix-sp.cpp

来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 2,109 行 · 第 1/4 页

CPP
2,109
字号
/* ********** * * 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 + =
减小字号Ctrl + -
显示快捷键?