hxplayercontrol.cpp

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

CPP
1,296
字号
/*************************************************************************** *   Copyright (C) 2006 Paul Cifarelli <paul@cifarelli.net>              * *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * ***************************************************************************//*************************************************************************** basically this implements a rudamentary rpc mechanism so the we can have each player in a separate process.  this is solely done to implement a  reliable crossfade (or more precicely, put the crossfade in the hands of  the alsa guys ***************************************************************************/#include <sys/time.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <iostream>#include <sys/mman.h>using namespace std;#include "hxplayercontrol.h"class HSPPlayerControlled : public HelixSimplePlayer{public:   HSPPlayerControlled(PlayerControl *pcntl, int index) : m_pcntl(pcntl), m_index(index) {}   virtual ~HSPPlayerControlled() {}   virtual void notifyUser(unsigned long code, const char *moreinfo, const char *moreinfourl);   virtual void interruptUser(unsigned long code, const char *moreinfo, const char *moreinfourl);   virtual void onContacting(const char *host);   virtual void onBuffering(int percentage);private:   PlayerControl *m_pcntl;   int            m_index;};void HSPPlayerControlled::notifyUser(unsigned long code, const char *moreinfo, const char *moreinfourl){   m_pcntl->sendnotifyuser(code, moreinfo, moreinfourl);}void HSPPlayerControlled::interruptUser(unsigned long code, const char *moreinfo, const char *moreinfourl){   m_pcntl->sendinterruptuser(code, moreinfo, moreinfourl);}void HSPPlayerControlled::onContacting(const char *host){   m_pcntl->sendcontacting(host);}void HSPPlayerControlled::onBuffering(int percentage){   m_pcntl->sendbuffering(percentage);}PlayerControl::PlayerControl() : m_eq_enabled(false), m_preamp(0), m_err(0), iamparent(0), m_index(0), nNumPlayers(0),                                 m_inited(false), m_api( HelixSimplePlayer::OSS ), m_device(0), mimehead(0), mimelistlen(0),                                 m_numPlugins(0), m_pluginInfo(0){   memset(m_children, 0, sizeof(m_children));}PlayerControl::~PlayerControl(){   tearDown();   print2stderr("In PlayerControl::~PlayerControl(), m_index=%d\n", m_index);   delete m_device;   if (pmapped)      munmap(pmapped, sizeof(stateStuff) * 2);}// init functionsvoid PlayerControl::init(const char *corelibpath, const char *pluginslibpath, const char *codecspath, int numPlayers){   int err;   iamparent = 0;   nNumPlayers = numPlayers;   m_err = 0;   print2stderr("In PlayerControl::init(), m_api=%d, m_device=%s\n", m_api, m_device ? m_device : "DEVICE NOT SET");   if (numPlayers > 2) // it's impossible   {      m_err = -1;      return;   }   memset(&m_children, 0, numPlayers * sizeof(struct playerChildren));   m_inited = false;   // create a shared memory region for state like stuff   if ( MAP_FAILED == (pmapped = (stateStuff *) mmap( (void *) statestuff,                                                       sizeof(stateStuff) * 2,                                                       PROT_READ | PROT_WRITE,#ifdef __linux__                                                      MAP_SHARED | MAP_ANONYMOUS,#else                                                      MAP_SHARED | MAP_ANON,#endif                                                      -1, 0)) )      pmapped = 0;         // we do this the old fashioned way, so that we don't have to include an executable with our plugin...   for (int i = 0; i < numPlayers; i++)   {      if (pmapped)      {         m_children[i].current_time = &(pmapped[i].current_time);         m_children[i].duration = &(pmapped[i].duration);         m_children[i].md = &(pmapped[i].md);         m_children[i].m_current = &(pmapped[i].m_current);         m_children[i].m_consumed = &(pmapped[i].m_consumed);         //m_children[i].q = pmapped[i].q;         //for (int j=0; j<NUM_SCOPEBUFS; j++)         //{         //   m_children[i].q[j].allocd = false;         //   m_children[i].q[j].buf = pmapped[i].b[j];         //}      }      err = pipe(m_children[i].m_pipeA);      err |= pipe(m_children[i].m_pipeB);      if ( !err && (iamparent = fork()) )      {         // parent         print2stderr("%%%%%% parent initializes player %d\n", i);         // parent's m_pid remains 0         m_children[i].m_pid = iamparent;         close(m_children[i].m_pipeA[1]); // parent uses A for reading         close(m_children[i].m_pipeB[0]); // and B for writing      }      else if (!err)      {         // child         cerr << "%%%%%% child initializes as player " << i << endl;;         m_index = i; // child's index is saved         close(m_children[i].m_pipeA[0]); // child uses A for writing         close(m_children[i].m_pipeB[1]); // and B for reading         break;      }   }   if (!iamparent) // children stay here, parents return   {      int rfd = m_children[m_index].m_pipeB[0];      int wfd = m_children[m_index].m_pipeA[1];      int n;      struct timeval timeout;      HSPPlayerControlled *player = 0;      bool playing = false;      player = new HSPPlayerControlled(this, m_index);      timeout.tv_sec = 0;      timeout.tv_usec = 10000;      fd_set rdset, wrset;      FD_ZERO(&rdset);      FD_ZERO(&wrset);      FD_SET(rfd, &rdset);      FD_SET(wfd, &wrset); // really should check to see if we can write, but not gonna      while ( 1 )      {         FD_SET(rfd, &rdset);         n = select(rfd + 1, &rdset, 0, 0, &timeout);         if ( FD_ISSET(rfd, &rdset) )         {            msgid m;            unsigned char buf[65536];            int sz = 0;            if (getmessage(rfd, m, buf, sz) && player)            {               switch (m)               {                  case INIT:                     cerr << "INIT\n";                     if (!sz)                     {                        player->setOutputSink(m_api);                        if (m_device)                           player->setDevice(m_device);                        player->init(corelibpath, pluginslibpath, codecspath, 1);                        m_inited = true;                        if (!m_index) // only player 0 need send the mime and plugin stuff                        {                           sendplugins(wfd, player);                           sendmimetypes(wfd, player);                        }                        cerr << "%%%%%% player " << m_index << " child sends ready\n";                        sendready(wfd);                     }                     else                        cerr << "CHILD " << m_index << " sz not right in INIT, sz=" << sz << endl;                     break;                  case SETURL:                  {                     bool islocal = (bool) buf[0];                     int len = strlen((const char *)&buf[1]); // not that this would prevent a crash...                     if (m_inited)                     {                        cerr << "CHILD " << m_index << " setURL for " << (const char *)&buf[1] <<                            ",islocal=" << islocal << ",len=" << len << endl;                        if (sz == len + 2)                            player->setURL((const char *)&buf[1], 0, islocal); // remember, we sent the null...                        else                           cerr << "CHILD " << m_index << " sz not right in SETURL, sz=" << sz << endl;                     }                  }                  break;                  case START:                  {                     bool fadein = (bool) buf[0];                     unsigned long fadetime;                     if (m_inited)                     {                        if (pmapped)                           *m_children[m_index].current_time = 0;                        if (sz == sizeof(unsigned long) + 1)                        {                           cerr << "CHILD " << m_index << " gets START\n";                           memcpy((void *)&fadetime, (void *)&buf[1], sizeof(unsigned long));                           playing = true;                           player->start(0, fadein, fadetime);                        }                        else                           cerr << "CHILD " << m_index << " sz not right in START, sz=" << sz << endl;                     }                  }                  break;                  case STOP:                     if (m_inited)                        if (!sz)                        {                           player->stop();                           playing = false;                           cerr << "CHILD " << m_index << " gets STOP\n";                        }                        else                           cerr << "CHILD " << m_index << " sz not right in STOP, sz=" << sz << endl;                     break;                  case PAUSE:                     if (m_inited)                        if (!sz)                           player->pause();                        else                           cerr << "CHILD " << m_index << " sz not right in PAUSE, sz=" << sz << endl;                     break;                  case RESUME:                     if (m_inited)                        if (!sz)                           player->resume();                        else                           cerr << "CHILD " << m_index << " sz not right in RESUME, sz=" << sz << endl;                     break;                  case SEEK:                     if (m_inited)                        if (sz == sizeof(unsigned long))                        {                           unsigned long pos;                           memcpy( (void *) &pos, (void *) buf, sizeof(unsigned long) );                           if (pos < player->duration(0))                              player->seek(pos, 0);                        }                        else                           cerr << "CHILD " << m_index << " sz not right in SEEK, sz=" << sz << endl;                     break;                  case SETVOLUME:                  {                     if (m_inited)                        if (sz == sizeof(unsigned long))                        {                           memcpy( (void *) &m_volume, (void *) buf, sizeof(unsigned long));                           cerr << "CHILD: received setvolume request " << m_volume <<endl;;                           player->setVolume(m_volume);                        }                        else                           cerr << "CHILD " << m_index << " sz not right in SETVOLUME, sz=" << sz << endl;                  }                  break;                  case OUTPUTSINK:                     if (m_inited)                        if (sz == 1)                        {                           m_api = (HelixSimplePlayer::AUDIOAPI) buf[0];                           cerr << "CHILD: received OUTPUTSINK: " << m_api <<endl;;                        }                        else                           cerr << "CHILD " << m_index << " sz not right in OUTPUTSINK, sz=" << sz << endl;                     break;                  case DEVICE:                  {                     char* dev = strdup((const char*) buf);                     if (m_inited)                        if ((unsigned)sz == strlen(dev) + 1)                        {                           cerr << "CHILD " << m_index << " gets device " << dev << endl;                           setDevice( dev );                        }                        else                           cerr << "CHILD " << m_index << " sz not right in DEVICE, sz=" << sz << endl;                     free(dev);                  }                  break;                  case SETFADE:                  {                     if (m_inited)                        if (sz == sizeof(unsigned long) + 1)                        {                           bool fadeout;                           unsigned long fadelength;                           fadeout = (bool) buf[0];                           memcpy((void *) &fadelength, (void *) &buf[1], sizeof(unsigned long));                           player->setFadeout(fadeout, fadelength, 0);                        }                        else                           cerr << "CHILD " << m_index << " sz not right in SETFADE, sz=" << sz << endl;                  }                  break;                  case ENABLEEQ:                  {                     if (m_inited)                        if (sz == 1)                        {                           m_eq_enabled = (bool) buf[0];                           player->enableEQ(m_eq_enabled);                           cerr << "CHILD " << m_index << " enables EQ\n";                        }                        else                           cerr << "CHILD " << m_index << " sz not right in ENABLEEQ, sz=" << sz << endl;                  }                  break;                  case UPDATEEQGAINS:                  {                     int i, n, k;                     cerr << "UPDATEGAINS\n";                     if (m_inited)                     {                        if (sz >= 2)                        {                           memcpy( (void *) &m_preamp, (void *) buf, sizeof(m_preamp) );                           memcpy( (void *) &n, (void *) &buf[ sizeof(m_preamp) ], sizeof(int) );                           player->m_preamp = m_preamp;                        }                        else                           cerr << "CHILD " << m_index << " sz not right in UPDATEEQGAINS, sz=" << sz << endl;                        if ((unsigned)sz == sizeof(m_preamp) + sizeof(int) + n * sizeof(int))                        {                           if (n > 0)                           {                              m_equalizerGains.resize(n);                              cerr << "CHILD " << m_index << " receives " << n << " equalizer gains\n";                              for (i=0; i<n; i++)                              {                                 memcpy( (void *) &k, (void *) &buf[ sizeof(m_preamp) + (i+1)*sizeof(int) ], sizeof(int) );                                 m_equalizerGains[i] = k;                              }                              player->m_equalizerGains = m_equalizerGains;                              if (!m_eq_enabled)                                 player->enableEQ(true);                              player->updateEQgains();                              player->enableEQ(m_eq_enabled);                           }                        }                        else                           cerr << "CHILD " << m_index << " sz not right in UPDATEEQGAINS, sz=" << sz << endl;                     }                  }                  break;                  case SCOPECLEAR:                     if (m_inited)                     {                        player->clearScopeQ(0);                        if (pmapped)                           *m_children[m_index].m_consumed = *m_children[m_index].m_current = 0;                     }                     break;                  case TEARDOWN:                     if (!sz)                     {                        cerr << "CHILD: " << m_index << " received shutdown request\n";                        player->stop(0);                        delete player;                        raise(15);                        exit(0);                     }                     else                        cerr << "CHILD " << m_index << " sz not right in TEARDOWN, sz=" << sz << endl;                     break;                  default: // send an error to the parent                        cerr << "CHILD " << m_index << " received unhandled message, sz=" << sz << endl;                     break;               }            }            else            {               cerr << "CHILD " << m_index << " gets EOD\n";               break;            }         }         if (m_inited)         {            player->dispatch();            if (playing && player->done(0))            {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?