⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alsapmo.cpp

📁 vc++ mp3 源码下载 使用vc写的mp3 播放器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
{
    m_iBaseTime = -1;

    PhysicalMediaOutput::Pause();
}

bool AlsaPMO::WaitForDrain(void)
{
   snd_pcm_playback_status_t ainfo;

   snd_pcm_playback_status(ai->handle,&ainfo);
   for(; !m_bExit && !m_bPause; )
   {
       snd_pcm_playback_status(ai->handle,&ainfo);
       if (ainfo.underrun || ainfo.queue  < ainfo.fragment_size)
       {
           return true;
       }
       WasteTime();
   }
   return false;
} 

void AlsaPMO::HandleTimeInfoEvent(PMOTimeInfoEvent *pEvent)
{
   MediaTimeInfoEvent *pmtpi;
   int32               hours, minutes, seconds;
   int                 iTotalTime = 0;
   snd_pcm_playback_status_t ainfo;
   long long           llStart, llEnd;

   if (m_iBaseTime < 0)
   {
       m_iBaseTime = (pEvent->GetFrameNumber() * 
                      myInfo->samples_per_frame) / 
                      myInfo->samples_per_second;
   }

   snd_pcm_playback_status(ai->handle,&ainfo);
   llEnd = ((long long)ainfo.time.tv_sec * 100) + 
           ((long long)ainfo.time.tv_usec / 10000);
   llStart = ((long long)ainfo.stime.tv_sec * 100) + 
             ((long long)ainfo.stime.tv_usec / 10000);
   iTotalTime = ((llEnd - llStart) / 100) + m_iBaseTime;

   iTotalTime %= 86400;

   hours = iTotalTime / 3600;
   minutes = (iTotalTime / 60) % 60;
   seconds = iTotalTime % 60;

   if (hours < 0  ||
       minutes < 0 || minutes > 59 || 
       seconds < 0 || seconds > 59)
      return;

   pmtpi = new MediaTimeInfoEvent(hours, minutes, seconds, 0, 
                                  iTotalTime, 0);
   m_pTarget->AcceptEvent(pmtpi);
}

void AlsaPMO::StartWorkerThread(void *pVoidBuffer)
{
   ((AlsaPMO*)pVoidBuffer)->WorkerThread();
}

void AlsaPMO::WorkerThread(void)
{
   void                      *pBuffer;
   Error                      eErr;
   size_t                     iRet;
   Event                     *pEvent;
   snd_pcm_playback_status_t  ainfo;

   // Don't do anything until resume is called.
   m_pPauseSem->Wait();

   // Sleep for a pre buffer period
   PreBuffer();

   // The following should be abstracted out into the general thread
   // classes:
#ifdef __linux__
   struct sched_param sParam;

   sParam.sched_priority = sched_get_priority_max(SCHED_OTHER);
   pthread_setschedparam(pthread_self(), SCHED_OTHER, &sParam);
#endif

   for(; !m_bExit;)
   {
      if (m_bPause)
      {
          m_pPauseSem->Wait();
          continue;
      }

      // Loop until we get an Init event from the LMC
      if (!m_properlyInitialized)
      {
          pEvent = ((EventBuffer *)m_pInputBuffer)->GetEvent();

          if (pEvent == NULL)
          {
              m_pLmc->Wake();
              WasteTime();

              continue;
          }

          if (pEvent->Type() == PMO_Init)
          {
              if (IsError(Init(((PMOInitEvent *)pEvent)->GetInfo())))
              {
                  delete pEvent;
                  break;
              }
          }
          delete pEvent;

          continue;
      }

      // Set up reading a block from the buffer. If not enough bytes are
      // available, sleep for a little while and try again.
      for(;;)
      {
          eErr = ((EventBuffer *)m_pInputBuffer)->BeginRead(pBuffer, 
                                                             m_iDataSize);
          if (eErr == kError_EndOfStream || eErr == kError_Interrupt)
             break;

          if (eErr == kError_NoDataAvail)
          {
              m_pLmc->Wake();

              WasteTime();
              continue;
          }

          // Is there an event pending that we need to take care of
          // before we play this block of samples?
          if (eErr == kError_EventPending)
          {
              pEvent = ((EventBuffer *)m_pInputBuffer)->GetEvent();

              if (pEvent->Type() == PMO_Init)
                  Init(((PMOInitEvent *)pEvent)->GetInfo());
    
              if (pEvent->Type() == PMO_Reset)
                  Reset(false);
    
              if (pEvent->Type() == PMO_Info) 
                  HandleTimeInfoEvent((PMOTimeInfoEvent *)pEvent);
    
              if (pEvent->Type() == PMO_Quit) 
              {
                  delete pEvent;
                  if (WaitForDrain())
                  {
                     Reset(true);
                     m_pTarget->AcceptEvent(new Event(INFO_DoneOutputting));
                  }
                  return;
              }
 
              delete pEvent;
    
              continue;
          }
          
          if (IsError(eErr))
          {
              ReportError("Internal error occured.");
              m_pContext->log->Error("Cannot read from buffer in PMO "
                                    "worker tread: %d\n", eErr);
              break;
          }
          break;
      }

      // Now write the block to the audio device. If the block doesn't
      // all fit, pause and loop until the entire block has been played.
      // This loop could be written using non-blocking io...
      for(;;)
      {
          if (m_bExit || m_bPause)
              break;

          iRet = snd_pcm_playback_status(ai->handle,&ainfo);
          if (ainfo.count < m_iDataSize)      
          {
              WasteTime();
              continue;
          }
          break;
      }        
      if (m_bExit || m_bPause)
      {
          m_pInputBuffer->EndRead(0);
          continue;
      }

      iRet = snd_pcm_write(ai->handle,pBuffer,m_iDataSize);
      if (iRet < 0)
      {
         m_pInputBuffer->EndRead(0);
         ReportError("Could not write sound data to the soundcard.");
         m_pContext->log->Error("Failed to write to the soundcard: %s\n", 
                               strerror(errno));
         break;
      }

      m_pInputBuffer->EndRead(iRet);
      m_pLmc->Wake();
      UpdateBufferStatus();
   }
}

