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

AOut.cpp

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

Generated at Tue Sep 4 20:59:07 2001 for out_lame by doxygen1.2.9.1 written by Dimitri van Heesch, © 1997-2001