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
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
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
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 static BOOL CALLBACK AboutProc(
00079 HWND hwndDlg,
00080 UINT uMsg,
00081 WPARAM wParam,
00082 LPARAM lParam
00083 )
00084 {
00085 static HBRUSH hBrushStatic;
00086 static LOGFONT lf;
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;
00254 }
00255 return bResult;
00256 }
00257
00259
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
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,
00296 0,
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
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
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]));
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),
00418 (LPTSTR) &lpMsgBuf,
00419 0,
00420 NULL
00421 );
00422
00423
00424
00425 MyMessageBox( (LPCTSTR)lpMsgBuf, MB_OK | MB_ICONINFORMATION );
00426
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)
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
00471
00472
00473
00474 BE_CONFIG beConfig;
00475 BE_ERR err;
00476
00477 memset(&beConfig,0,sizeof(beConfig));
00478
00479
00480 beConfig.dwConfig = BE_CONFIG_LAME;
00481
00482
00483 beConfig.format.LHV1.dwStructVersion = 1;
00484 beConfig.format.LHV1.dwStructSize = sizeof(beConfig);
00485 beConfig.format.LHV1.dwSampleRate = samplerate;
00486
00487 if (my_Properties.GetResampleMode())
00488 beConfig.format.LHV1.dwReSampleRate = my_Properties.GetResampleFreq();
00489 else
00490 beConfig.format.LHV1.dwReSampleRate = 0;
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();
00497 }
00498 else
00499 {
00500 if (numchannels < 2)
00501 beConfig.format.LHV1.nMode = BE_MP3_MODE_MONO;
00502 else
00503 {
00504 if (my_Properties.GetChannelModeValue() == BE_MP3_MODE_MONO)
00505 beConfig.format.LHV1.nMode = BE_MP3_MODE_STEREO;
00506 else
00507 beConfig.format.LHV1.nMode = my_Properties.GetChannelModeValue();
00508 }
00509 }
00510
00511 if (beConfig.format.LHV1.dwReSampleRate == 0)
00512 {
00513 if (samplerate < 32000)
00514 beConfig.format.LHV1.dwMpegVersion = MPEG2;
00515 else
00516 beConfig.format.LHV1.dwMpegVersion = MPEG1;
00517 }
00518 else
00519 {
00520 if (beConfig.format.LHV1.dwReSampleRate < 32000)
00521 beConfig.format.LHV1.dwMpegVersion = MPEG2;
00522 else
00523 beConfig.format.LHV1.dwMpegVersion = MPEG1;
00524 }
00525
00526 int bitrateOK = my_Properties.GetBitrateValue(beConfig.format.LHV1.dwBitrate, beConfig.format.LHV1.dwMpegVersion);
00527
00528 if (my_Properties.GetVBRUseMode())
00529 {
00530
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
00553 HWND hwndWinamp = FindWindow("Winamp v1.x",NULL);
00554 if (hwndWinamp == NULL)
00555
00556 hwndWinamp = AOut::GetOutModule()->hMainWindow;
00557
00558
00559
00560 int index = SendMessage(hwndWinamp, WM_USER, 0, 125);
00561 char *name = (char *)SendMessage(hwndWinamp, WM_USER, index, 212);
00562
00563
00564 std::string tmpFilename2 = name;
00565
00566
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
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
00604 if (the_OutputFile == INVALID_HANDLE_VALUE )
00605 {
00606 int i=0;
00607 base_file += "-";
00608 while (the_OutputFile == INVALID_HANDLE_VALUE && i < 1000 )
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();
00629
00630 beConfig.format.LHV1.dwPsyModel = 0;
00631 beConfig.format.LHV1.dwEmphasis = 0;
00632 beConfig.format.LHV1.bOriginal = my_Properties.GetOriginalMode();
00633 beConfig.format.LHV1.bCRC = my_Properties.GetCRCMode();
00634 beConfig.format.LHV1.bCopyright = my_Properties.GetCopyrightMode();
00635 beConfig.format.LHV1.bPrivate = my_Properties.GetPrivateMode();
00636 beConfig.format.LHV1.bNoRes = my_Properties.GetNoBiResMode();
00637
00638
00639 beConfig.format.LHV1.nVbrMethod = my_Properties.GetVBRValue( beConfig.format.LHV1.dwMaxBitrate,
00640 beConfig.format.LHV1.nVBRQuality,
00641 beConfig.format.LHV1.dwVbrAbr_bps,
00642 beConfig.format.LHV1.bWriteVBRHeader,
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
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
00662 the_WorkingBufferUseSize = 0;
00663 the_SamplesUsed = 0;
00664 the_Channels = numchannels;
00665 the_SamplesPerSec = samplerate;
00666
00667
00668 result = the_SamplesPerBlock * 1000 / (the_SamplesPerSec * the_Channels);
00669
00670
00671 name = (char *)SendMessage(hwndWinamp, WM_USER, index, 211);
00672
00673
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
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
00693
00694 bool bFooter = (Header[5] & 0x10) == 0x10;
00695 UINT32 TagSize = (Header[6] << 21) | (Header[7] << 14) | (Header[8] << 7) | Header[9];
00696 TagSize += 10;
00697
00698 if (bFooter)
00699 TagSize += 10;
00700
00701
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
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
00743
00744 if (the_WorkingBufferUseSize != 0)
00745 {
00746 BE_ERR err = the_LameDLL.EncodeChunk(the_WorkingBufferUseSize / 2, (PSHORT)the_WorkingBuffer, (PBYTE)Output, &EncodedSize);
00747 if (err == BE_ERR_SUCCESSFUL)
00748 {
00749 do {
00750 DWORD BytesWritten;
00751 WriteFile(the_OutputFile, Output, EncodedSize, &BytesWritten , NULL);
00752
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);
00764
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
00788
00789
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
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
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);
00832 #endif // ENABLE_RAWOUTPUT
00833
00834 #ifndef DISABLE_MP3OUTPUT
00835
00836
00837
00838
00839
00840
00841
00842 int TotalLen = lenToUse;
00843 while (lenToUse + the_WorkingBufferUseSize >= the_SamplesPerBlock)
00844 {
00845
00846
00847 memcpy(&the_WorkingBuffer[the_WorkingBufferUseSize], &OriginBuffer[TotalLen - lenToUse], the_SamplesPerBlock - the_WorkingBufferUseSize);
00848
00849 err = the_LameDLL.EncodeChunk(the_SamplesPerBlock / 2, (PSHORT)the_WorkingBuffer, (PBYTE)Output, &EncodedSize);
00850 if (err != BE_ERR_SUCCESSFUL)
00851 {
00852 return -1;
00853 }
00854
00855
00856 do {
00857 DWORD BytesWritten;
00858 WriteFile(the_OutputFile, Output, EncodedSize, &BytesWritten , NULL);
00859 EncodedSize -= BytesWritten;
00860 } while (EncodedSize != 0);
00861
00862 the_SamplesUsed += the_SamplesPerBlock;
00863 lenToUse += the_WorkingBufferUseSize - the_SamplesPerBlock;
00864 the_WorkingBufferUseSize = 0;
00865 }
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
00877 if (the_LameDLL.IsLoaded())
00878 return 16*1024*1024;
00879 else
00880 return 0;
00881
00882
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
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
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
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 }