欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

soundcardpmo.cpp

freeamp有名的媒体播放器
CPP
第 1 页 / 共 2 页
字号:
/*____________________________________________________________________________
   
   FreeAmp - The Free MP3 Player

   Portions Copyright (C) 1998-1999 EMusic.com
   Portions Copyright (C) 1997 Jeff Tsay (ctsay@pasteur.eecs.berkeley.edu)

   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.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   
   $Id: soundcardpmo.cpp,v 1.59.2.2.2.1.2.2 2000/03/15 23:37:35 robert Exp $
____________________________________________________________________________*/

/* system headers */
#include <windows.h>
#include <winbase.h>
#include <stdlib.h>
#include <string.h>

/* project headers */
//#include "config.h"
#include "SoundCardPMO.h"
#include "eventdata.h"
#include "debug.h"

#define DB Debug_v("%s:%d", __FILE__, __LINE__);

#define MAXINT32 0x7FFFFFFF
const int iFramesPerHeader = 8;

Mutex *g_pHeaderMutex;

extern    "C"
{
   PhysicalMediaOutput *Initialize(FAContext *context)
   {
      return new SoundCardPMO(context);
   }
}

static void CALLBACK
MCICallBack(HWAVEOUT hwo, UINT msg, DWORD dwInstance,
            DWORD dwParam1, DWORD dwParam2)
{
   switch (msg)
   {
   case WOM_DONE:
      {
         LPWAVEHDR lpWaveHdr = (LPWAVEHDR) dwParam1;

         g_pHeaderMutex->Acquire();
         lpWaveHdr->dwUser = -((int)lpWaveHdr->dwUser);
         g_pHeaderMutex->Release();

         break;
      }
   }
}

SoundCardPMO::SoundCardPMO(FAContext *context) :
        PhysicalMediaOutput(context)
{
   MMRESULT mmresult = 0;
   Int32PropValue *pProp;
   HWND            hWnd;
   
   m_wfex = NULL;
   m_wavehdr_array = NULL;
   m_hwo = NULL;

   m_channels = 0;
   m_samples_per_second = 0;
   m_samples_per_frame = 0;
   m_hdr_size = 0;
   m_data_size = 0;
   m_initialized = false;
   m_pBufferThread = NULL;
   g_pHeaderMutex = new Mutex(); 
   m_iHead = 0;
   m_iTail = 0;
   m_iOffset = 0;
   m_iBaseTime = MAXINT32;
   m_iBytesPerSample = 0;
   m_num_headers = 0;

pBase = 0;
   
   if (!m_pBufferThread)
   {
      m_pBufferThread = Thread::CreateThread();
      assert(m_pBufferThread);
      m_pBufferThread->Create(SoundCardPMO::StartWorkerThread, this);
   }

   if (IsError(m_pContext->props->GetProperty("MainWindow", 
              (PropValue **)&pProp)))
      return;        
   else
      hWnd = (HWND)pProp->GetInt32();
   
   mmresult = mixerOpen(&m_hmixer, 0, (DWORD)hWnd, NULL, 
                        MIXER_OBJECTF_MIXER | CALLBACK_WINDOW);
   if (mmresult != MMSYSERR_NOERROR)
   {
       m_hmixer = NULL;
       m_pContext->log->Error("Cannot open Mixer device.");
   }    
   SetupVolumeControl();
}

SoundCardPMO::~SoundCardPMO()
{
   m_bExit = true;
   m_pSleepSem->Signal();
   m_pPauseSem->Signal();

   if (m_initialized)
   {
      mixerClose(m_hmixer);
      waveOutReset(m_hwo);

      for(int iLoop = 0; iLoop < m_num_headers; iLoop++)
      {
          if ((int)m_wavehdr_array[iLoop].dwUser < 0)
		  {
              waveOutUnprepareHeader(m_hwo, &m_wavehdr_array[iLoop], sizeof(WAVEHDR));
		  }
      }

      while (waveOutClose(m_hwo) == WAVERR_STILLPLAYING)
      {
         usleep(100000);
      }

      delete m_wavehdr_array;
      delete m_wfex;
   }
   if (m_pBufferThread)
   {
      m_pBufferThread->Join();
      delete m_pBufferThread;
   }
   if (g_pHeaderMutex)
   {
      delete g_pHeaderMutex;
      g_pHeaderMutex = NULL;
   }
}