int AlsaPMO::audio_set_all(struct audio_info_struct *ai)
{
        int err;

        if(ai->format == -1) {
#ifdef DEBUG
cout<<"AlsaPMO::audio_set_all:ai->format error"<<endl;
#endif
                return 0;
        }
        if(!ai || ai->rate < 0) {
#ifdef DEBUG
cout<<"AlsaPMO::audio_set_all:ai->rate error"<<endl;
#endif
                return -1;
        }
        if(ai->alsa_format.channels < 0) {
#ifdef DEBUG
cout<<"AlsaPMO::audio_set_all:ai->channels error"<<endl;
#endif
                return 0;
        }
#ifdef DEBUG
cout<<"AlsaPMO::audio_set_all: format="<<ai->format<<",rate="<<ai->rate<<",channels="<<ai->channels<<endl;
#endif

        switch(ai->format)
        {
                case AUDIO_FORMAT_SIGNED_16:
                default:
                        ai->alsa_format.format=SND_PCM_SFMT_S16_LE;
                        break;
                case AUDIO_FORMAT_UNSIGNED_8:
                        ai->alsa_format.format=SND_PCM_SFMT_U8;
                        break;
                case AUDIO_FORMAT_SIGNED_8:
                        ai->alsa_format.format=SND_PCM_SFMT_S8;
                        break;
                case AUDIO_FORMAT_ULAW_8:
                        ai->alsa_format.format=SND_PCM_SFMT_MU_LAW;
                        break;
                case AUDIO_FORMAT_ALAW_8:
                        ai->alsa_format.format=SND_PCM_SFMT_A_LAW;
                        break;
                case AUDIO_FORMAT_UNSIGNED_16:
                        ai->alsa_format.format=SND_PCM_SFMT_U16_LE;
                        break;
        }
//      ai->alsa_format.format=SND_PCM_SFMT_S16_LE;
        ai->alsa_format.rate=ai->rate;
        ai->alsa_format.channels = ai->channels;

        if((err=snd_pcm_playback_format(ai->handle, &ai->alsa_format)) < 0 ) {
//          ReportError("Cannot reset the soundcard.");
            ReportError("Cannot get audio format.");
            return (Error)pmoError_IOCTL_SNDCTL_DSP_RESET;
        }
//      audio_set_playback_params2(ai);
//      int err;
        snd_pcm_playback_info_t pi;
        snd_pcm_playback_params_t pp;

        if((err=snd_pcm_playback_info(ai->handle, &pi)) < 0 )
        {
                ReportError("Cannot get audio info.");
                return (Error)pmoError_ALSA_Playback_Info;
        }

        bzero(&pp, sizeof(pp));
        pp.fragment_size = pi.buffer_size/4;
        if ((unsigned)pp.fragment_size > pi.max_fragment_size) 
            pp.fragment_size = pi.max_fragment_size;
        if ((unsigned)pp.fragment_size < pi.min_fragment_size) 
            pp.fragment_size = pi.min_fragment_size;
        pp.fragments_max = -1;
        pp.fragments_room = 1;

        if((err=snd_pcm_playback_params(ai->handle, &pp)) < 0 )
        {
                ReportError("Cannot set audio params.");
                return (Error)pmoError_ALSA_Playback_Params;
        }
        return 0;
}

⌨️ 快捷键说明

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