CPI_Player_CoDec_WinAmpPlugin.c
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:24k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////////////////////////
  2. #include "stdafx.h"
  3. #include "globals.h"
  4. #include "CPI_Player_CoDec.h"
  5. #include "CP_WinAmpStructs.h"
  6. #include "CPI_CircleBuffer.h"
  7. ////////////////////////////////////////////////////////////////////////////////
  8. //
  9. // This is the CoDec module - the basic idea is that the file will be opened and
  10. // data will be sucked through the CoDec via calls to CPI_CoDec__GetPCMBlock
  11. //
  12. //
  13. ////////////////////////////////////////////////////////////////////////////////
  14. ////////////////////////////////////////////////////////////////////////////////
  15. //
  16. //
  17. // Module functions
  18. void CPP_OMAPLG_Uninitialise(CPs_CoDecModule* pModule);
  19. BOOL CPP_OMAPLG_OpenFile(CPs_CoDecModule* pModule, const char* pcFilename, DWORD dwCookie, HWND hWndOwner);
  20. void CPP_OMAPLG_CloseFile(CPs_CoDecModule* pModule);
  21. void CPP_OMAPLG_Seek(CPs_CoDecModule* pModule, const int iNumerator, const int iDenominator);
  22. void CPP_OMAPLG_GetFileInfo(CPs_CoDecModule* pModule, CPs_FileInfo* pInfo);
  23. //
  24. BOOL CPP_OMAPLG_GetPCMBlock(CPs_CoDecModule* pModule, void* pBlock, DWORD* pdwBlockSize);
  25. int CPP_OMAPLG_GetCurrentPos_secs(CPs_CoDecModule* pModule);
  26. //
  27. ////////////////////////////////////////////////////////////////////////////////
  28. ////////////////////////////////////////////////////////////////////////////////
  29. // Dummy functions used by the in module (but we don't need 'em)
  30. void CP_Dummy_SAVSAInit(int maxlatency_in_ms, int srate) {}
  31. void CP_Dummy_SAVSADeInit() {}
  32. void CP_Dummy_SAAddPCMData(void *PCMData, int nch, int bps, int timestamp) {}
  33. int CP_Dummy_SAGetMode() { return 0; }
  34. void CP_Dummy_SAAdd(void *data, int timestamp, int csa) {}
  35. void CP_Dummy_VSAAddPCMData(void *PCMData, int nch, int bps, int timestamp) {}
  36. int CP_Dummy_VSAGetMode(int *specNch, int *waveNch) { return 0; }
  37. void CP_Dummy_VSAAdd(void *data, int timestamp) {}
  38. int CP_Dummy_dsp_isactive() { return 0; }
  39. int CP_Dummy_dsp_dosamples(short int *samples, int numsamples, int bps, int nch, int srate) { return 0; }
  40. //
  41. void CP_Dummy_VSASetInfo(int nch, int srate) {}
  42. int CP_Dummy_SetInfo(int bitrate, int srate, int stereo, int synched) { return 0; }
  43. //
  44. // Dummy output functions
  45. int CP_Dummy_Pause(int pause) { return 0; }
  46. void CP_Dummy_SetVolume(int volume) {}
  47. void CP_Dummy_SetPan(int pan) {}
  48. int CP_Dummy_GetOutputTime() { return 0; }
  49. int CP_Dummy_GetWrittenTime() { return 0; }
  50. ////////////////////////////////////////////////////////////////////////////////
  51. ////////////////////////////////////////////////////////////////////////////////
  52. //
  53. typedef struct __CPs_CoDec_WinAmpPlugin
  54. {
  55.     CP_PlugInModule* m_pFirstPlugIn;
  56.     CP_PlugInModule* m_pActivePluginModule;
  57.     HMODULE m_hModPlugin;
  58.     In_Module* m_pInModule;
  59.     BOOL m_bModuleIsPlaying;
  60.     Out_Module m_FakeOutModule;
  61. } CPs_CoDec_WinAmpPlugin;
  62. //
  63. ////////////////////////////////////////////////////////////////////////////////
  64. #define CIC_CIRCLE_DATABUFFER_SIZE 0x10000 //64Kb
  65. #define CIC_WAITTIMEOUT 2000 // 2Secs
  66. ////////////////////////////////////////////////////////////////////////////////
  67. // Callback interface (WinAmp doesn't "DO" cookies so we have to have this global
  68. // variable) - this means that we can only have one thread (the plugins prob aren't
  69. // thread safe anyhow) - but there we go!
  70. //
  71. struct CPs_OutputGlobalData
  72. {
  73.     CRITICAL_SECTION m_csGlobal;
  74.     BOOL m_bStreamIsComplete;
  75.     int m_iCurrentTime_ms;
  76.     // Stuff for the file information
  77.     HANDLE m_evtFileInfoValid;
  78.     CPs_FileInfo m_FileInfo;
  79.     // Stuff for the data buffer
  80.     CPs_CircleBuffer* m_pCBuffer;
  81.     HANDLE m_evtSeekComplete;
  82. } glb_OutputData;
  83. //
  84. //
  85. //
  86. int CP_OutPI_Open(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms)
  87. {
  88.     // returns >=0 on success, <0 on failure
  89.     // NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins.
  90.     //    ... so don't expect the max latency returned to be what you asked for.
  91.     // returns max latency in ms (0 for diskwriters, etc)
  92.     // bufferlenms and prebufferms must be in ms. 0 to use defaults.
  93.     // prebufferms must be <= bufferlenms
  94.     if(bitspersamp != 8 && bitspersamp != 16)
  95.     {
  96.         CP_TRACE0("Inappropriate stream type");
  97.         return -1;
  98.     }
  99.     if(numchannels != 1 && numchannels != 2)
  100.     {
  101.         CP_TRACE0("Inappropriate stream type");
  102.         return -1;
  103.     }
  104.     // Setup the global info struct
  105.     {
  106.         EnterCriticalSection(&glb_OutputData.m_csGlobal);
  107.         glb_OutputData.m_FileInfo.m_iFileLength_Secs = 0;
  108.         glb_OutputData.m_FileInfo.m_iBitRate_Kbs = 0;
  109.         glb_OutputData.m_FileInfo.m_iFreq_Hz = samplerate;
  110.         glb_OutputData.m_FileInfo.m_bStereo = (numchannels>1) ? TRUE : FALSE;
  111.         glb_OutputData.m_FileInfo.m_b16bit = (bitspersamp==16) ? TRUE : FALSE;
  112.         LeaveCriticalSection(&glb_OutputData.m_csGlobal);
  113.         SetEvent(glb_OutputData.m_evtFileInfoValid);
  114.     }
  115.     return 1;
  116. }
  117. //
  118. //
  119. //
  120. void CP_OutPI_Close()
  121. {
  122.     CP_TRACE0("CP_OutPI_Close");
  123.     EnterCriticalSection(&glb_OutputData.m_csGlobal);
  124.     if(glb_OutputData.m_pCBuffer)
  125.         glb_OutputData.m_pCBuffer->SetComplete(glb_OutputData.m_pCBuffer);
  126.     LeaveCriticalSection(&glb_OutputData.m_csGlobal);
  127. }
  128. //
  129. //
  130. //
  131. int CP_OutPI_CanWrite()
  132. {
  133.     int iNumBytesFree;
  134.     // returns number of bytes possible to write at a given time.
  135.     // Never will decrease unless you call Write (or Close, heh)
  136.     EnterCriticalSection(&glb_OutputData.m_csGlobal);
  137.     if(glb_OutputData.m_pCBuffer == NULL)
  138.         iNumBytesFree = 0xFFFFFFFF;
  139.     else
  140.         iNumBytesFree = glb_OutputData.m_pCBuffer->GetFreeSize(glb_OutputData.m_pCBuffer);
  141.     LeaveCriticalSection(&glb_OutputData.m_csGlobal);
  142.     return iNumBytesFree;
  143. }
  144. //
  145. //
  146. //
  147. int CP_OutPI_Write(char *buf, int len)
  148. {
  149.     // 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data.
  150.     // 1 returns not able to write (yet). Non-blocking, always.
  151.     if(len > CP_OutPI_CanWrite())
  152.         return 1;
  153.     EnterCriticalSection(&glb_OutputData.m_csGlobal);
  154.     if(glb_OutputData.m_pCBuffer)
  155.         glb_OutputData.m_pCBuffer->Write(glb_OutputData.m_pCBuffer, buf, len);
  156.     // Update the current time
  157.     {
  158.         int iBytesPerSample = (glb_OutputData.m_FileInfo.m_bStereo ? 2 : 1)
  159.                               << (glb_OutputData.m_FileInfo.m_b16bit ? 1 : 0);
  160.         glb_OutputData.m_iCurrentTime_ms += ((len / iBytesPerSample)*1000) / glb_OutputData.m_FileInfo.m_iFreq_Hz;
  161.     }
  162.     LeaveCriticalSection(&glb_OutputData.m_csGlobal);
  163.     return 0;
  164. }
  165. //
  166. //
  167. //
  168. void CP_OutPI_Flush(int iNewTime)
  169. {
  170.     EnterCriticalSection(&glb_OutputData.m_csGlobal);
  171.     if(glb_OutputData.m_pCBuffer)
  172.         glb_OutputData.m_pCBuffer->Flush(glb_OutputData.m_pCBuffer);
  173.     glb_OutputData.m_iCurrentTime_ms = iNewTime;
  174.     SetEvent(glb_OutputData.m_evtSeekComplete);
  175.     LeaveCriticalSection(&glb_OutputData.m_csGlobal);
  176. }
  177. //
  178. //
  179. //
  180. int CP_OutPI_IsPlaying()
  181. {
  182.     CP_TRACE0("CP_OutPI_IsPlaying");
  183.     EnterCriticalSection(&glb_OutputData.m_csGlobal);
  184.     if(glb_OutputData.m_pCBuffer)
  185.         glb_OutputData.m_pCBuffer->SetComplete(glb_OutputData.m_pCBuffer);
  186.     LeaveCriticalSection(&glb_OutputData.m_csGlobal);
  187.     return 0;
  188. }
  189. //
  190. //
  191. ////////////////////////////////////////////////////////////////////////////////
  192. #define CP_INVALIDCHARPOS -1
  193. typedef In_Module* (*wp_winampGetInModule2)();
  194. ////////////////////////////////////////////////////////////////////////////////
  195. //
  196. //
  197. //
  198. void ProbeWinAmpModule(CPs_CoDecModule* pCoDec, const char* pcModulePath)
  199. {
  200.     CPs_CoDec_WinAmpPlugin *pContext;
  201.     HMODULE hModPlugin;
  202.     wp_winampGetInModule2 pfnGetInModule;
  203.     In_Module* pInModule;
  204.     pContext = (CPs_CoDec_WinAmpPlugin*)pCoDec->m_pModuleCookie;
  205.     CP_CHECKOBJECT(pContext);
  206.     // Load plugin and get EP
  207.     hModPlugin = LoadLibrary(pcModulePath);
  208.     if(!hModPlugin)
  209.         return;
  210.     pfnGetInModule = (wp_winampGetInModule2)GetProcAddress(hModPlugin, "winampGetInModule2");
  211.     if(!pfnGetInModule)
  212.     {
  213.         FreeLibrary(hModPlugin);
  214.         return;
  215.     }
  216.     // Get the plug in descriptor
  217.     pInModule = pfnGetInModule();
  218.     // Skip modules that we cannot support
  219.     if(!pInModule->UsesOutputPlug)
  220.     {
  221.         CP_TRACE1(""%s" Cannot be supported (not an output user)", pcModulePath);
  222.         FreeLibrary(hModPlugin);
  223.         return;
  224.     }
  225.     // Get the extensions supported by this plugin
  226.     if(pInModule && pInModule->FileExtensions && pInModule->FileExtensions[0])
  227.     {
  228.         char* pExtensions = pInModule->FileExtensions;
  229.         CP_PlugInModule* pNewPlugInModule = (CP_PlugInModule*)malloc(sizeof(CP_PlugInModule));
  230.         // Create new plug in module and add it to our list
  231.         pNewPlugInModule->m_pNext = pContext->m_pFirstPlugIn;
  232.         STR_AllocSetString(&pNewPlugInModule->m_pcModuleName, pcModulePath, FALSE);
  233.         pContext->m_pFirstPlugIn = pNewPlugInModule;
  234.         // Attach etensions to this module
  235.         CP_TRACE1("Probing module: "%s"", pcModulePath);
  236.         while(*pExtensions)
  237.         {
  238.             char* pDescription = pExtensions + strlen(pExtensions) + 1;
  239.             CP_TRACE2("Extensions: "%s" type:"%s"", pExtensions, pDescription);
  240.             // The extensions are in the format EXT1;EXT2;EXT3  - split these and
  241.             // add them to the player's extension list
  242.             {
  243.                 char* pcExtensionCursor;
  244.                 char* pcLastExtensionStart = pExtensions;
  245.                 for(pcExtensionCursor = pExtensions; *pcExtensionCursor; pcExtensionCursor++)
  246.                 {
  247.                     // Look for an extension break
  248.                     if(*pcExtensionCursor == ';' && pcExtensionCursor != pcLastExtensionStart)
  249.                     {
  250.                         const int iExtensionLen = pcExtensionCursor - pcLastExtensionStart;
  251.                         char* pcExtensionCopy = (char*)malloc(iExtensionLen+1);
  252.                         memcpy(pcExtensionCopy, pcLastExtensionStart, iExtensionLen);
  253.                         pcExtensionCopy[iExtensionLen] = '';
  254.                         CPFA_AddFileAssociation(pCoDec, pcExtensionCopy, (DWORD)pNewPlugInModule);
  255.                         free(pcExtensionCopy);
  256.                         pcLastExtensionStart = pcExtensionCursor+1;
  257.                     }
  258.                 }
  259.                 // Add last extension
  260.                 if(*pcLastExtensionStart)
  261.                     CPFA_AddFileAssociation(pCoDec, pcLastExtensionStart, (DWORD)pNewPlugInModule);
  262.             }
  263.             // Move cursor to next extension set
  264.             pExtensions = pDescription + strlen(pDescription) + 1;
  265.         }
  266.     }
  267.     // Free plugin
  268.     FreeLibrary(hModPlugin);
  269. }
  270. //
  271. //
  272. //
  273. void AddWinAmpModulesInPath(CPs_CoDecModule* pCoDec, const char* pcFileInPath)
  274. {
  275.     WIN32_FIND_DATA finddata;
  276.     HANDLE hFileFind;
  277.     char pcModuleDirectory[MAX_PATH];
  278.     char pcSearchWildcard[MAX_PATH];
  279.     strcpy(pcModuleDirectory, pcFileInPath);
  280.     // Work out the module directory
  281.     {
  282.         int iLastSlashPos, iCharIDX;
  283.         iLastSlashPos = CP_INVALIDCHARPOS;
  284.         for(iCharIDX=0; pcModuleDirectory[iCharIDX]; iCharIDX++)
  285.         {
  286.             if(pcModuleDirectory[iCharIDX] == '\')
  287.                 iLastSlashPos = iCharIDX;
  288.         }
  289.         // We must exist in some kind of directory!!!
  290.         CP_ASSERT(iLastSlashPos != CP_INVALIDCHARPOS);
  291.         pcModuleDirectory[iLastSlashPos+1] = '';
  292.     }
  293.     // Setup wildcard
  294.     strcpy(pcSearchWildcard,pcModuleDirectory);
  295.     strcat(pcSearchWildcard, "in_*.dll");
  296.     // Load each module to find out the file extensions that it supports
  297.     // ProbeWinAmpModule will also produce a linked list of module names
  298.     // and assign them to the FileAssociation cookie
  299.     hFileFind = FindFirstFile(pcSearchWildcard, &finddata);
  300.     if(hFileFind != INVALID_HANDLE_VALUE)
  301.     {
  302.         do
  303.         {
  304.             char pcFullPath[MAX_PATH];
  305.             strcpy(pcFullPath,pcModuleDirectory);
  306.             strcat(pcFullPath, finddata.cFileName);
  307.             ProbeWinAmpModule(pCoDec, pcFullPath);
  308.         } while(FindNextFile(hFileFind, &finddata) != 0);
  309.         FindClose(hFileFind);
  310.     }
  311. }
  312. //
  313. //
  314. //
  315. void CP_InitialiseCodec_WinAmpPlugin(CPs_CoDecModule* pCoDec)
  316. {
  317.     CPs_CoDec_WinAmpPlugin *pContext;
  318.     // Setup functions
  319.     pCoDec->Uninitialise = CPP_OMAPLG_Uninitialise;
  320.     pCoDec->OpenFile = CPP_OMAPLG_OpenFile;
  321.     pCoDec->CloseFile = CPP_OMAPLG_CloseFile;
  322.     pCoDec->Seek = CPP_OMAPLG_Seek;
  323.     pCoDec->GetFileInfo = CPP_OMAPLG_GetFileInfo;
  324.     pCoDec->GetPCMBlock = CPP_OMAPLG_GetPCMBlock;
  325.     pCoDec->GetCurrentPos_secs = CPP_OMAPLG_GetCurrentPos_secs;
  326.     // Setup private data
  327.     pCoDec->m_pModuleCookie = malloc(sizeof(CPs_CoDec_WinAmpPlugin));
  328.     pContext = (CPs_CoDec_WinAmpPlugin*)pCoDec->m_pModuleCookie;
  329.     pContext->m_pFirstPlugIn = 0L;
  330.     pContext->m_pActivePluginModule = NULL;
  331.     pContext->m_hModPlugin = NULL;
  332.     pContext->m_pInModule = NULL;
  333.     pContext->m_bModuleIsPlaying = FALSE;
  334.     memset(&pContext->m_FakeOutModule, 0, sizeof(pContext->m_FakeOutModule));
  335.     pContext->m_FakeOutModule.version = OUT_VER;
  336.     pContext->m_FakeOutModule.Open = CP_OutPI_Open;
  337.     pContext->m_FakeOutModule.Close = CP_OutPI_Close;
  338.     pContext->m_FakeOutModule.Write = CP_OutPI_Write;
  339.     pContext->m_FakeOutModule.CanWrite = CP_OutPI_CanWrite;
  340.     pContext->m_FakeOutModule.IsPlaying = CP_OutPI_IsPlaying;
  341.     pContext->m_FakeOutModule.Flush = CP_OutPI_Flush;
  342.     pContext->m_FakeOutModule.Pause = CP_Dummy_Pause;
  343.     pContext->m_FakeOutModule.SetVolume = CP_Dummy_SetVolume;
  344.     pContext->m_FakeOutModule.SetPan = CP_Dummy_SetPan;
  345.     pContext->m_FakeOutModule.GetOutputTime = CP_Dummy_GetOutputTime;
  346.     pContext->m_FakeOutModule.GetWrittenTime = CP_Dummy_GetWrittenTime;
  347.     // Global data
  348.     InitializeCriticalSection(&glb_OutputData.m_csGlobal);
  349.     glb_OutputData.m_evtFileInfoValid = NULL;
  350.     memset(&glb_OutputData.m_FileInfo, 0, sizeof(glb_OutputData.m_FileInfo));
  351.     glb_OutputData.m_pCBuffer = NULL;
  352.     glb_OutputData.m_iCurrentTime_ms = 0;
  353.     glb_OutputData.m_evtSeekComplete = NULL;
  354.     CPFA_InitialiseFileAssociations(pCoDec);
  355.     // Look in the current directory for WinAmp plugins - these have the format
  356.     // in_*.dll
  357.     {
  358.         char pcCurrentModuleDirectory[MAX_PATH];
  359. main_get_program_path(GetModuleHandle(NULL), pcCurrentModuleDirectory, MAX_PATH);
  360.         AddWinAmpModulesInPath(pCoDec, pcCurrentModuleDirectory);
  361.     }
  362.     /*
  363.       Some plugins have problems running outside of the WinAmp directory - so we will only
  364.       use plugins from the current dir (until someone has inspiration!!) 
  365.     */
  366.     /*
  367.      // Try to track down the WinAmp plugins directory (and add them too)
  368.      {
  369.      LONG lResult;
  370.      HKEY hKeyWinAmp;
  371.      lResult = RegOpenKey(HKEY_CLASSES_ROOT,
  372.      "WinAmp.File\shell\open\command",
  373.      &hKeyWinAmp);
  374.      if(lResult == ERROR_SUCCESS)
  375.      {
  376.      char cWinAmpPath[255];
  377.      char* pcValue;
  378.      LONG iValueLen;
  379.      RegQueryValue(hKeyWinAmp, NULL, NULL, &iValueLen);
  380.      pcValue = (char*)malloc(iValueLen);
  381.      RegQueryValue(hKeyWinAmp, NULL, pcValue, &iValueLen);
  382.      if(sscanf(pcValue, ""%255[^"]", cWinAmpPath) == 1)
  383.      {
  384.      int iLastSlashPos, iCharIDX;
  385.      // Remove the WinAmp exe name
  386.      iLastSlashPos = CP_INVALIDCHARPOS;
  387.      for(iCharIDX=0; cWinAmpPath[iCharIDX]; iCharIDX++)
  388.      {
  389.      if(cWinAmpPath[iCharIDX] == '\')
  390.      iLastSlashPos = iCharIDX;
  391.      }
  392.      // We must exist in some kind of directory!!!
  393.      CP_ASSERT(iLastSlashPos != CP_INVALIDCHARPOS);
  394.      cWinAmpPath[iLastSlashPos+1] = '';
  395.      // Append the Plugins folder
  396.      strcat(cWinAmpPath, "Plugins\");
  397.      AddWinAmpModulesInPath(pCoDec, cWinAmpPath);
  398.      }
  399.      // Cleanup
  400.      free(pcValue);
  401.      RegCloseKey(hKeyWinAmp);
  402.      }
  403.      }
  404.     */
  405. }
  406. //
  407. //
  408. //
  409. void CPP_OMAPLG_Uninitialise(CPs_CoDecModule* pModule)
  410. {
  411.     CPs_CoDec_WinAmpPlugin *pContext = (CPs_CoDec_WinAmpPlugin*)pModule->m_pModuleCookie;
  412.     CP_PlugInModule* pPlugInCursor;
  413.     CP_PlugInModule* pPlugInCursor_Next;
  414.     CP_CHECKOBJECT(pContext);
  415.     // Cleanup plug in module list
  416.     pPlugInCursor_Next = NULL;
  417.     for(pPlugInCursor = pContext->m_pFirstPlugIn; pPlugInCursor; pPlugInCursor = pPlugInCursor_Next)
  418.     {
  419.         pPlugInCursor_Next = (CP_PlugInModule*)pPlugInCursor->m_pNext;
  420.         free(pPlugInCursor->m_pcModuleName);
  421.         free(pPlugInCursor);
  422.     }
  423.     // Global output data
  424.     DeleteCriticalSection(&glb_OutputData.m_csGlobal);
  425.     free(pContext);
  426.     CPFA_EmptyFileAssociations(pModule);
  427. }
  428. //
  429. //
  430. //
  431. void InitialiseGlobalData()
  432. {
  433.     EnterCriticalSection(&glb_OutputData.m_csGlobal);
  434.     // Stuff for the file information
  435.     CP_ASSERT(!glb_OutputData.m_evtFileInfoValid);
  436.     glb_OutputData.m_evtFileInfoValid = CreateEvent(NULL, TRUE, FALSE, NULL);
  437.     memset(&glb_OutputData.m_FileInfo, 0, sizeof(glb_OutputData.m_FileInfo));
  438.     // Stuff for the data buffer
  439.     CP_ASSERT(!glb_OutputData.m_pCBuffer);
  440.     glb_OutputData.m_pCBuffer = CP_CreateCircleBuffer(CIC_CIRCLE_DATABUFFER_SIZE);
  441.     glb_OutputData.m_iCurrentTime_ms = 0;
  442.     CP_ASSERT(!glb_OutputData.m_evtSeekComplete);
  443.     glb_OutputData.m_evtSeekComplete = CreateEvent(NULL, FALSE, FALSE, NULL);
  444.     LeaveCriticalSection(&glb_OutputData.m_csGlobal);
  445. }
  446. //
  447. //
  448. //
  449. void UnitialiseGlobalData()
  450. {
  451.     EnterCriticalSection(&glb_OutputData.m_csGlobal);
  452.     // Stuff for the file information
  453.     CP_ASSERT(glb_OutputData.m_evtFileInfoValid);
  454.     CloseHandle(glb_OutputData.m_evtFileInfoValid);
  455.     glb_OutputData.m_evtFileInfoValid = NULL;
  456.     // Stuff for the data buffer
  457.     CP_ASSERT(glb_OutputData.m_pCBuffer);
  458.     glb_OutputData.m_pCBuffer->Uninitialise(glb_OutputData.m_pCBuffer);
  459.     glb_OutputData.m_pCBuffer = NULL;
  460.     CP_ASSERT(glb_OutputData.m_evtSeekComplete);
  461.     CloseHandle(glb_OutputData.m_evtSeekComplete);
  462.     glb_OutputData.m_evtSeekComplete = NULL;
  463.     LeaveCriticalSection(&glb_OutputData.m_csGlobal);
  464. }
  465. //
  466. //
  467. //
  468. void CloseCurrentModule(CPs_CoDec_WinAmpPlugin *pContext)
  469. {
  470.     CP_CHECKOBJECT(pContext);
  471.     CP_ASSERT(pContext->m_pActivePluginModule);
  472.     CP_ASSERT(pContext->m_hModPlugin);
  473.     CP_ASSERT(pContext->m_pInModule);
  474.     CP_ASSERT(pContext->m_pInModule->Stop);
  475.     CP_ASSERT(pContext->m_pInModule->Quit);
  476.     CP_TRACE1("Free module: "%s"", pContext->m_pActivePluginModule->m_pcModuleName);
  477.     if(pContext->m_bModuleIsPlaying)
  478.         pContext->m_pInModule->Stop();
  479.     pContext->m_pInModule->Quit();
  480.     FreeLibrary(pContext->m_hModPlugin);
  481.     pContext->m_pActivePluginModule = NULL;
  482.     pContext->m_hModPlugin = NULL;
  483.     pContext->m_pInModule = NULL;
  484.     pContext->m_bModuleIsPlaying = FALSE;
  485. }
  486. //
  487. //
  488. //
  489. void SetupCurrentInputPluginModule(CPs_CoDec_WinAmpPlugin *pContext)
  490. {
  491.     CP_CHECKOBJECT(pContext);
  492.     CP_ASSERT(pContext->m_pActivePluginModule);
  493.     CP_ASSERT(pContext->m_hModPlugin);
  494.     CP_ASSERT(pContext->m_pInModule);
  495.     pContext->m_pInModule->hMainWindow = (HWND)0x2398;
  496.     pContext->m_pInModule->hDllInstance = pContext->m_hModPlugin;
  497.     // Setup functions
  498.     pContext->m_pInModule->SAVSAInit = CP_Dummy_SAVSAInit;
  499.     pContext->m_pInModule->SAVSADeInit = CP_Dummy_SAVSADeInit;
  500.     pContext->m_pInModule->SAAddPCMData = CP_Dummy_SAAddPCMData;
  501.     pContext->m_pInModule->SAGetMode = CP_Dummy_SAGetMode;
  502.     pContext->m_pInModule->SAAdd = CP_Dummy_SAAdd;
  503.     pContext->m_pInModule->VSAAddPCMData = CP_Dummy_VSAAddPCMData;
  504.     pContext->m_pInModule->VSAGetMode = CP_Dummy_VSAGetMode;
  505.     pContext->m_pInModule->VSAAdd = CP_Dummy_VSAAdd;
  506.     pContext->m_pInModule->dsp_isactive = CP_Dummy_dsp_isactive;
  507.     pContext->m_pInModule->dsp_dosamples = CP_Dummy_dsp_dosamples;
  508.     pContext->m_pInModule->VSASetInfo = CP_Dummy_VSASetInfo;
  509.     pContext->m_pInModule->SetInfo = CP_Dummy_SetInfo;
  510.     pContext->m_pInModule->outMod = &pContext->m_FakeOutModule;
  511. }
  512. //
  513. //
  514. //
  515. BOOL CPP_OMAPLG_OpenFile(CPs_CoDecModule* pModule, const char* pcFilename, DWORD dwCookie, HWND hWndOwner)
  516. {
  517.     CPs_CoDec_WinAmpPlugin *pContext = (CPs_CoDec_WinAmpPlugin*)pModule->m_pModuleCookie;
  518.     CP_PlugInModule* pSelectedPlugInModule = (CP_PlugInModule*)dwCookie;
  519.     int iError;
  520.     CP_CHECKOBJECT(pContext);
  521. if(!pSelectedPlugInModule) return FALSE;
  522.     // Open output module
  523.     {
  524.         // Module has changed
  525.         wp_winampGetInModule2 pfnGetInModule;
  526.         if(pContext->m_pActivePluginModule)
  527.             CloseCurrentModule(pContext);
  528.         // Load plugin and get EP
  529.         CP_TRACE1("Load module: "%s"", pSelectedPlugInModule->m_pcModuleName);
  530.         pContext->m_hModPlugin = LoadLibrary(pSelectedPlugInModule->m_pcModuleName);
  531.         if(!pContext->m_hModPlugin)
  532.             return FALSE;
  533.         pfnGetInModule = (wp_winampGetInModule2)GetProcAddress(pContext->m_hModPlugin, "winampGetInModule2");
  534.         if(!pfnGetInModule)
  535.         {
  536.             FreeLibrary(pContext->m_hModPlugin);
  537.             pContext->m_hModPlugin = NULL;
  538.             return FALSE;
  539.         }
  540.         pContext->m_pActivePluginModule = pSelectedPlugInModule;
  541.         pContext->m_pInModule = pfnGetInModule();
  542.         SetupCurrentInputPluginModule(pContext);
  543.         pContext->m_pInModule->Init();
  544.         InitialiseGlobalData();
  545.     }
  546.     iError = pContext->m_pInModule->Play(pcFilename);
  547.     if(iError != 0)
  548.     {
  549.         CP_TRACE1("**** Failed to open file: "%s"", pcFilename);
  550.         CloseCurrentModule(pContext);
  551.         UnitialiseGlobalData();
  552.         return FALSE;
  553.     }
  554.     pContext->m_bModuleIsPlaying = TRUE;
  555.     return TRUE; // Success
  556. }
  557. //
  558. //
  559. //
  560. void CPP_OMAPLG_CloseFile(CPs_CoDecModule* pModule)
  561. {
  562.     CPs_CoDec_WinAmpPlugin *pContext = (CPs_CoDec_WinAmpPlugin*)pModule->m_pModuleCookie;
  563.     CP_CHECKOBJECT(pContext);
  564.     UnitialiseGlobalData();
  565.     if(pContext->m_pActivePluginModule)
  566.         CloseCurrentModule(pContext);
  567. }
  568. //
  569. //
  570. //
  571. void CPP_OMAPLG_Seek(CPs_CoDecModule* pModule, const int iNumerator, const int iDenominator)
  572. {
  573.     CPs_CoDec_WinAmpPlugin *pContext = (CPs_CoDec_WinAmpPlugin*)pModule->m_pModuleCookie;
  574.     int iStreamLength_ms;
  575.     CP_CHECKOBJECT(pContext);
  576.     CP_ASSERT(pContext->m_pActivePluginModule);
  577.     iStreamLength_ms = pContext->m_pInModule->GetLength();
  578.     pContext->m_pInModule->SetOutputTime( (iNumerator*iStreamLength_ms) / iDenominator);
  579.     WaitForSingleObject(glb_OutputData.m_evtSeekComplete, CIC_WAITTIMEOUT);
  580. }
  581. //
  582. //
  583. //
  584. BOOL CPP_OMAPLG_GetPCMBlock(CPs_CoDecModule* pModule, void* _pBlock, DWORD* pdwBlockSize)
  585. {
  586.     CPs_CoDec_WinAmpPlugin *pContext = (CPs_CoDec_WinAmpPlugin*)pModule->m_pModuleCookie;
  587.     CP_CHECKOBJECT(pContext);
  588.     return glb_OutputData.m_pCBuffer->Read(glb_OutputData.m_pCBuffer, _pBlock, *pdwBlockSize, pdwBlockSize);
  589. }
  590. //
  591. //
  592. //
  593. void CPP_OMAPLG_GetFileInfo(CPs_CoDecModule* pModule, CPs_FileInfo* pInfo)
  594. {
  595.     CPs_CoDec_WinAmpPlugin *pContext = (CPs_CoDec_WinAmpPlugin*)pModule->m_pModuleCookie;
  596.     DWORD dwWaitResult;
  597.     CP_CHECKOBJECT(pContext);
  598.     CP_ASSERT(pContext->m_pActivePluginModule);
  599.     // Wait up to 1 second for the plugin to return the stream format - if it doesn't
  600.     // set the file info into something that we know will be unsupported
  601.     dwWaitResult = WaitForSingleObject(glb_OutputData.m_evtFileInfoValid, CIC_WAITTIMEOUT);
  602.     if(dwWaitResult == WAIT_OBJECT_0)
  603.     {
  604.         EnterCriticalSection(&glb_OutputData.m_csGlobal);
  605.         memcpy(pInfo, &glb_OutputData.m_FileInfo, sizeof(*pInfo));
  606.         LeaveCriticalSection(&glb_OutputData.m_csGlobal);
  607.     }
  608.     else
  609.     {
  610.         CP_TRACE0("Module did not respond in time - setting bogus stream params");
  611.         memset(pInfo, 0, sizeof(*pInfo));
  612.     }
  613.     pInfo->m_iFileLength_Secs = pContext->m_pInModule->GetLength() / 1000;
  614. }
  615. //
  616. //
  617. //
  618. int CPP_OMAPLG_GetCurrentPos_secs(CPs_CoDecModule* pModule)
  619. {
  620.     CPs_CoDec_WinAmpPlugin *pContext = (CPs_CoDec_WinAmpPlugin*)pModule->m_pModuleCookie;
  621.     int iCurrentPos_secs;
  622.     CP_CHECKOBJECT(pContext);
  623.     CP_ASSERT(pContext->m_pActivePluginModule);
  624.     EnterCriticalSection(&glb_OutputData.m_csGlobal);
  625.     iCurrentPos_secs = glb_OutputData.m_iCurrentTime_ms / 1000;
  626.     LeaveCriticalSection(&glb_OutputData.m_csGlobal);
  627.     return iCurrentPos_secs;
  628. }
  629. //
  630. //
  631. //