Main Page   Alphabetical List   Compound List   File List   Compound Members   Related Pages  

AOut.cpp

00001 /*
00002 
00003 $Id: AOut.cpp,v 1.12 2001/08/21 18:40:38 robux4 Exp $ 
00004 
00005 
00006 $Log: AOut.cpp,v $
00007 Revision 1.12  2001/08/21 18:40:38  robux4
00008 Added for safe ID3v2 keeping and no overwrite
00009 
00010 Revision 1.11  2001/08/16 20:00:33  robux4
00011 Added the encoding DLL location in the abuot box
00012 
00013 Revision 1.10  2001/08/15 17:21:50  robux4
00014 Added force channel support
00015 
00016 Revision 1.9  2001/08/13 18:44:42  robux4
00017 Initial support for free borland compiler
00018 
00019 Revision 1.8  2001/08/11 10:20:24  robux4
00020 Dialog boxes now display the DLL version
00021 
00022 Revision 1.7  2001/08/01 19:40:16  robux4
00023 Updated with complete documentation support
00024 
00025 Revision 1.6  2001/07/31 18:50:53  robux4
00026 Moved the version handling in the ALameDLL class
00027 
00028 Revision 1.5  2001/07/27 16:38:49  robux4
00029 Unified the MessageBox handling
00030 
00031 Revision 1.3  2001/07/26 19:28:49  robux4
00032 Added CVS tags
00033  
00034 
00035 */
00036 
00037 #if !defined(STRICT)
00038 #define STRICT
00039 #endif // !defined(STRICT)
00040 
00041 #include <windows.h>
00042 #include <windowsx.h>
00043 #include <shellapi.h>
00044 #include <intshcut.h>
00045 #include <strstream>
00046 #include <algorithm>
00047 
00048 #include "resource.h"
00049 
00050 #include "AOut.h"
00051 
00052 /*
00053 #ifdef __alpha
00054 #define PI_VER " (AXP)"
00055 #else
00056 #define PI_VER " (x86)"
00057 #endif
00058 */
00059 
00060 /*
00061   \fn AboutProc
00062 */
00063 static BOOL CALLBACK AboutProc(
00064   HWND hwndDlg,  // handle to dialog box
00065   UINT uMsg,     // message
00066   WPARAM wParam, // first message parameter
00067   LPARAM lParam  // second message parameter
00068   )
00069 {
00070   static HBRUSH hBrushStatic;
00071   static LOGFONT lf;  // structure for font information  
00072   static HFONT hfnt;
00073   BOOL bResult;
00074   static HCURSOR hcOverCursor;
00075 
00076   switch (uMsg) {
00077 
00078     case WM_COMMAND:
00079       UINT command;
00080       command = GET_WM_COMMAND_ID(wParam, lParam);
00081       if ((IDOK == command) || (IDCANCEL == command))
00082       {
00083         ::DeleteObject(hfnt);
00084 
00085         ::EndDialog(hwndDlg, (IDOK == command));
00086       } 
00087       bResult = FALSE;
00088       break;
00089 
00090     case WM_INITDIALOG:
00091 
00092       ::GetObject(::GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf); 
00093       lf.lfUnderline = TRUE;
00094 
00095       hfnt = ::CreateFontIndirect(&lf);
00096 
00097       ::SendMessage(::GetDlgItem(hwndDlg,IDC_ABOUT_HOMEPAGE), WM_SETFONT, (WPARAM) hfnt, TRUE);
00098       ::SendMessage(::GetDlgItem(hwndDlg,IDC_ABOUT_BSD), WM_SETFONT, (WPARAM) hfnt, TRUE);
00099 
00100       ::SetDlgItemText(hwndDlg, IDC_ABOUT_VERSION, AOut::GetVersion());
00101 
00102       BE_VERSION  Version;
00103       if (AOut::GetLameVersion(&Version))
00104       {
00105 
00106         SetDlgItemText(hwndDlg, IDC_DLL_HOMEPAGE, Version.zHomepage);
00107 
00108         char toto[20];
00109         
00110         wsprintf(toto,"%u.%02u (%02u/%02u/%04u)",Version.byDLLMajorVersion, Version.byDLLMinorVersion, Version.byDay, Version.byMonth, Version.wYear);
00111         SetDlgItemText(hwndDlg, IDC_DLL_VERSION, toto);
00112 
00113         char titi[10];
00114         wsprintf(titi,"%u.%02u",Version.byMajorVersion, Version.byMinorVersion);
00115         ::SetDlgItemText(hwndDlg, IDC_DLL_ENGINE, titi);
00116 
00117         if (Version.byMMXEnabled)
00118           ::SetDlgItemText(hwndDlg, IDC_DLL_MMX, "MMX enabled");
00119         else
00120           ::SetDlgItemText(hwndDlg, IDC_DLL_MMX, "No MMX");
00121 
00122         ::SendMessage(::GetDlgItem(hwndDlg,IDC_DLL_HOMEPAGE), WM_SETFONT, (WPARAM) hfnt, TRUE);
00123 
00124         char output[MAX_PATH];
00125         if (!AOut::LameDLL().GetFullLocation(output,MAX_PATH) != 0)
00126         {
00127           ::LoadString(AOut::GetInstance(),IDS_STRING_PROMPT_REPLACE_CURRENT,output,MAX_PATH);
00128         }
00129         ::SetDlgItemText(hwndDlg, IDC_EDIT_ABOUT_DLL_LOCATION, output);
00130       }
00131       else
00132       {
00133         char output[MAX_PATH];
00134         ::LoadString(AOut::GetInstance(),IDS_STRING_ABOUT_DLL_NOT_FOUND,output,MAX_PATH);
00135         ::SetDlgItemText(hwndDlg, IDC_EDIT_ABOUT_DLL_LOCATION, output);
00136         ::SetDlgItemText(hwndDlg, IDC_DLL_HOMEPAGE, "");
00137         ::SetDlgItemText(hwndDlg, IDC_DLL_VERSION, "0.00");
00138         ::SetDlgItemText(hwndDlg, IDC_DLL_ENGINE, "0.00");
00139       }
00140 
00144       hBrushStatic = ::CreateSolidBrush(::GetSysColor (COLOR_BTNFACE));
00145 
00146       hcOverCursor = ::LoadCursor(NULL,(LPCTSTR)IDC_CROSS); 
00147 
00148       bResult = TRUE;
00149       break;
00150 
00151     case WM_CTLCOLORSTATIC:
00155       if ((HWND)lParam == ::GetDlgItem(hwndDlg,IDC_DLL_HOMEPAGE) ||
00156         (HWND)lParam == ::GetDlgItem(hwndDlg,IDC_ABOUT_HOMEPAGE) ||
00157         (HWND)lParam == ::GetDlgItem(hwndDlg,IDC_ABOUT_BSD))
00158       {
00159         ::SetTextColor((HDC)wParam, ::GetSysColor (COLOR_HIGHLIGHT));
00160         ::SetBkColor((HDC)wParam, ::GetSysColor (COLOR_BTNFACE));
00161 
00162         return (LRESULT) hBrushStatic;
00163       }
00164       else
00165         return (LRESULT) NULL;
00166 
00167     case WM_MOUSEMOVE:
00168       {
00169         POINT pnt;
00170         ::GetCursorPos(&pnt);
00171 
00172         RECT rctBSD;
00173         ::GetWindowRect( ::GetDlgItem(hwndDlg,IDC_ABOUT_BSD), &rctBSD);
00174 
00175         RECT rctDLLurl;
00176         ::GetWindowRect( ::GetDlgItem(hwndDlg,IDC_DLL_HOMEPAGE), &rctDLLurl);
00177 
00178         RECT rctMYurl;
00179         ::GetWindowRect( ::GetDlgItem(hwndDlg,IDC_ABOUT_HOMEPAGE), &rctMYurl);
00180 
00181         if (  ::PtInRect(&rctBSD,pnt) 
00182           || (::PtInRect(&rctDLLurl,pnt) && AOut::LameDLL().IsLoaded())
00183           || ::PtInRect(&rctMYurl,pnt) )
00184         {
00185           ::SetCursor(hcOverCursor);
00186         }
00187 
00188 
00189       }
00190       break;
00191 
00192     case WM_LBUTTONUP:
00193       {
00194         POINT pnt;
00195         ::GetCursorPos(&pnt);
00196 
00197         RECT rctBSD;
00198         ::GetWindowRect( ::GetDlgItem(hwndDlg,IDC_ABOUT_BSD), &rctBSD);
00199 
00200         RECT rctDLLurl;
00201         ::GetWindowRect( ::GetDlgItem(hwndDlg,IDC_DLL_HOMEPAGE), &rctDLLurl);
00202 
00203         RECT rctMYurl;
00204         ::GetWindowRect( ::GetDlgItem(hwndDlg,IDC_ABOUT_HOMEPAGE), &rctMYurl);
00205 
00206         TCHAR Url[200];
00207         bool bUrl = false;
00208         if (::PtInRect(&rctBSD,pnt))
00209         {
00210           ::LoadString(AOut::GetInstance(),IDS_STRING_BSD_LICENCE_URL,Url,200);
00211           bUrl = true;
00212         }
00213         else if (::PtInRect(&rctDLLurl,pnt) && AOut::LameDLL().IsLoaded())
00214         {
00215           ::GetWindowText(::GetDlgItem(hwndDlg,IDC_DLL_HOMEPAGE),Url,sizeof(Url));
00216           bUrl = true;
00217         }
00218         else if (::PtInRect(&rctMYurl,pnt))
00219         {
00220           ::GetWindowText(::GetDlgItem(hwndDlg,IDC_ABOUT_HOMEPAGE),Url,sizeof(Url));
00221           bUrl = true;
00222         }   
00223 
00224         if (bUrl)
00225         {
00226           LPSTR tmpStr;
00227           HRESULT hresult = ::TranslateURL(Url, TRANSLATEURL_FL_GUESS_PROTOCOL|TRANSLATEURL_FL_GUESS_PROTOCOL, &tmpStr);
00228           if (hresult == S_OK)
00229             ::ShellExecute(hwndDlg,"open",tmpStr,NULL,"",SW_SHOWMAXIMIZED );
00230           else if (hresult == S_FALSE)
00231             ::ShellExecute(hwndDlg,"open",Url,NULL,"",SW_SHOWMAXIMIZED );
00232         }
00233 
00234       }
00235       break;
00236 
00237     default:
00238       bResult = FALSE; // will be treated by DefWindowProc
00239   }
00240   return bResult;
00241 }
00242 
00244 // Variables
00246 
00249 
00253 static unsigned char Output[10000];
00254 
00255 AOut *         AOut::the_AOut = NULL;
00256 ADbg           AOut::the_Debug;
00257 DWORD          AOut::the_SamplesPerBlock;
00258 //char         * AOut::the_WorkingBuffer = NULL;
00259 char           AOut::the_WorkingBuffer[3000];
00260 char           the_TmpOutbufBuffer[3000];
00261 unsigned int   AOut::the_WorkingBufferUseSize = 0;
00262 DWORD          AOut::the_SamplesUsed = 0;
00263 DWORD          AOut::the_SamplesPerSec;
00264 DWORD          AOut::the_Channels;
00265 DWORD          AOut::the_MaxBuffer;
00266 HANDLE         AOut::the_OutputFile = INVALID_HANDLE_VALUE;
00267 ALameDLL       AOut::the_LameDLL;
00268 AEncodeProperties AOut::my_Properties;
00269 std::string    AOut::my_Filename = "";
00270 char           AOut::the_complete_name[31];
00271 char           AOut::the_version_name[10];
00272 #ifdef ENABLE_RAWOUTPUT
00273 static HANDLE the_RawOutputFile;
00274 #endif // ENABLE_RAWOUTPUT
00275 
00276 Out_Module AOut::the_Module = {
00277   OUT_VER,
00278   the_complete_name,
00279   44444,
00280   0, // hmainwindow
00281   0, // hdllinstance
00282   config,
00283   about,
00284   init,
00285   quit,
00286   open,
00287   close,
00288   write,
00289   canwrite,
00290   isplaying,
00291   pause,
00292   setvolume,
00293   setpan,
00294   flush,
00295   getoutputtime,
00296   getwrittentime
00297 };
00298 
00300 // Construction/Destruction
00302 
00303 AOut::AOut()
00304 {
00305   the_Debug.setPrefix("Winamp MP3 output");
00306 
00307   the_AOut = this;
00308 }
00309 
00310 AOut::~AOut()
00311 {
00312   the_AOut = NULL;
00313 }
00314 
00316 // Methods
00318 
00319 Out_Module * AOut::GetOutModule()
00320 {
00321   DWORD val, size = 0;
00322   char right_path[MAX_PATH];
00323 
00324   HMODULE htmp;
00325   htmp = LoadLibrary("plugins\\out_lame.dll");
00326   if (htmp == NULL)
00327   {
00328     htmp = LoadLibrary("out_lame.dll");
00329   }
00330   if (htmp != NULL)
00331   {
00332     ::GetModuleFileName(htmp, right_path, MAX_PATH);
00333     ::FreeLibrary(htmp);
00334 
00335     size = ::GetFileVersionInfoSize(right_path,&val);
00336   }
00337 
00338   bool bSet = false;
00339 
00340   if (size != 0)
00341   {
00342     HANDLE  hMem;
00343     char * tmpInfo;
00344 
00345     hMem = GlobalAlloc(GMEM_MOVEABLE, size);
00346     tmpInfo  = (char *)GlobalLock(hMem);
00347             
00348 
00349     if (tmpInfo != NULL)
00350     {
00351       ::GetFileVersionInfo( right_path, NULL, size, tmpInfo);
00352 
00353       unsigned int tmpSize;
00354       DWORD *infos;
00355       if (::VerQueryValue(tmpInfo, "\\VarFileInfo\\Translation", (LPVOID *)&infos, &tmpSize))
00356       {
00357         TCHAR tmpStr[100];
00358         TCHAR * version;
00359         wsprintf(tmpStr,"\\StringFileInfo\\%04X%04X\\ProductVersion",LOWORD(infos[0]),HIWORD(infos[0])); // first language : english ?
00360         ::VerQueryValue(tmpInfo, tmpStr, (LPVOID *)&version, &tmpSize);
00361         wsprintf(the_version_name,"%s",version);
00362         wsprintf(the_complete_name,"%s%s","Lame MP3 Writer plug-in v", version);
00363         bSet = true;
00364       }
00365     }
00366 
00367     if (tmpInfo != 0)
00368     {
00369       ::GlobalUnlock(hMem);
00370       ::GlobalFree(hMem);
00371     }
00372   }
00373   
00374   if (!bSet)
00375   {
00376     wsprintf(the_version_name,"%s","?.?.?");
00377     wsprintf(the_complete_name,"%s","Lame MP3 Writer plug-in");
00378   }
00379 
00380   return &the_Module;
00381 }
00382 
00383 void AOut::config(const HWND hwndParent) { 
00384   the_Debug.OutPut("config");
00385 
00386   my_Properties.Config(the_Module.hDllInstance, hwndParent);
00387 }
00388 
00389 void AOut::about(const HWND hwndParent) { 
00390   the_Debug.OutPut("about");
00391 
00392   ::DialogBox(the_Module.hDllInstance, MAKEINTRESOURCE(IDD_ABOUT), hwndParent, ::AboutProc);
00393 }
00394 
00395 void AOut::init() { 
00396   the_Debug.OutPut("init");
00397 
00398   my_Properties.ParamsRestore();
00399 }
00400 
00401 void AOut::quit() { 
00402   the_Debug.OutPut("quit");
00403 
00404   my_Properties.ParamsSave();
00405 }
00406 
00407 int  AOut::open(const int samplerate, const int numchannels, const int bitspersamp, const int bufferlenms, const int prebufferms)
00408 { 
00409   the_Debug.OutPut("open, samplerate = %d / numchannels = %d / bitspersamp =%d / bufferlenms = %d / prebufferms = %d", samplerate, numchannels, bitspersamp, bufferlenms, prebufferms);
00410 
00411   int result = -1;
00412 
00413   if (bitspersamp != 16) // only 16 bits supported at the moment
00414     return result;
00415 
00416   bool bDllLoaded;
00417 
00418   if (!the_LameDLL.IsLoaded())
00419   {
00420 
00421     bDllLoaded = the_LameDLL.Load(my_Properties.GetDllLocation());
00422 
00423   }
00424   else
00425     bDllLoaded = true;
00426 
00427   if (!bDllLoaded)
00428   {
00429     CloseHandle(the_OutputFile);
00430     the_OutputFile = INVALID_HANDLE_VALUE;
00431   }
00432   else
00433   {
00434     // for the given sampling freq/bitpersamp/bitrate (config)
00435     //  we must compute the max latency (it will be one frame -> 576/1152 samples)
00436 
00437     // Init the MP3 Stream
00438     BE_CONFIG beConfig;
00439     BE_ERR    err;
00440     
00441     memset(&beConfig,0,sizeof(beConfig));         // clear all fields
00442 
00443     // use the LAME config structure
00444     beConfig.dwConfig = BE_CONFIG_LAME;
00445 
00446     // this are the default settings for testcase.wav
00447     beConfig.format.LHV1.dwStructVersion  = 1;
00448     beConfig.format.LHV1.dwStructSize   = sizeof(beConfig);   
00449     beConfig.format.LHV1.dwSampleRate   = samplerate;             // INPUT FREQUENCY
00450 
00451     if (my_Properties.GetResampleMode())
00452       beConfig.format.LHV1.dwReSampleRate   = my_Properties.GetResampleFreq();  // RESAMPLE
00453     else
00454       beConfig.format.LHV1.dwReSampleRate   = 0;                // DON'T RESAMPLE
00455 
00456 the_Debug.OutPut("GetResampleMode = %s / GetResampleFreq = %d / dwReSampleRate = %d",my_Properties.GetResampleMode()?"TRUE":"FALSE",my_Properties.GetResampleFreq(),beConfig.format.LHV1.dwReSampleRate);
00457 
00458     if (my_Properties.GetForceChannelMode())
00459     {
00460       beConfig.format.LHV1.nMode      = my_Properties.GetChannelModeValue();  // OUTPUT IN DESIRED MODE
00461     }
00462     else
00463     {
00464       if (numchannels < 2)
00465         beConfig.format.LHV1.nMode      = BE_MP3_MODE_MONO;           // OUTPUT IN MONO
00466       else
00467       {
00468         if (my_Properties.GetChannelModeValue() == BE_MP3_MODE_MONO)
00469           beConfig.format.LHV1.nMode      = BE_MP3_MODE_STEREO; // force STEREO when Mono is selected
00470         else
00471           beConfig.format.LHV1.nMode      = my_Properties.GetChannelModeValue();  // OUTPUT IN DESIRED MODE
00472       }
00473     }
00474     
00475     if (beConfig.format.LHV1.dwReSampleRate == 0) // no resampling
00476     {
00477       if (samplerate < 32000)
00478         beConfig.format.LHV1.dwMpegVersion    = MPEG2;              // MPEG VERSION (I or II)
00479       else
00480         beConfig.format.LHV1.dwMpegVersion    = MPEG1;              // MPEG VERSION (I or II)
00481     }
00482     else
00483     {
00484       if (beConfig.format.LHV1.dwReSampleRate < 32000)
00485         beConfig.format.LHV1.dwMpegVersion    = MPEG2;              // MPEG VERSION (I or II)
00486       else
00487         beConfig.format.LHV1.dwMpegVersion    = MPEG1;              // MPEG VERSION (I or II)
00488     }
00489 
00490     int bitrateOK = my_Properties.GetBitrateValue(beConfig.format.LHV1.dwBitrate, beConfig.format.LHV1.dwMpegVersion);
00491 
00492     if (my_Properties.GetVBRUseMode())
00493     {
00494       // the VBR parameters are automatically
00495       bitrateOK = 0;
00496     }
00497 
00498     if (bitrateOK < 0)
00499     {
00500       TCHAR output[250];
00501       ::LoadString(GetInstance(),IDS_STRING_BITRATE_HIGH,output,250);
00502       AOut::MyMessageBox( output, MB_OK|MB_ICONEXCLAMATION);
00503 
00504       the_LameDLL.Free();
00505     }
00506     else if (bitrateOK > 0)
00507     {
00508       TCHAR output[250];
00509       ::LoadString(GetInstance(),IDS_STRING_BITRATE_SMALL,output,250);
00510       AOut::MyMessageBox( output, MB_OK|MB_ICONEXCLAMATION);
00511 
00512       the_LameDLL.Free();
00513     }
00514     else
00515     {
00516       // Get the current played file
00517       HWND hwndWinamp = FindWindow("Winamp v1.x",NULL);
00518 //#define IPC_GETLISTPOS       125
00519 //#define IPC_GETPLAYLISTFILE  211
00520 //#define IPC_GETPLAYLISTTITLE 212
00521       int index = SendMessage(hwndWinamp, WM_USER, 0, 125);
00522       char *name = (char *)SendMessage(hwndWinamp, WM_USER, index, 212);
00523 //      char *name = (char *)SendMessage(hwndWinamp, WM_USER, index, IPC_GETPLAYLISTFILE);
00524 
00525       std::string tmpFilename2 = name;
00526 
00527       // strip the known extensions
00528       std::string tmpCase = tmpFilename2;
00529       std::transform(tmpCase.begin(), tmpCase.end(), tmpCase.begin(), tolower);
00530       if (tmpCase.substr(tmpCase.length()-4).compare(".wav") == 0)
00531         tmpFilename2.erase( tmpFilename2.length()-4, 4);
00532       else if (tmpCase.substr(tmpCase.length()-4).compare(".mp3") == 0)
00533         tmpFilename2.erase( tmpFilename2.length()-4, 4);
00534 
00535       // replace forbidden chars
00536       replaceAllChar(tmpFilename2,'\\','-');
00537       replaceAllChar(tmpFilename2,'/','-');
00538       replaceAllChar(tmpFilename2,':','_');
00539       replaceAllChar(tmpFilename2,'*','x');
00540       replaceAllChar(tmpFilename2,'?','.');
00541       replaceAllChar(tmpFilename2,'"','\'');
00542       replaceAllChar(tmpFilename2,'<','.');
00543       replaceAllChar(tmpFilename2,'>','.');
00544       replaceAllChar(tmpFilename2,'|','_');
00545 
00546       const char * dir = my_Properties.GetOutputDirectory();
00547 
00548       std::string base_file;
00549 
00550       base_file = dir;
00551       if (dir[strlen(dir)-1] != '\\')
00552         base_file += '\\';
00553       base_file += tmpFilename2;
00554 
00555       
00556       my_Filename = base_file + ".mp3";
00557 
00558       the_OutputFile = CreateFile(my_Filename.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
00559 #ifdef ENABLE_RAWOUTPUT
00560       std::string tmpName = my_Filename + ".raw";
00561       the_RawOutputFile = CreateFile(tmpName.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
00562 #endif // ENABLE_RAWOUTPUT
00563       
00564       // no overwrite support
00565       if (the_OutputFile == INVALID_HANDLE_VALUE )
00566       {
00567         int i=0;
00568         base_file += "-";
00569         while (the_OutputFile == INVALID_HANDLE_VALUE && i < 1000 ) // over 1000 there must really be another problem
00570         {
00571           std::strstream sstream;
00572           std::string tmpStr;
00573           sstream << i;
00574           sstream >> tmpStr;
00575           my_Filename = base_file + tmpStr + ".mp3";;
00576           i++;
00577 
00578           the_OutputFile = CreateFile(my_Filename.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
00579         }
00580       }
00581 
00582       if (the_OutputFile == INVALID_HANDLE_VALUE)
00583       {
00584         the_LameDLL.Free();
00585       }
00586       else
00587       {
00588 
00589         beConfig.format.LHV1.nPreset      = my_Properties.GetPresetModeValue(); // QUALITY PRESET SETTING
00590 
00591         beConfig.format.LHV1.dwPsyModel     = 0;                  // USE DEFAULT PSYCHOACOUSTIC MODEL 
00592         beConfig.format.LHV1.dwEmphasis     = 0;                  // NO EMPHASIS TURNED ON
00593         beConfig.format.LHV1.bOriginal      = my_Properties.GetOriginalMode();    // SET ORIGINAL FLAG
00594         beConfig.format.LHV1.bCRC           = my_Properties.GetCRCMode();     // INSERT CRC
00595         beConfig.format.LHV1.bCopyright     = my_Properties.GetCopyrightMode();   // SET COPYRIGHT FLAG 
00596         beConfig.format.LHV1.bPrivate       = my_Properties.GetPrivateMode();   // SET PRIVATE FLAG
00597         beConfig.format.LHV1.bNoRes         = my_Properties.GetNoBiResMode();   // No Bit resorvoir
00598 
00599         // USE VBR
00600         beConfig.format.LHV1.bEnableVBR         = my_Properties.GetVBRValue( beConfig.format.LHV1.dwMaxBitrate,     // MAXIMUM BIT RATE
00601                                                                            beConfig.format.LHV1.nVBRQuality,      // SET VBR QUALITY
00602                                            beConfig.format.LHV1.bWriteVBRHeader,  // YES, WRITE THE XING VBR HEADER
00603                                            beConfig.format.LHV1.dwMpegVersion);
00604         
00605         err = the_LameDLL.InitStream(&beConfig, &the_SamplesPerBlock, &the_MaxBuffer);
00606 
00607         // Check result
00608         if(err != BE_ERR_SUCCESSFUL)
00609         {
00610           the_Debug.OutPut("Error opening encoding stream (%lu)", err);
00611           result = -1;
00612         }
00613         else
00614         {
00615           the_Debug.OutPut("Inited stream, the_SamplesPerBlock = %d (the_MaxBuffer = %d)", the_SamplesPerBlock, the_MaxBuffer);
00616 //          the_WorkingBuffer = new char[the_SamplesPerBlock];
00617           the_WorkingBufferUseSize = 0;
00618           the_SamplesUsed = 0;
00619           the_Channels = numchannels;
00620           the_SamplesPerSec = samplerate;
00621 
00622 //          result = 0;
00623           result =  the_SamplesPerBlock * 1000 / (the_SamplesPerSec * the_Channels);
00624 
00625 //#define IPC_GETPLAYLISTFILE  211
00626           name = (char *)SendMessage(hwndWinamp, WM_USER, index, 211);
00627 
00628           // save the ID3 information that should be at the beginning
00629           HANDLE input_file = ::CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
00630           if (input_file != INVALID_HANDLE_VALUE)
00631           {
00632             char Header[10];
00633             DWORD bytesRead;
00634             if (::ReadFile(input_file, Header, 10, &bytesRead, NULL) && bytesRead == 10)
00635             {
00636               // check if this is a valid ID3v2 tag
00637               if (   Header[0] == 'I'
00638                 && Header[1] == 'D'
00639                 && Header[2] == '3'
00640                 && Header[3] != 0xFF
00641                 && Header[4] != 0xFF
00642                 && Header[6] <  0x80
00643                 && Header[7] <  0x80
00644                 && Header[8] <  0x80
00645                 && Header[9] <  0x80)
00646               {
00647                 // seems to be a valid tag
00648                 // get the size
00649                 bool bFooter = (Header[5] & 0x10) == 0x10;
00650                 UINT32 TagSize = (Header[6] << 21) | (Header[7] << 14) | (Header[8] << 7) | Header[9];
00651                 TagSize += 10; // the header
00652 
00653                 if (bFooter)
00654                   TagSize += 10;
00655 
00656                 // save the data from the original file to the new one
00657                 DWORD bytesWritten;
00658                 UINT32 i;
00659                 ::SetFilePointer( input_file, 0, NULL, FILE_BEGIN );
00660                 for (i=TagSize;i>0;i -= bytesWritten)
00661                 {
00662                   if (!::ReadFile(input_file, Header, 10, &bytesRead, NULL))
00663                   {
00664                     break;
00665                   }
00666 
00667                   if (!::WriteFile( the_OutputFile, Header, (bytesRead>i?i:bytesRead), &bytesWritten, NULL)
00668                     || bytesWritten != (bytesRead>i?i:bytesRead))
00669                   {
00670                     break;
00671                   }
00672                 }
00673 
00674                 if (i != 0)
00675                 {
00676                   // there was a problem, forget that ID3 tag
00677                   ::SetFilePointer( the_OutputFile, 0, NULL, FILE_BEGIN );
00678                 }
00679               }
00680             }
00681             ::CloseHandle(input_file);
00682           }
00683         }
00684       }
00685     }
00686   }
00687 
00688   return result;
00689 }
00690 
00691 
00692 void AOut::close() {
00693   the_Debug.OutPut("close");
00694 
00695   DWORD EncodedSize = 0;
00696 
00697   // encode the remaining data
00698 //the_Debug.OutPut("the_WorkingBufferUseSize = %d",the_WorkingBufferUseSize);
00699   if (the_WorkingBufferUseSize != 0)
00700   {
00701     BE_ERR err = the_LameDLL.EncodeChunk(the_WorkingBufferUseSize / 2, (PSHORT)the_WorkingBuffer, (PBYTE)Output, &EncodedSize); // 2 for 16bits<->8bits
00702     if (err == BE_ERR_SUCCESSFUL)
00703     {
00704       do {
00705         DWORD BytesWritten;
00706         WriteFile(the_OutputFile, Output, EncodedSize, &BytesWritten , NULL); // TODO : better handling
00707 //the_Debug.OutPut("written %d bytes in file for %d byes encoded", BytesWritten, EncodedSize);
00708         EncodedSize -= BytesWritten;
00709       } while (EncodedSize != 0);
00710     }
00711   }
00712 
00713 
00714   the_LameDLL.DeinitStream( (PBYTE)Output, &EncodedSize);
00715 
00716   do {
00717     DWORD BytesWritten;
00718     WriteFile(the_OutputFile, Output, EncodedSize, &BytesWritten , NULL); // TODO : better handling
00719 //the_Debug.OutPut("written %d bytes in file for %d byes encoded", BytesWritten, EncodedSize);
00720     EncodedSize -= BytesWritten;
00721   } while (EncodedSize != 0);
00722 
00723   if (the_OutputFile != INVALID_HANDLE_VALUE)
00724     CloseHandle(the_OutputFile);
00725   the_OutputFile = INVALID_HANDLE_VALUE;
00726 #ifdef ENABLE_RAWOUTPUT
00727 CloseHandle(the_RawOutputFile);
00728 #endif // ENABLE_RAWOUTPUT
00729 
00730   if (my_Properties.GetVBRUseMode())
00731   {
00732     the_LameDLL.WriteVBRHeader(my_Filename.c_str());
00733   }
00734 
00735   my_Filename = "";
00736 
00737   the_LameDLL.CloseStream( );
00738 
00739   the_LameDLL.Free();
00740 
00741 //  if (the_WorkingBuffer != NULL)
00742 //    delete the_WorkingBuffer;
00743 //  the_WorkingBuffer = NULL;
00744   the_MaxBuffer = 0;
00745 }
00746 
00747 int  AOut::write(char *buf, const int len) {
00748   BE_ERR    err;
00749 
00750 DWORD EncodedSize = 0;
00751 
00752   char * OriginBuffer = buf;
00753   DWORD lenToUse = len;
00754 
00755   if (my_Properties.GetForceChannelMode())
00756   {
00757     assert(the_Channels == 1 || the_Channels == 2);
00758 
00759     if (the_Channels == 1)
00760     {
00761       if (my_Properties.GetChannelModeValue() != BE_MP3_MODE_MONO)
00762       {
00763         // turn mono into stereo
00764         assert(2*len <= sizeof(the_TmpOutbufBuffer)/sizeof(the_TmpOutbufBuffer[0]));
00765         OriginBuffer = the_TmpOutbufBuffer;
00766         UpMixToStereo( (SHORT*) buf, (SHORT*) OriginBuffer, len);
00767         lenToUse = len*2;
00768       }
00769     }
00770     else
00771     {
00772       if (my_Properties.GetChannelModeValue() == BE_MP3_MODE_MONO)
00773       {
00774           assert(len/2 <= sizeof(the_TmpOutbufBuffer)/sizeof(the_TmpOutbufBuffer[0]));
00775           OriginBuffer = the_TmpOutbufBuffer;
00776         // turn stereo into mono
00777         MixToMono( (SHORT*) buf, (SHORT*) OriginBuffer, len/2);
00778         lenToUse = len/2;
00779       }
00780     }
00781   }
00782 
00783 #ifdef ENABLE_RAWOUTPUT
00784 DWORD RawBytesWritten;
00785 WriteFile(the_RawOutputFile, OriginBuffer, lenToUse, &RawBytesWritten , NULL); // TODO : better handling
00786 #endif // ENABLE_RAWOUTPUT
00787 
00788 #ifndef DISABLE_MP3OUTPUT
00789   // we have to encode OriginBuffer which is lenToUse big
00790   // the data wiil be copied to the_WorkingBuffer to be the source encoding buffer
00791   // we will get the remaining data from the previous encoding
00792   // add enough data to get the_SamplesPerBlock samples
00793   // then, encode the_SamplesPerBlock samples each time
00794   // until we don't have enough data
00795 
00796   int TotalLen = lenToUse;
00797   while (lenToUse >= the_SamplesPerBlock) // 2 for 16bits<->8bits
00798   {
00799     // the_WorkingBuffer may have some remaining data from a block
00800     // fill the remaining part of the block to encode
00801     memcpy(&the_WorkingBuffer[the_WorkingBufferUseSize], &OriginBuffer[TotalLen - lenToUse], the_SamplesPerBlock - the_WorkingBufferUseSize); // 2 for 16bits<->8bits
00802 
00803     err = the_LameDLL.EncodeChunk(the_SamplesPerBlock / 2, (PSHORT)the_WorkingBuffer, (PBYTE)Output, &EncodedSize); // 2 for 16bits<->8bits
00804     if (err != BE_ERR_SUCCESSFUL)
00805     {
00806       return -1;
00807     }
00808     
00809     // TODO no more while
00810     do {
00811       DWORD BytesWritten;
00812       WriteFile(the_OutputFile, Output, EncodedSize, &BytesWritten , NULL); // TODO : better handling
00813       EncodedSize -= BytesWritten;
00814     } while (EncodedSize != 0);
00815 
00816     the_SamplesUsed += the_SamplesPerBlock;
00817     lenToUse -= the_SamplesPerBlock; // 2 for 16bits<->8bits
00818     the_WorkingBufferUseSize = 0;
00819   } // while
00820 
00821   memcpy(&the_WorkingBuffer[the_WorkingBufferUseSize], &OriginBuffer[TotalLen - lenToUse], lenToUse);
00822   the_WorkingBufferUseSize += lenToUse;
00823 #endif // DISABLE_MP3OUTPUT
00824 
00825   return 0;
00826 }
00827 
00828 int  AOut::canwrite() { 
00829   the_Debug.OutPut("canwrite (%d)",the_MaxBuffer);
00830 //  return 1152; // TODO : 576 is different cases
00831   if (the_LameDLL.IsLoaded())
00832     return 16*1024*1024; // TODO : 576 is different cases
00833   else
00834     return 0;
00835 //  return the_MaxBuffer * 2 / the_Channels;
00836 //  return the_MaxBuffer * 2 / the_Channels;
00837 }
00838 
00839 int  AOut::isplaying() { 
00840   the_Debug.OutPut("isplaying");
00841   return 0;
00842 }
00843 
00844 int  AOut::pause(const int) { 
00845   the_Debug.OutPut("pause");
00846   return 0;
00847 }
00848 
00849 void AOut::setvolume(const int volume) { 
00850   the_Debug.OutPut("setvolume at %d (not used yet)",volume);
00851   // -666 is the default volume... (nothing to do)
00852 }
00853 
00854 void AOut::setpan(const int pan) { 
00855   the_Debug.OutPut("setpan at %d (not used yet)", pan);
00856 }
00857 
00858 void AOut::flush(const int) { 
00859   the_Debug.OutPut("flush");
00860 }
00861 
00862 int  AOut::getoutputtime() { 
00863   the_Debug.OutPut("getoutputtime");
00864 //  return 0;
00865   return getwrittentime();
00866 }
00867 
00868 int  AOut::getwrittentime() { 
00869   DWORD up = the_SamplesUsed * 1000;
00870   DWORD low = the_SamplesPerSec * 2;
00871 
00872   the_Debug.OutPut("getwrittentime = %d ms ", up/low);
00873   
00874   return up / low;
00875 
00876 //  return 0;
00877 }
00878 
00879 
00880 inline void AOut::UpMixToStereo(SHORT* psData,SHORT* psOutData,DWORD dwNumSamples)
00881 {
00882   for (int dwSample=0; dwSample < dwNumSamples; dwSample++)
00883   {
00884     psOutData[2*dwSample+1] = psOutData[2*dwSample] = psData[dwSample];
00885   }
00886 }
00887 
00888 inline void AOut::MixToMono(SHORT* psData,SHORT* psOutData,DWORD dwNumSamples)
00889 {
00890   for (int dwSample=0; dwSample < dwNumSamples; dwSample++)
00891   {
00892     psOutData[dwSample] = (psData[2*dwSample] >> 1) + (psData[2*dwSample+1] >> 1);
00893   }
00894 }
00895 
00896 
00897 void AOut::replaceAllChar(std::string & the_string, const char src, const char dst)
00898 {
00899 
00900   assert(the_string != NULL);
00901   std::string aSrc;
00902   aSrc = src;
00903 
00904   while (the_string.find( aSrc ) != std::string::npos)
00905   {
00906     std::string a_tmpStr = the_string.substr(0,the_string.find( aSrc ));
00907     a_tmpStr += dst;
00908     a_tmpStr += the_string.substr(the_string.find( aSrc ) + 1);
00909     the_string = a_tmpStr;
00910   }
00911 }
00912 
00913 int AOut::MyMessageBox(const char * the_output, const UINT the_type, const HWND the_parent)
00914 {
00915   std::string str;
00916   str = "MP3 Output v";
00917   str += the_version_name;
00918   return MessageBox( the_parent, the_output, str.c_str() ,the_type);
00919 }
00920 
00921 bool AOut::GetLameVersion(BE_VERSION * ver)
00922 {
00923   assert(ver != NULL);
00924 
00925   if (!the_LameDLL.Load(my_Properties.GetDllLocation()))
00926     return false;
00927 
00928   the_LameDLL.Version(ver);
00929   return true;
00930 }

Generated at Tue Aug 21 21:10:48 2001 for out_lame by doxygen1.2.9.1 written by Dimitri van Heesch, © 1997-2001