bool SoundCardPMO::SetupVolumeControl(void)
{
	MIXERLINE mxl;
	MIXERCONTROL mxc;
	MIXERLINECONTROLS mxlc;
    
	m_oDstLineName = "";
	m_oVolumeControlName = "";

	if (m_hmixer == NULL)
		return FALSE;

	mxl.cbStruct = sizeof(MIXERLINE);
	mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
	if (mixerGetLineInfo((HMIXEROBJ)m_hmixer,
                         &mxl,
                         MIXER_OBJECTF_HMIXER |
                         MIXER_GETLINEINFOF_COMPONENTTYPE)
		!= MMSYSERR_NOERROR)
		return false;

	mxlc.cbStruct = sizeof(MIXERLINECONTROLS);
	mxlc.dwLineID = mxl.dwLineID;
	mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
	mxlc.cControls = 1;
	mxlc.cbmxctrl = sizeof(MIXERCONTROL);
	mxlc.pamxctrl = &mxc;

	if (mixerGetLineControls((HMIXEROBJ)m_hmixer,
		     				 &mxlc,
							 MIXER_OBJECTF_HMIXER |
							 MIXER_GETLINECONTROLSF_ONEBYTYPE)
		!= MMSYSERR_NOERROR)
		return false;

	// record dwControlID
	m_oDstLineName = mxl.szName;
	m_oVolumeControlName = mxc.szName;
	m_dwMinimum = mxc.Bounds.dwMinimum;
	m_dwMaximum = mxc.Bounds.dwMaximum;
	m_dwVolumeControlID = mxc.dwControlID;

	return TRUE;
}

int32 SoundCardPMO::GetVolume() 
{
	MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;
	MIXERCONTROLDETAILS mxcd;
    int                 ret;
    
	mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
	mxcd.dwControlID = m_dwVolumeControlID;
	mxcd.cChannels = 1;
	mxcd.cMultipleItems = 0;
	mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
	mxcd.paDetails = &mxcdVolume;
	ret = mixerGetControlDetails((HMIXEROBJ)m_hmixer,
								 &mxcd,
								 MIXER_OBJECTF_HMIXER |
								 MIXER_GETCONTROLDETAILSF_VALUE);
	if (ret != MMSYSERR_NOERROR)
		return false;

    return  (int)(((float)((mxcdVolume.dwValue - m_dwMinimum) * 100) /  
                  (float)(m_dwMaximum - m_dwMinimum)) + 0.5); 
}

void SoundCardPMO::SetVolume(int32 volume) 
{
    DWORD dwVal;
    
    dwVal = (volume * (m_dwMaximum - m_dwMinimum) / 100);

	MIXERCONTROLDETAILS_UNSIGNED mxcdVolume[2];
	MIXERCONTROLDETAILS mxcd;
    
    memcpy(&mxcdVolume[0], &dwVal, sizeof(MIXERCONTROLDETAILS_UNSIGNED));
    memcpy(&mxcdVolume[1], &dwVal, sizeof(MIXERCONTROLDETAILS_UNSIGNED));
    
	mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
	mxcd.dwControlID = m_dwVolumeControlID;
	mxcd.cChannels = 2;
	mxcd.cMultipleItems = 0;
	mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
	mxcd.paDetails = &mxcdVolume;
    
	mixerSetControlDetails((HMIXEROBJ)m_hmixer, &mxcd, 
                           MIXER_OBJECTF_HMIXER | 
                           MIXER_SETCONTROLDETAILSF_VALUE);
}

