00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 static BOOL CALLBACK AboutProc(
00064 HWND hwndDlg,
00065 UINT uMsg,
00066 WPARAM wParam,
00067 LPARAM lParam
00068 )
00069 {
00070 static HBRUSH hBrushStatic;
00071 static LOGFONT lf;
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;
00239 }
00240 return bResult;
00241 }
00242
00244
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
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,
00281 0,
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
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
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]));
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)
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
00435
00436
00437
00438 BE_CONFIG beConfig;
00439 BE_ERR err;
00440
00441 memset(&beConfig,0,sizeof(beConfig));
00442
00443
00444 beConfig.dwConfig = BE_CONFIG_LAME;
00445
00446
00447 beConfig.format.LHV1.dwStructVersion = 1;
00448 beConfig.format.LHV1.dwStructSize = sizeof(beConfig);
00449 beConfig.format.LHV1.dwSampleRate = samplerate;
00450
00451 if (my_Properties.GetResampleMode())
00452 beConfig.format.LHV1.dwReSampleRate = my_Properties.GetResampleFreq();
00453 else
00454 beConfig.format.LHV1.dwReSampleRate = 0;
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();
00461 }
00462 else
00463 {
00464 if (numchannels < 2)
00465 beConfig.format.LHV1.nMode = BE_MP3_MODE_MONO;
00466 else
00467 {
00468 if (my_Properties.GetChannelModeValue() == BE_MP3_MODE_MONO)
00469 beConfig.format.LHV1.nMode = BE_MP3_MODE_STEREO;
00470 else
00471 beConfig.format.LHV1.nMode = my_Properties.GetChannelModeValue();
00472 }
00473 }
00474
00475 if (beConfig.format.LHV1.dwReSampleRate == 0)
00476 {
00477 if (samplerate < 32000)
00478 beConfig.format.LHV1.dwMpegVersion = MPEG2;
00479 else
00480 beConfig.format.LHV1.dwMpegVersion = MPEG1;
00481 }
00482 else
00483 {
00484 if (beConfig.format.LHV1.dwReSampleRate < 32000)
00485 beConfig.format.LHV1.dwMpegVersion = MPEG2;
00486 else
00487 beConfig.format.LHV1.dwMpegVersion = MPEG1;
00488 }
00489
00490 int bitrateOK = my_Properties.GetBitrateValue(beConfig.format.LHV1.dwBitrate, beConfig.format.LHV1.dwMpegVersion);
00491
00492 if (my_Properties.GetVBRUseMode())
00493 {
00494
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
00517 HWND hwndWinamp = FindWindow("Winamp v1.x",NULL);
00518
00519
00520
00521 int index = SendMessage(hwndWinamp, WM_USER, 0, 125);
00522 char *name = (char *)SendMessage(hwndWinamp, WM_USER, index, 212);
00523
00524
00525 std::string tmpFilename2 = name;
00526
00527
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
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
00565 if (the_OutputFile == INVALID_HANDLE_VALUE )
00566 {
00567 int i=0;
00568 base_file += "-";
00569 while (the_OutputFile == INVALID_HANDLE_VALUE && i < 1000 )
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();
00590
00591 beConfig.format.LHV1.dwPsyModel = 0;
00592 beConfig.format.LHV1.dwEmphasis = 0;
00593 beConfig.format.LHV1.bOriginal = my_Properties.GetOriginalMode();
00594 beConfig.format.LHV1.bCRC = my_Properties.GetCRCMode();
00595 beConfig.format.LHV1.bCopyright = my_Properties.GetCopyrightMode();
00596 beConfig.format.LHV1.bPrivate = my_Properties.GetPrivateMode();
00597 beConfig.format.LHV1.bNoRes = my_Properties.GetNoBiResMode();
00598
00599
00600 beConfig.format.LHV1.bEnableVBR = my_Properties.GetVBRValue( beConfig.format.LHV1.dwMaxBitrate,
00601 beConfig.format.LHV1.nVBRQuality,
00602 beConfig.format.LHV1.bWriteVBRHeader,
00603 beConfig.format.LHV1.dwMpegVersion);
00604
00605 err = the_LameDLL.InitStream(&beConfig, &the_SamplesPerBlock, &the_MaxBuffer);
00606
00607
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
00617 the_WorkingBufferUseSize = 0;
00618 the_SamplesUsed = 0;
00619 the_Channels = numchannels;
00620 the_SamplesPerSec = samplerate;
00621
00622
00623 result = the_SamplesPerBlock * 1000 / (the_SamplesPerSec * the_Channels);
00624
00625
00626 name = (char *)SendMessage(hwndWinamp, WM_USER, index, 211);
00627
00628
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
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
00648
00649 bool bFooter = (Header[5] & 0x10) == 0x10;
00650 UINT32 TagSize = (Header[6] << 21) | (Header[7] << 14) | (Header[8] << 7) | Header[9];
00651 TagSize += 10;
00652
00653 if (bFooter)
00654 TagSize += 10;
00655
00656
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
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
00698
00699 if (the_WorkingBufferUseSize != 0)
00700 {
00701 BE_ERR err = the_LameDLL.EncodeChunk(the_WorkingBufferUseSize / 2, (PSHORT)the_WorkingBuffer, (PBYTE)Output, &EncodedSize);
00702 if (err == BE_ERR_SUCCESSFUL)
00703 {
00704 do {
00705 DWORD BytesWritten;
00706 WriteFile(the_OutputFile, Output, EncodedSize, &BytesWritten , NULL);
00707
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);
00719
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
00742
00743
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
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
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);
00786 #endif // ENABLE_RAWOUTPUT
00787
00788 #ifndef DISABLE_MP3OUTPUT
00789
00790
00791
00792
00793
00794
00795
00796 int TotalLen = lenToUse;
00797 while (lenToUse >= the_SamplesPerBlock)
00798 {
00799
00800
00801 memcpy(&the_WorkingBuffer[the_WorkingBufferUseSize], &OriginBuffer[TotalLen - lenToUse], the_SamplesPerBlock - the_WorkingBufferUseSize);
00802
00803 err = the_LameDLL.EncodeChunk(the_SamplesPerBlock / 2, (PSHORT)the_WorkingBuffer, (PBYTE)Output, &EncodedSize);
00804 if (err != BE_ERR_SUCCESSFUL)
00805 {
00806 return -1;
00807 }
00808
00809
00810 do {
00811 DWORD BytesWritten;
00812 WriteFile(the_OutputFile, Output, EncodedSize, &BytesWritten , NULL);
00813 EncodedSize -= BytesWritten;
00814 } while (EncodedSize != 0);
00815
00816 the_SamplesUsed += the_SamplesPerBlock;
00817 lenToUse -= the_SamplesPerBlock;
00818 the_WorkingBufferUseSize = 0;
00819 }
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
00831 if (the_LameDLL.IsLoaded())
00832 return 16*1024*1024;
00833 else
00834 return 0;
00835
00836
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
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
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
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 }