Error SoundCardPMO::Init(OutputInfo * info)
{
   Error           result = kError_UnknownErr;
   MMRESULT        mmresult = 0;
   Int32PropValue *pProp = NULL;

   m_channels = info->number_of_channels;
   m_samples_per_second = info->samples_per_second;
   m_samples_per_frame = info->samples_per_frame;
   m_data_size = info->max_buffer_size;

   m_iBytesPerSample = info->number_of_channels * (info->bits_per_sample / 8);

   m_num_headers = (m_pInputBuffer->GetBufferSize() / m_data_size) - 1;
   
   m_hdr_size = sizeof(WAVEHDR);

   m_wfex = new WAVEFORMATEX;

   m_wfex->wBitsPerSample = info->bits_per_sample;
   m_wfex->wFormatTag = WAVE_FORMAT_PCM;
   m_wfex->nChannels = (WORD) m_channels;
   m_wfex->nSamplesPerSec = info->samples_per_second;
   m_wfex->nBlockAlign = (info->bits_per_sample / 8) * m_channels;
   m_wfex->nAvgBytesPerSec = info->samples_per_second * m_wfex->nBlockAlign;
   m_wfex->cbSize = 0;

   mmresult = waveOutOpen(&m_hwo,
                          WAVE_MAPPER,
                          m_wfex,
                          (DWORD) MCICallBack,
                          NULL,
                          WAVE_ALLOWSYNC | CALLBACK_FUNCTION);

   if (mmresult == MMSYSERR_NOERROR)
   {
      result = kError_NoErr;
   }

   uint32    i;

   m_wavehdr_array = new WAVEHDR[m_num_headers];
   for (i = 0; i < m_num_headers; i++)
   {
      m_wavehdr_array[i].dwBufferLength = m_data_size;
      m_wavehdr_array[i].dwBytesRecorded = 0;
      m_wavehdr_array[i].dwUser = 0;   
      m_wavehdr_array[i].dwLoops = 0;
      m_wavehdr_array[i].dwFlags = NULL;
   }
   m_iBytesPerSample = info->number_of_channels * (info->bits_per_sample / 8);

   m_initialized = true;

   return result;
}

void SoundCardPMO::HandleTimeInfoEvent(PMOTimeInfoEvent *pEvent)
{
   MediaTimeInfoEvent *pmtpi;
   int32               hours, minutes, seconds;
   int                 iTotalTime = 0;
   MMTIME              sTime;

   if (m_iBaseTime == MAXINT32)
   {
       if (!pEvent)
          return;
          
       m_iBaseTime = (pEvent->GetFrameNumber() * m_samples_per_frame) / 
                      m_samples_per_second;

       sTime.wType = TIME_BYTES;
       if (waveOutGetPosition(m_hwo, &sTime, sizeof(sTime)) != MMSYSERR_NOERROR)
           return;
   
       m_iBaseTime -= (sTime.u.cb / (m_samples_per_second * m_iBytesPerSample));
   }

   if (m_samples_per_second <= 0)
      return;

   sTime.wType = TIME_BYTES;
   if (waveOutGetPosition(m_hwo, &sTime, sizeof(sTime)) != MMSYSERR_NOERROR)
       return;
   
   iTotalTime = (sTime.u.cb / (m_samples_per_second * m_iBytesPerSample)) +
                m_iBaseTime;
      
   hours = iTotalTime / 3600;
   minutes = (iTotalTime - 
                (hours * 3600)) / 60;
   seconds = iTotalTime - 
			    (hours * 3600) - 
			    (minutes * 60);

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

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

bool SoundCardPMO::WaitForDrain(void)
{
   unsigned iLoop, iNumHeadersPending = 0;

   for(; !m_bExit && !m_bPause; )

⌨️ 快捷键说明

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