From cc2160de5cc05dc3aa77f3a34358e66f6193c8c9 Mon Sep 17 00:00:00 2001 From: Michał Cichoń Date: Tue, 26 Jun 2012 20:35:30 +0200 Subject: Add support for AAC. --- faad2/src/plugins/QCD/QCDFAAD.c | 1030 ++++++++++++++++++++++++++++++++++ faad2/src/plugins/QCD/QCDFAAD.sln | 29 + faad2/src/plugins/QCD/QCDFAAD.vcproj | 348 ++++++++++++ faad2/src/plugins/QCD/QCDInputDLL.h | 50 ++ faad2/src/plugins/QCD/QCDModDefs.h | 340 +++++++++++ faad2/src/plugins/QCD/QCDModInput.h | 117 ++++ faad2/src/plugins/QCD/ReadMe.txt | 11 + faad2/src/plugins/QCD/logo.bmp | Bin 0 -> 87614 bytes faad2/src/plugins/QCD/plugin_dlg.rc | 141 +++++ faad2/src/plugins/QCD/resource.h | 33 ++ 10 files changed, 2099 insertions(+) create mode 100644 faad2/src/plugins/QCD/QCDFAAD.c create mode 100644 faad2/src/plugins/QCD/QCDFAAD.sln create mode 100644 faad2/src/plugins/QCD/QCDFAAD.vcproj create mode 100644 faad2/src/plugins/QCD/QCDInputDLL.h create mode 100644 faad2/src/plugins/QCD/QCDModDefs.h create mode 100644 faad2/src/plugins/QCD/QCDModInput.h create mode 100644 faad2/src/plugins/QCD/ReadMe.txt create mode 100644 faad2/src/plugins/QCD/logo.bmp create mode 100644 faad2/src/plugins/QCD/plugin_dlg.rc create mode 100644 faad2/src/plugins/QCD/resource.h (limited to 'faad2/src/plugins/QCD') diff --git a/faad2/src/plugins/QCD/QCDFAAD.c b/faad2/src/plugins/QCD/QCDFAAD.c new file mode 100644 index 0000000..1d12295 --- /dev/null +++ b/faad2/src/plugins/QCD/QCDFAAD.c @@ -0,0 +1,1030 @@ +/* +** FAAD - Freeware Advanced Audio Decoder +** Copyright (C) 2002 M. Bakker +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** $Id: QCDFAAD.c,v 1.2 2003/04/28 19:04:35 menno Exp $ +** based on menno's in_faad.dll plugin for Winamp +** +** The tag function has been removed because QCD supports ID3v1 & ID3v2 very well +** About how to tagging: Please read the "ReadMe.txt" first +**/ + +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include +#include +#include +#include "QCDInputDLL.h" + +#include "resource.h" + +#include +#include +#include +//#include + +static char app_name[] = "QCDFAAD"; + +faadAACInfo file_info; + +faacDecHandle hDecoder; +faacDecFrameInfo frameInfo; + +HINSTANCE hInstance; +HWND hwndPlayer, hwndConfig, hwndAbout; +QCDModInitIn sQCDCallbacks, *QCDCallbacks; +BOOL oldAPIs = 0; +static char lastfn[MAX_PATH]; // currently playing file (used for getting info on the current file) +int file_length; // file length, in bytes +int paused; // are we paused? +int seek_needed; // if != -1, it is the point that the decode thread should seek to, in ms. + +char *sample_buffer; // sample buffer +unsigned char *buffer; // input buffer +unsigned char *memmap_buffer; // input buffer for whole file +long memmap_index; + +long buffercount, fileread, bytecount; + +// seek table for ADTS header files +unsigned long *seek_table = NULL; +int seek_table_length=0; + +int killPlayThread = 0; // the kill switch for the decode thread +HANDLE play_thread_handle = INVALID_HANDLE_VALUE; // the handle to the decode thread +FILE_STREAM *infile; + +/* Function definitions */ +int id3v2_tag(unsigned char *buffer); +DWORD WINAPI PlayThread(void *b); // the decode thread procedure + +// general funcz +static void show_error(const char *message,...) +{ + char foo[512]; + va_list args; + va_start(args, message); + vsprintf(foo, message, args); + va_end(args); + MessageBox(hwndPlayer, foo, "FAAD Plug-in Error", MB_ICONSTOP); +} + + +// 1= use vbr display, 0 = use average bitrate. This value only controls what shows up in the +// configuration form. Also- Streaming uses an on-the-fly bitrate display regardless of this value. +long m_variable_bitrate_display=0; +long m_priority = 5; +long m_memmap_file = 0; +static char INI_FILE[MAX_PATH]; + +char *priority_text[] = { "", + "Decode Thread Priority: Lowest", + "Decode Thread Priority: Lower", + "Decode Thread Priority: Normal", + "Decode Thread Priority: Higher", + "Decode Thread Priority: Highest (default)" + }; + +long priority_table[] = {0, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST}; + +long current_file_mode = 0; + +int PlayThread_memmap(); +int PlayThread_file(); + +static void _r_s(char *name,char *data, int mlen) +{ + char buf[10]; + strcpy(buf,data); + GetPrivateProfileString(app_name,name,buf,data,mlen,INI_FILE); +} + +#define RS(x) (_r_s(#x,x,sizeof(x))) +#define WS(x) (WritePrivateProfileString(app_name,#x,x,INI_FILE)) + +void config_read() +{ + char variable_bitrate_display[10]; + char priority[10]; + char memmap_file[10]; + char local_buffer_size[10]; + char stream_buffer_size[10]; + + strcpy(variable_bitrate_display, "1"); + strcpy(priority, "5"); + strcpy(memmap_file, "0"); + strcpy(local_buffer_size, "128"); + strcpy(stream_buffer_size, "64"); + + RS(variable_bitrate_display); + RS(priority); + RS(memmap_file); + RS(local_buffer_size); + RS(stream_buffer_size); + + m_priority = atoi(priority); + m_variable_bitrate_display = atoi(variable_bitrate_display); + m_memmap_file = atoi(memmap_file); + m_local_buffer_size = atoi(local_buffer_size); + m_stream_buffer_size = atoi(stream_buffer_size); +} + +void config_write() +{ + char variable_bitrate_display[10]; + char priority[10]; + char memmap_file[10]; + char local_buffer_size[10]; + char stream_buffer_size[10]; + + itoa(m_priority, priority, 10); + itoa(m_variable_bitrate_display, variable_bitrate_display, 10); + itoa(m_memmap_file, memmap_file, 10); + itoa(m_local_buffer_size, local_buffer_size, 10); + itoa(m_stream_buffer_size, stream_buffer_size, 10); + + WS(variable_bitrate_display); + WS(priority); + WS(memmap_file); + WS(local_buffer_size); + WS(stream_buffer_size); +} + +//----------------------------------------------------------------------------- + +BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID pRes) +{ + if (fdwReason == DLL_PROCESS_ATTACH) + hInstance = hInst; + return TRUE; +} + +//----------------------------------------------------------------------------- +//old entrypoint api +PLUGIN_API BOOL QInputModule(QCDModInitIn *ModInit, QCDModInfo *ModInfo) +{ + ModInit->version = PLUGIN_API_VERSION; + ModInit->toModule.ShutDown = ShutDown; + ModInit->toModule.GetTrackExtents = GetTrackExtents; + ModInit->toModule.GetMediaSupported = GetMediaSupported; + ModInit->toModule.GetCurrentPosition= GetCurrentPosition; + ModInit->toModule.Play = Play; + ModInit->toModule.Pause = Pause; + ModInit->toModule.Stop = Stop; + ModInit->toModule.SetVolume = SetVolume; + ModInit->toModule.About = About; + ModInit->toModule.Configure = Configure; + QCDCallbacks = ModInit; + + ModInfo->moduleString = "FAAD Plugin v1.0b"; + /* read config */ + QCDCallbacks->Service(opGetPluginSettingsFile, INI_FILE, MAX_PATH, 0); + + config_read(); + ModInfo->moduleExtensions = "AAC"; + + hwndPlayer = (HWND)ModInit->Service(opGetParentWnd, 0, 0, 0); + lastfn[0] = 0; + play_thread_handle = INVALID_HANDLE_VALUE; + + oldAPIs = 1; + + return TRUE; +} + +//----------------------------------------------------------------------------- + +PLUGIN_API QCDModInitIn* INPUTDLL_ENTRY_POINT() +{ + sQCDCallbacks.version = PLUGIN_API_VERSION; + sQCDCallbacks.toModule.Initialize = Initialize; + sQCDCallbacks.toModule.ShutDown = ShutDown; + sQCDCallbacks.toModule.GetTrackExtents = GetTrackExtents; + sQCDCallbacks.toModule.GetMediaSupported = GetMediaSupported; + sQCDCallbacks.toModule.GetCurrentPosition = GetCurrentPosition; + sQCDCallbacks.toModule.Play = Play; + sQCDCallbacks.toModule.Pause = Pause; + sQCDCallbacks.toModule.Stop = Stop; + sQCDCallbacks.toModule.SetVolume = SetVolume; + sQCDCallbacks.toModule.About = About; + sQCDCallbacks.toModule.Configure = Configure; + + QCDCallbacks = &sQCDCallbacks; + return &sQCDCallbacks; +} + +//---------------------------------------------------------------------------- + +BOOL CALLBACK config_dialog_proc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char tmp[10]; + + switch (message) + { + case WM_INITDIALOG: + /* Set priority slider range and previous position */ + SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_SETRANGE, TRUE, MAKELONG(1, 5)); + SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_SETPOS, TRUE, m_priority); + SetDlgItemText(hwndDlg, IDC_STATIC2, priority_text[m_priority]); + + /* Put a limit to the amount of characters allowed in the buffer boxes */ + SendMessage(GetDlgItem(hwndDlg, LOCAL_BUFFER_TXT), EM_LIMITTEXT, 4, 0); + SendMessage(GetDlgItem(hwndDlg, STREAM_BUFFER_TXT), EM_LIMITTEXT, 4, 0); + + if(m_variable_bitrate_display) + SendMessage(GetDlgItem(hwndDlg, VARBITRATE_CHK), BM_SETCHECK, BST_CHECKED, 0); + if(m_memmap_file) + SendMessage(GetDlgItem(hwndDlg, IDC_MEMMAP), BM_SETCHECK, BST_CHECKED, 0); + + itoa(m_local_buffer_size, tmp, 10); + SetDlgItemText(hwndDlg, LOCAL_BUFFER_TXT, tmp); + + itoa(m_stream_buffer_size, tmp, 10); + SetDlgItemText(hwndDlg, STREAM_BUFFER_TXT, tmp); + + return TRUE; + + case WM_HSCROLL: + + /* Thread priority slider moved */ + if(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER) == (HWND) lParam) + { + int tmp; + tmp = SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_GETPOS, 0, 0); + + if(tmp > 0) + { + m_priority = tmp; + + SetDlgItemText(hwndDlg, IDC_STATIC2, priority_text[m_priority]); + + if(play_thread_handle) + SetThreadPriority(play_thread_handle, priority_table[m_priority]); + } + } + + return TRUE; + + case WM_COMMAND: + + if(HIWORD(wParam) == BN_CLICKED) + { + if(GetDlgItem(hwndDlg, VARBITRATE_CHK) == (HWND) lParam) + { + /* Variable Bitrate checkbox hit */ + m_variable_bitrate_display = SendMessage(GetDlgItem(hwndDlg, VARBITRATE_CHK), BM_GETCHECK, 0, 0); + } + if(GetDlgItem(hwndDlg, IDC_MEMMAP) == (HWND) lParam) + { + /* Variable Bitrate checkbox hit */ + m_memmap_file = SendMessage(GetDlgItem(hwndDlg, IDC_MEMMAP), BM_GETCHECK, 0, 0); + } + } + + switch (LOWORD(wParam)) + { + case OK_BTN: + /* User hit OK, save buffer settings (all others are set on command) */ + GetDlgItemText(hwndDlg, LOCAL_BUFFER_TXT, tmp, 5); + m_local_buffer_size = atol(tmp); + + GetDlgItemText(hwndDlg, STREAM_BUFFER_TXT, tmp, 5); + m_stream_buffer_size = atol(tmp); + + config_write(); + + EndDialog(hwndDlg, wParam); + return TRUE; + case RESET_BTN: + SendMessage(GetDlgItem(hwndDlg, VARBITRATE_CHK), BM_SETCHECK, BST_CHECKED, 0); + m_variable_bitrate_display = 1; + SendMessage(GetDlgItem(hwndDlg, IDC_MEMMAP), BM_SETCHECK, BST_UNCHECKED, 0); + m_memmap_file = 0; + SendMessage(GetDlgItem(hwndDlg, THREAD_PRIORITY_SLIDER), TBM_SETPOS, TRUE, 5); + m_priority = 5; + SetDlgItemText(hwndDlg, IDC_STATIC2, priority_text[5]); + SetDlgItemText(hwndDlg, LOCAL_BUFFER_TXT, "128"); + m_local_buffer_size = 128; + SetDlgItemText(hwndDlg, STREAM_BUFFER_TXT, "64"); + m_stream_buffer_size = 64; + return TRUE; + case IDCANCEL: + case CANCEL_BTN: + /* User hit Cancel or the X, just close without saving buffer settings */ + DestroyWindow(hwndDlg); + return TRUE; + } + } + return FALSE; +} + + +void Configure(int flags) +{ + if(!IsWindow(hwndConfig)) + hwndConfig = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_CONFIG), hwndPlayer, config_dialog_proc); + ShowWindow(hwndConfig, SW_NORMAL); +} + +//----------------------------------------------------------------------------- +// proc of "About Dialog" +INT_PTR CALLBACK about_dialog_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static RECT rcLOGO, rcMail1, rcMail2/*, rcMail3*/; + POINT ptMouse; + static char szPluginVer[] = "QCD FAAD Input Plug-in v1.0b\nCompiled on " __TIME__ ", " __DATE__; + static char szFLACVer[] = "Using: FAAD2 v "FAAD2_VERSION" by"; + + switch (uMsg) + { + case WM_INITDIALOG: + case WM_MOVE: + GetWindowRect(GetDlgItem(hwndDlg, IDC_LOGO), &rcLOGO); + GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL1), &rcMail1); + GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL2), &rcMail2); +// GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL2), &rcMail3); + + SetDlgItemText(hwndDlg, IDC_PLUGINVER, szPluginVer); + SetDlgItemText(hwndDlg, IDC_FAADVER, szFLACVer); + + return TRUE; + case WM_MOUSEMOVE: + ptMouse.x = LOWORD(lParam); + ptMouse.y = HIWORD(lParam); + ClientToScreen(hwndDlg, &ptMouse); + if( (ptMouse.x >= rcLOGO.left && ptMouse.x <= rcLOGO.right && + ptMouse.y >= rcLOGO.top && ptMouse.y<= rcLOGO.bottom) + || + (ptMouse.x >= rcMail1.left && ptMouse.x <= rcMail1.right && + ptMouse.y >= rcMail1.top && ptMouse.y<= rcMail1.bottom) + || + (ptMouse.x >= rcMail2.left && ptMouse.x <= rcMail2.right && + ptMouse.y >= rcMail2.top && ptMouse.y<= rcMail2.bottom) +/* || + (ptMouse.x >= rcMail3.left && ptMouse.x <= rcMail3.right && + ptMouse.y >= rcMail3.top && ptMouse.y<= rcMail3.bottom)*/ ) + SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(32649))); + else + SetCursor(LoadCursor(NULL, IDC_ARROW)); + + return TRUE; + case WM_LBUTTONDOWN: + ptMouse.x = LOWORD(lParam); + ptMouse.y = HIWORD(lParam); + ClientToScreen(hwndDlg, &ptMouse); + if(ptMouse.x >= rcLOGO.left && ptMouse.x <= rcLOGO.right && + ptMouse.y >= rcLOGO.top && ptMouse.y<= rcLOGO.bottom) + ShellExecute(0, NULL, "http://www.audiocoding.com", NULL,NULL, SW_NORMAL); + else if(ptMouse.x >= rcMail1.left && ptMouse.x <= rcMail1.right && + ptMouse.y >= rcMail1.top && ptMouse.y<= rcMail1.bottom) + ShellExecute(0, NULL, "mailto:shaohao@elong.com", NULL,NULL, SW_NORMAL); + else if(ptMouse.x >= rcMail2.left && ptMouse.x <= rcMail2.right && + ptMouse.y >= rcMail2.top && ptMouse.y<= rcMail2.bottom) + ShellExecute(0, NULL, "mailto:menno@audiocoding.com", NULL,NULL, SW_NORMAL); +/* else if(ptMouse.x >= rcMail3.left && ptMouse.x <= rcMail3.right && + ptMouse.y >= rcMail3.top && ptMouse.y<= rcMail3.bottom) + ShellExecute(0, NULL, "I don't know", NULL,NULL, SW_NORMAL); +*/ + return TRUE; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDOK: + default: + DestroyWindow(hwndDlg); + return TRUE; + } + } + return FALSE; +} + +void About(int flags) +{ + if(!IsWindow(hwndAbout)) + hwndAbout = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_ABOUT), hwndPlayer, about_dialog_proc); + ShowWindow(hwndAbout, SW_SHOW); +} + +//----------------------------------------------------------------------------- + +BOOL Initialize(QCDModInfo *ModInfo, int flags) +{ + hwndPlayer = (HWND)QCDCallbacks->Service(opGetParentWnd, 0, 0, 0); + + lastfn[0] = 0; + seek_needed = -1; + paused = 0; + play_thread_handle = INVALID_HANDLE_VALUE; + + /* read config */ + QCDCallbacks->Service(opGetPluginSettingsFile, INI_FILE, MAX_PATH, 0); + config_read(); + + ModInfo->moduleString = "FAAD Plugin v1.0b"; + ModInfo->moduleExtensions = "AAC"; + + /* Initialize winsock, necessary for streaming */ + WinsockInit(); + + // insert menu item into plugin menu +// QCDCallbacks->Service(opSetPluginMenuItem, hInstance, IDD_CONFIG, (long)"FAAD Plug-in"); + + return TRUE; +} + +//---------------------------------------------------------------------------- + +void ShutDown(int flags) +{ + Stop(lastfn, STOPFLAG_FORCESTOP); + + if(buffer) + LocalFree(buffer); + + /* Deallocate winsock */ + WinsockDeInit(); + + // delete the inserted plugin menu +// QCDCallbacks->Service(opSetPluginMenuItem, hInstance, 0, 0); +} + +//----------------------------------------------------------------------------- + +BOOL GetMediaSupported(LPCSTR medianame, MediaInfo *mediaInfo) +{ + FILE_STREAM *in; + faadAACInfo tmp; + char *ch = strrchr(medianame, '.'); + + if (!medianame || !*medianame) + return FALSE; + + if(!ch) + return (lstrlen(medianame) > 2); // no extension defaults to me (if not drive letter) + + /* Finally fixed */ + if(StringComp(ch, ".aac", 4) == 0) + { + in = open_filestream((char *)medianame); + + if(in != NULL && mediaInfo) + { + if(in->http) + { + /* No seeking in http streams */ + mediaInfo->mediaType = DIGITAL_STREAM_MEDIA; + mediaInfo->op_canSeek = FALSE; + } + else + { + mediaInfo->mediaType = DIGITAL_FILE_MEDIA; + get_AAC_format((char *)medianame, &tmp, NULL, NULL, 1); + if(tmp.headertype == 2) /* ADTS header - seekable */ + mediaInfo->op_canSeek = TRUE; + else + mediaInfo->op_canSeek = FALSE; /* ADIF or Headerless - not seekable */ + } + + close_filestream(in); + return TRUE; + } + else + { + close_filestream(in); + return FALSE; + } + } + else + return FALSE; +} + +unsigned long samplerate, channels; + +int play_memmap(char *fn) +{ + int tagsize = 0; + + infile = open_filestream(fn); + + if (infile == NULL) + return 1; + + fileread = filelength_filestream(infile); + + memmap_buffer = (char*)LocalAlloc(LPTR, fileread); + read_buffer_filestream(infile, memmap_buffer, fileread); + + /* skip id3v2 tag */ + memmap_index = id3v2_tag(memmap_buffer); + + hDecoder = faacDecOpen(); + + /* Copy the configuration dialog setting and use it as the default */ + /* initialize the decoder, and get samplerate and channel info */ + + if( (buffercount = faacDecInit(hDecoder, memmap_buffer + memmap_index, + fileread - memmap_index - 1, &samplerate, &channels)) < 0 ) + { + show_error("Error opening input file"); + return 1; + } + + memmap_index += buffercount; + + PlayThread_memmap(); + + return 0; +} + +int play_file(char *fn) +{ + int k; + int tagsize; + + ZeroMemory(buffer, 768*2); + + infile = open_filestream(fn); + + if (infile == NULL) + return 1; + + fileread = filelength_filestream(infile); + + buffercount = bytecount = 0; + read_buffer_filestream(infile, buffer, 768*2); + + tagsize = id3v2_tag(buffer); + + /* If we find a tag, run right over it */ + if(tagsize) + { + if(infile->http) + { + int i; + /* Crude way of doing this, but I believe its fast enough to not make a big difference */ + close_filestream(infile); + infile = open_filestream(fn); + + for(i=0; i < tagsize; i++) + read_byte_filestream(infile); + } + else + seek_filestream(infile, tagsize, FILE_BEGIN); + + bytecount = tagsize; + buffercount = 0; + read_buffer_filestream(infile, buffer, 768*2); + } + + hDecoder = faacDecOpen(); + + /* Copy the configuration dialog setting and use it as the default */ + /* initialize the decoder, and get samplerate and channel info */ + + if((buffercount = faacDecInit(hDecoder, buffer, 768*2, &samplerate, &channels)) < 0) + { + show_error("Error opening input file"); + return 1; + } + + if(buffercount > 0) + { + bytecount += buffercount; + + for (k = 0; k < (768*2 - buffercount); k++) + buffer[k] = buffer[k + buffercount]; + + read_buffer_filestream(infile, buffer + (768*2) - buffercount, buffercount); + buffercount = 0; + } + + PlayThread_file(); + + return 0; +} + + +//----------------------------------------------------------------------------- + +BOOL Play(LPCSTR medianame, int playfrom, int playto, int flags) +{ + if(stricmp(lastfn, medianame) != 0) + { + sQCDCallbacks.toPlayer.OutputStop(STOPFLAG_PLAYDONE); + Stop(lastfn, STOPFLAG_PLAYDONE); + } + + if(paused) + { + // Update the player controls to reflect the new unpaused state + sQCDCallbacks.toPlayer.OutputPause(0); + + Pause(medianame, PAUSE_DISABLED); + + if (playfrom >= 0) + seek_needed = playfrom; + } + else if(play_thread_handle != INVALID_HANDLE_VALUE) + { + seek_needed = playfrom; + return TRUE; + } + else + { + int thread_id; + + // alloc the input buffer + buffer = (unsigned char*)LocalAlloc(LPTR, 768*2); + + current_file_mode = m_memmap_file; + + if(current_file_mode) + { + if(play_memmap((char *)medianame)) + return FALSE; + } + else + { + if(play_file((char *)medianame)) + return FALSE; + } + + if(seek_table) + { + free(seek_table); + seek_table = NULL; + seek_table_length = 0; + } + + get_AAC_format((char *)medianame, &file_info, &seek_table, &seek_table_length, 0); + + seek_needed = playfrom > 0 ? playfrom : -1; + killPlayThread = 0; + strcpy(lastfn,medianame); + + /* + To RageAmp: This is really needed, because aacinfo isn't very accurate on ADIF files yet. + Can be fixed though :-) + */ + file_info.sampling_rate = samplerate; + file_info.channels = frameInfo.channels; + + play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PlayThread, (void *) &killPlayThread, 0, &thread_id); + if(!play_thread_handle) + return FALSE; + + // Note: This line seriously slows down start up time + if(m_priority != 3) // if the priority in config window is set to normal, there is nothing to reset! + SetThreadPriority(play_thread_handle, priority_table[m_priority]); + + } + + return TRUE; +} + +//----------------------------------------------------------------------------- + +BOOL Pause(LPCSTR medianame, int flags) +{ + if(QCDCallbacks->toPlayer.OutputPause(flags)) + { + // send back pause/unpause notification + QCDCallbacks->toPlayer.PlayPaused(medianame, flags); + paused = flags; + return TRUE; + } + return FALSE; +} + +//----------------------------------------------------------------------------- + +BOOL Stop(LPCSTR medianame, int flags) +{ + if(medianame && *medianame && stricmp(lastfn, medianame) == 0) + { + sQCDCallbacks.toPlayer.OutputStop(flags); + + killPlayThread = 1; + if(play_thread_handle != INVALID_HANDLE_VALUE) + { + if(WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT) + { +// MessageBox(hwndPlayer, "FAAD thread kill timeout", "debug", 0); + TerminateThread(play_thread_handle,0); + } + CloseHandle(play_thread_handle); + play_thread_handle = INVALID_HANDLE_VALUE; + } + + if (oldAPIs) + QCDCallbacks->toPlayer.PlayStopped(lastfn); + + lastfn[0] = 0; + } + + return TRUE; +} + +int aac_seek(int pos_ms, int *sktable) +{ + double offset_sec; + + offset_sec = pos_ms / 1000.0; + if(!current_file_mode) + { + seek_filestream(infile, sktable[(int)(offset_sec+0.5)], FILE_BEGIN); + + bytecount = sktable[(int)(offset_sec+0.5)]; + buffercount = 0; + read_buffer_filestream(infile, buffer, 768*2); + } + else + { + memmap_index = sktable[(int)(offset_sec+0.5)]; + } + + return 0; +} + +//----------------------------------------------------------------------------- + +void SetVolume(int levelleft, int levelright, int flags) +{ + QCDCallbacks->toPlayer.OutputSetVol(levelleft, levelright, flags); +} + +//----------------------------------------------------------------------------- + +BOOL GetCurrentPosition(LPCSTR medianame, long *track, long *offset) +{ + return QCDCallbacks->toPlayer.OutputGetCurrentPosition((UINT*)offset, 0); +} + +//----------------------------------------------------------------------------- + +BOOL GetTrackExtents(LPCSTR medianame, TrackExtents *ext, int flags) +{ + faadAACInfo tmp; + + if(get_AAC_format((char*)medianame, &tmp, NULL, NULL, 1)) + return FALSE; + + ext->track = 1; + ext->start = 0; + ext->end = tmp.length; + ext->bytesize = tmp.bitrate * tmp.length; + ext->unitpersec = 1000; + + return TRUE; +} + +//--------------------------for play thread------------------------------------- + +int last_frame; + +DWORD WINAPI PlayThread(void *b) +{ + BOOL done = FALSE, updatePos = FALSE; + int decode_pos_ms = 0; // current decoding position, in milliseconds + int l; + int decoded_frames=0; + int br_calc_frames=0; + int br_bytes_consumed=0; + unsigned long bytesconsumed; + + last_frame = 0; + + if(!done) + { + // open outputdevice + WAVEFORMATEX wf; + wf.wFormatTag = WAVE_FORMAT_PCM; + wf.cbSize = 0; + wf.nChannels = file_info.channels; + wf.wBitsPerSample = 16; + wf.nSamplesPerSec = file_info.sampling_rate; + wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8; + wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; + if (!QCDCallbacks->toPlayer.OutputOpen(lastfn, &wf)) + { + show_error("Error: Failed openning output plugin!"); + done = TRUE; // cannot open sound device + } + } + + while (! *((int *)b) ) + { + /********************** SEEK ************************/ + if (!done && seek_needed >= 0) + { + int seconds; + + // Round off to a second + seconds = seek_needed - (seek_needed%1000); + QCDCallbacks->toPlayer.OutputFlush(decode_pos_ms); + aac_seek(seconds, seek_table); + decode_pos_ms = seconds; + decoded_frames = 0; + br_calc_frames = 0; + br_bytes_consumed = 0; + + seek_needed = -1; + updatePos = 1; + } + + /********************* QUIT *************************/ + if (done) + { + if (QCDCallbacks->toPlayer.OutputDrain(0) && !(seek_needed >= 0)) + { + play_thread_handle = INVALID_HANDLE_VALUE; + QCDCallbacks->toPlayer.OutputStop(STOPFLAG_PLAYDONE); + QCDCallbacks->toPlayer.PlayDone(lastfn); + } + else if (seek_needed >= 0) + { + done = FALSE; + continue; + } + break; + } + + /******************* DECODE TO BUFFER ****************/ + else + { + if (current_file_mode) + bytesconsumed = PlayThread_memmap(); + else + bytesconsumed = PlayThread_file(); + + if(last_frame) + done = TRUE; + else + { + + decoded_frames++; + br_calc_frames++; + br_bytes_consumed += bytesconsumed; + + /* Update the variable bitrate about every second */ + if(m_variable_bitrate_display && br_calc_frames == 43) + { + AudioInfo vai; + vai.struct_size = sizeof(AudioInfo); + vai.frequency = file_info.sampling_rate; + vai.bitrate = (int)((br_bytes_consumed * 8) / (decoded_frames / 43.07)); + vai.mode = (channels == 2) ? 0 : 3; + vai.layer = 0; + vai.level = file_info.version; + QCDCallbacks->Service(opSetAudioInfo, &vai, sizeof(AudioInfo), 0); + + br_calc_frames = 0; + } + + if (!killPlayThread && (frameInfo.samples > 0)) + { + //update the time display + if (updatePos) + { + QCDCallbacks->toPlayer.PositionUpdate(decode_pos_ms); + updatePos = 0; + } + + { + WriteDataStruct wd; + + l = frameInfo.samples * sizeof(short); + + decode_pos_ms += (1024*1000)/file_info.sampling_rate; + + wd.bytelen = l; + wd.data = sample_buffer; + wd.markerend = 0; + wd.markerstart = decode_pos_ms; + wd.bps = 16; + wd.nch = frameInfo.channels; + wd.numsamples =l/file_info.channels/(16/8); + wd.srate = file_info.sampling_rate; + + if (!QCDCallbacks->toPlayer.OutputWrite(&wd)) + done = TRUE; + } + } + } + } + Sleep(10); + } + + // close up + play_thread_handle = INVALID_HANDLE_VALUE; + + faacDecClose(hDecoder); + hDecoder = INVALID_HANDLE_VALUE; + close_filestream(infile); + infile = NULL; + + if(seek_table) + { + free(seek_table); + seek_table = NULL; + seek_table_length = 0; + } + + if(buffer) + { + LocalFree(buffer); + buffer = NULL; + } + if(memmap_buffer) + { + LocalFree(memmap_buffer); + memmap_buffer = NULL; + } + + return 0; +} + +// thread play funcs +int PlayThread_memmap() +{ + sample_buffer = (char*)faacDecDecode(hDecoder, &frameInfo, + memmap_buffer + memmap_index, fileread - memmap_index - 1); + if (frameInfo.error) + { +// show_error(faacDecGetErrorMessage(frameInfo.error)); + last_frame = 1; + } + + memmap_index += frameInfo.bytesconsumed; + if (memmap_index >= fileread) + last_frame = 1; + + return frameInfo.bytesconsumed; +} + +int PlayThread_file() +{ + int k; + + if (buffercount > 0) + { + for (k = 0; k < (768*2 - buffercount); k++) + buffer[k] = buffer[k + buffercount]; + + read_buffer_filestream(infile, buffer + (768*2) - buffercount, buffercount); + buffercount = 0; + } + + sample_buffer = (char*)faacDecDecode(hDecoder, &frameInfo, buffer, 768*2); + if (frameInfo.error) + { +// show_error(faacDecGetErrorMessage(frameInfo.error)); + last_frame = 1; + } + + buffercount += frameInfo.bytesconsumed; + + bytecount += frameInfo.bytesconsumed; + if (bytecount >= fileread) + last_frame = 1; + + return frameInfo.bytesconsumed; +} + +// tag +int id3v2_tag(unsigned char *buffer) +{ + if (StringComp(buffer, "ID3", 3) == 0) + { + unsigned long tagsize; + + /* high bit is not used */ + tagsize = (buffer[6] << 21) | (buffer[7] << 14) | + (buffer[8] << 7) | (buffer[9] << 0); + + tagsize += 10; + + return tagsize; + } + else + { + return 0; + } +} \ No newline at end of file diff --git a/faad2/src/plugins/QCD/QCDFAAD.sln b/faad2/src/plugins/QCD/QCDFAAD.sln new file mode 100644 index 0000000..5810dde --- /dev/null +++ b/faad2/src/plugins/QCD/QCDFAAD.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QCDFAAD", "QCDFAAD.vcproj", "{71955EB0-4F77-462B-A844-2BA56E74B87E}" + ProjectSection(ProjectDependencies) = postProject + {BC3EFE27-9015-4C9C-AD3C-72B3B7ED2114} = {BC3EFE27-9015-4C9C-AD3C-72B3B7ED2114} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfaad", "..\..\libfaad\libfaad.vcproj", "{BC3EFE27-9015-4C9C-AD3C-72B3B7ED2114}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {71955EB0-4F77-462B-A844-2BA56E74B87E}.Debug|Win32.ActiveCfg = Debug|Win32 + {71955EB0-4F77-462B-A844-2BA56E74B87E}.Debug|Win32.Build.0 = Debug|Win32 + {71955EB0-4F77-462B-A844-2BA56E74B87E}.Release|Win32.ActiveCfg = Release|Win32 + {71955EB0-4F77-462B-A844-2BA56E74B87E}.Release|Win32.Build.0 = Release|Win32 + {BC3EFE27-9015-4C9C-AD3C-72B3B7ED2114}.Debug|Win32.ActiveCfg = Debug|Win32 + {BC3EFE27-9015-4C9C-AD3C-72B3B7ED2114}.Debug|Win32.Build.0 = Debug|Win32 + {BC3EFE27-9015-4C9C-AD3C-72B3B7ED2114}.Release|Win32.ActiveCfg = Release|Win32 + {BC3EFE27-9015-4C9C-AD3C-72B3B7ED2114}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/faad2/src/plugins/QCD/QCDFAAD.vcproj b/faad2/src/plugins/QCD/QCDFAAD.vcproj new file mode 100644 index 0000000..a57975e --- /dev/null +++ b/faad2/src/plugins/QCD/QCDFAAD.vcproj @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/faad2/src/plugins/QCD/QCDInputDLL.h b/faad2/src/plugins/QCD/QCDInputDLL.h new file mode 100644 index 0000000..a69023b --- /dev/null +++ b/faad2/src/plugins/QCD/QCDInputDLL.h @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// +// File: QCDInputDLL.h +// +// About: QCD Player Input module DLL interface. For more documentation, see +// QCDModInput.h. +// +// Authors: Written by Paul Quinn and Richard Carlson. +// +// QCD multimedia player application Software Development Kit Release 1.0. +// +// Copyright (C) 1997-2002 Quinnware +// +// This code is free. If you redistribute it in any form, leave this notice +// here. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +//----------------------------------------------------------------------------- + +#ifndef QCDInputDLL_H +#define QCDInputDLL_H + +#include "QCDModInput.h" + +extern HINSTANCE hInstance; +extern HWND hwndPlayer; +extern QCDModInitIn sQCDCallbacks, *QCDCallbacks; + +// Calls from the Player +int GetMediaSupported(const char* medianame, MediaInfo *mediaInfo); +int GetTrackExtents(const char* medianame, TrackExtents *ext, int flags); +int GetCurrentPosition(const char* medianame, long *track, long *offset); + +void SetEQ(EQInfo*); +void SetVolume(int levelleft, int levelright, int flags); + +int Play(const char* medianame, int framefrom, int frameto, int flags); +int Pause(const char* medianame, int flags); +int Stop(const char* medianame, int flags); +int Eject(const char* medianame, int flags); + +int Initialize(QCDModInfo *ModInfo, int flags); +void ShutDown(int flags); +void Configure(int flags); +void About(int flags); + +#endif //QCDInputDLL_H \ No newline at end of file diff --git a/faad2/src/plugins/QCD/QCDModDefs.h b/faad2/src/plugins/QCD/QCDModDefs.h new file mode 100644 index 0000000..1f68baf --- /dev/null +++ b/faad2/src/plugins/QCD/QCDModDefs.h @@ -0,0 +1,340 @@ +//----------------------------------------------------------------------------- +// +// File: QCDModDefs.h +// +// About: Module definitions file. Miscellanious definitions used by different +// module types. This file is published with the plugin SDKs. +// +// Authors: Written by Paul Quinn and Richard Carlson. +// +// Copyright: +// +// QCD multimedia player application Software Development Kit Release 1.0. +// +// Copyright (C) 1997-2002 Quinnware +// +// This code is free. If you redistribute it in any form, leave this notice +// here. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +//----------------------------------------------------------------------------- + +#ifndef QCDMODDEFS_H +#define QCDMODDEFS_H + +#include + +#ifdef __cplusplus +#define PLUGIN_API extern "C" __declspec(dllexport) +#else +#define PLUGIN_API __declspec(dllexport) +#endif + +// Current plugin version +#define PLUGIN_API_VERSION 250 + +//----------------------------------------------------------------------------- + +typedef struct { + char *moduleString; + char *moduleExtensions; + +} QCDModInfo; + +//----------------------------------------------------------------------------- +// Services (ops) provided by the Player +//----------------------------------------------------------------------------- +typedef enum +{ //*** below returns numeric info (*buffer not used) + + opGetPlayerVersion = 0, // high-order word = major version (eg 3.01 is 3), low-order word = minor (eg 3.01 = 1) + opGetParentWnd = 1, // handle to player window + opGetPlayerInstance = 2, // HINSTANCE to player executable + + opGetPlayerState = 9, // get current state of the player (returns: 1 = stopped, 2 = playing, 3 = paused, 0 = failed) + opGetNumTracks = 10, // number of tracks in playlist + opGetCurrentIndex = 11, // index of current track in playlist (0 based) + opGetNextIndex = 12, // get index of next track to play (0 based), param1 = index start index. -1 for after current + opGetTrackNum = 13, // get track number of index, param1 = index of track in playlist, -1 for current + // - 'track number' is the number of the track in it's respective album, as opposed to playlist number + // - the 'track number' for digital files will be 1, unless they are tagged with the CDDB identifier + + opGetTrackLength = 14, // get track length, param1 = index of track in playlist, -1 for current + // param2 = 0 for seconds, 1 for milliseconds + opGetTime = 15, // get time on player, param1 = 0 for time displayed, 1 for track time, 2 for playlist time + // param2 = 0 for elapsed, 1 for remaining + opGetTrackState = 16, // get whether track is marked, param1 = index of track, -1 for current + opGetPlaylistNum = 17, // get playlist number of index, param1 = index of track in playlist, -1 for current + opGetMediaType = 18, // get media type of track, param1 = index if track in playlist, -1 for current + // - see MediaTypes below for return values + + opGetAudioInfo = 19, // get format info about currently playing track + // - param1 = 0 for samplerate, 1 for bitrate, 2 for num channels + + opGetOffline = 20, // true if client is in Offline Mode + opGetVisTarget = 21, // where is vis being drawn > 0 - internal to skin, 1 - external window, 2 - full screen + opGetAlwaysOnTop = 22, // true if player is set to 'Always on Top' + opGetRepeatState = 23, // returns: 0 - repeat off, 1 - repeat track, 2 - repeat all + opGetShuffleState = 27, // returns: 0 - shuffle off, 1 - shuffle enabled + + opGetTimerState = 24, // low-order word: 0 - track ascend, 1 - playlist ascend, 2 - track descend, 3 - playlist descend + // hi-order word: 1 if 'show hours' is set, else 0 + + opGetVolume = 25, // get master volume level (0 - 100), param1: 0 = combined, 1 = left, 2 = right + opSetVolume = 26, // set master volume level, param1: vol level 0 - 100, param2: balance (-100 left, 0 center, 100 right) + + opGetIndexFromPLNum = 28, // get index from playlist number, param1 = playlist number + + opGetChildWnd = 30, // handle to the draggable window extension (only available on some skins) + opGetExtVisWnd = 31, // handle to the external visual window + opGetMusicBrowserWnd = 32, // handle to the music browser window + opGetSkinPreviewWnd = 33, // handle to the skin preview window + opGetPropertiesWnd = 34, // handle to the player properties window + opGetExtInfoWnd = 35, // handle to the extended information window + opGetAboutWnd = 36, // handle to the about window + opGetSegmentsWnd = 37, // handle to the segments window + opGetEQPresetsWnd = 38, // handle to the EQ presets window + + opGetVisDimensions = 50, // gets the width and height of visual window (param1 = -1 current vis window, 0 internal vis, 1 external vis, 2 full screen) + // returns: HEIGHT in high word, WIDTH in low word + + opGetQueriesComplete = 60, // get status on whether all tracks in playlist have been queryied for their info + + // playlist manipulation + opDeleteIndex = 90, // delete index from playlist (param1 = index) + opSelectIndex = 91, // mark index as selected (param1 = index, param2 = 1 - set, 0 - unset) + opBlockIndex = 92, // mark index as blocked (param1 = index, param2 = 1 - set, 0 - unset) + + opGetMediaInfo = 99, // get the CddbDisc object for the index specified, param1 = index of track, -1 for current + // param2 = pointer to integer that receives track value + // returns: pointer to CddbDisc object. Do not release or deallocate this pointer + + + //*** below returns string info in buffer, param1 = size of buffer + //*** returns 1 on success, 0 on failure + + opGetTrackName = 100, // get track name, param2 = index of track in playlist, -1 for current + opGetArtistName = 101, // get artist name, param2 = index of track in playlist, -1 for current + opGetDiscName = 102, // get disc name, param2 = index of track in playlist, -1 for current + + opGetTrackFile = 103, // file name of track in playlist, param2 = index of track in playlist, -1 for current + opGetSkinName = 104, // get current skin name + + opGetPluginFolder = 105, // get current plugin folder + opGetPluginSettingsFile = 106, // get settings file (plugins.ini) that plugin should save settings to + opGetPluginCacheFile = 107, // get file that describes plugin validity, functions and names + opGetPlayerSettingsFile = 108, // get settings file (qcd.ini) that player saves it settings to (should use for read-only) + + opGetMusicFolder = 110, // get current music folder + opGetPlaylistFolder = 111, // get current playlist folder + opGetSkinFolder = 112, // get current skin folder + opGetCDDBCacheFolder = 113, // get current folder for CDDB cached info + + opGetCurrentPlaylist = 114, // get full pathname of playlist currently loaded + + opGetMediaID = 115, // get media identifier, param2 = index of track in playlist, -1 for current + // - for CD's it's the TOC - for anything else, right now it's 0 + + opGetSupportedExtensions = 116, // get file extensions supported by the player, param2 = 0 - get all extensions, 1 - get registered extensions + // - returned extensions will be colon delimited + + + //*** below buffer points to struct or other object + //*** returns 1 on success, 0 on failure + + opShowMainMenu = 120, // Display Main QCD Menu (buffer = POINT* - location to display menu) + opGetMainMenu = 121, // Returns copy of HMENU handle to QCD Menu (must use DestroyMenu on handle when complete) + + opShowQuickTrack = 125, // Display QuickTrack Menu (buffer = POINT* - location to display menu) + + opGetEQVals = 200, // get current EQ levels/on/off (buffer = EQInfo*) + opSetEQVals = 201, // set EQ levels/on/off (buffer = EQInfo*) + + opGetProxyInfo = 202, // get proxy info (buffer = ProxyInfo*), returns 0 if proxy not in use + + + //*** below returns numeric info, buffer used + + opGetIndexFromFilename = 210, // get the index of a file that exists in current playlist (buffer = full path of file), + // param1 = startindex (index to start searching on) + // returns -1 if file not in playlist + + + //*** below send information to player + //*** returns 1 on success, 0 on failure + + opSetStatusMessage = 1000, // display message in status area (buffer = msg buffer (null term), param1 = text flags (see below)) + + opSetBrowserUrl = 1001, // set music browser URL (buffer = url (null term)) + // null url buffer - closes browser + // param1 = 0 - normal, 1 - force open + + opSetAudioInfo = 1002, // set the current music bitrate/khz (buffer = AudioInfo*, param1 = size of AudioInfo) + + opSetTrackAlbum = 1003, // update track ablum name (buffer = album (null term), param1 = (string ptr)file name), param2 = MediaTypes + opSetTrackTitle = 1004, // update track title (buffer = title (null term), param1 = (string ptr)file name), param2 = MediaTypes + opSetTrackArtist = 1005, // update track artist name (buffer = artist (null term), param1 = (string ptr)file name), param2 = MediaTypes + + opSetPlaylist = 1006, // add files to or reset playlist with new files (buffer = file list (null term), param1 = (string ptr)originating path (can be NULL), param2 = 1 - clear playlist flag, 2 - enqueue to top + + opSetTrackExtents = 1007, // update track TrackExtents info (buffer = &TrackExtents), param1 = (string ptr)file name) + opSetTrackSeekable = 1008, // update track seekable flag (buffer = (string ptr)file name), param1 = TRUE/FALSE + opSetPlayNext = 1009, // set the next index to be played (buffer = NULL, param1 = index, index = -1 unsets playnext) + opSetIndexFilename = 1010, // updates the filename (or stream) that an index in the current playlist refers to, buffer = new filename, param1 = index + + opSetSeekPosition = 1100, // seek to position during playback (buffer = NULL, param1 = position, param2 = 0 - position is in seconds, 1 - position is in milliseconds, 2 - position is in percent (use (float)param1)) + + + //*** below configures custom plugin menu items for the 'plugin menu' + //*** Player will call plugin's configure routine with menu value when menu item selected + //*** returns 1 on success, 0 on failure + + opSetPluginMenuItem = 2000, // buffer = HINSTANCE of plugin, param1 = item id, param2 = (string ptr)string to display + // - set param2 = 0 to remove item id from menu + // - set param1 = 0 and param2 = 0 to remove whole menu + opSetPluginMenuState = 2001, // buffer = HINSTANCE of plugin, param1 = item id, param2 = menu flags (same as windows menu flags - eg: MF_CHECKED) + + + //*** other services + + opSafeWait = 10000 // plugin's can use this to wait on an object without worrying about deadlocking the player. + // this should only be called by the thread that enters the plugin, not by any plugin-created threads + +} PluginServiceOp; + +//----------------------------------------------------------------------------- +// Info services api provided by the Player, called by Plugin. +//----------------------------------------------------------------------------- +typedef long (*PluginServiceFunc)(PluginServiceOp op, void *buffer, long param1, long param2); + + +//----------------------------------------------------------------------------- +typedef struct // for Output Plugin Write callback +{ + void *data; // pointer to valid data + int bytelen; // length of data pointed to by 'data' in bytes + UINT numsamples; // number of samples represented by 'data' + UINT bps; // bits per sample + UINT nch; // number of channels + UINT srate; // sample rate + + UINT markerstart; // Marker position at start of data (marker is time value of data) + // (set to WAVE_VIS_DATA_ONLY to not have data sent to output plugins) + UINT markerend; // Marker position at end of data (not currently used, set to 0) +} WriteDataStruct; + +//----------------------------------------------------------------------------- +typedef struct // for GetTrackExtents Input Plugin callback +{ + UINT track; // for CD's, set the track number. Otherwise set to 1. + UINT start; // for CD's or media that doesn't start at the beginning + // of the file, set to start position. Otherwise set to 0. + UINT end; // set to end position of media. + UINT unitpersec; // whatever units are being used for this media, how many + // of them per second. + // (Note: ((end - start) / unitpersecond) = file length + UINT bytesize; // size of file in bytes (if applicable, otherwise 0). +} TrackExtents; + +//----------------------------------------------------------------------------- +typedef struct // for opSetAudioInfo service +{ + long struct_size; // sizeof(AudioInfo) + long level; // MPEG level (1 for MPEG1, 2 for MPEG2, 3 for MPEG2.5, 7 for MPEGpro) + long layer; // and layer (1, 2 or 3) + long bitrate; // audio bitrate in bits per second + long frequency; // audio freq in Hz + long mode; // 0 for stereo, 1 for joint-stereo, 2 for dual-channel, 3 for mono, 4 for multi-channel +} AudioInfo; + +//----------------------------------------------------------------------------- +// Equalizer Info +//----------------------------------------------------------------------------- +typedef struct // for coming QCD version +{ + long struct_size; // sizeof(EQInfo) + char enabled; + char preamp; // -128 to 127, 0 is even + char bands[10]; // -128 to 127, 0 is even +} EQInfo; + +//----------------------------------------------------------------------------- +typedef struct +{ + long struct_size; // sizeof(ProxyInfo) + char hostname[200]; + long port; + char username[100]; + char password[100]; +} ProxyInfo; + +//----------------------------------------------------------------------------- +typedef enum // for MediaInfo.mediaType +{ + UNKNOWN_MEDIA = 0, + CD_AUDIO_MEDIA = 1, + DIGITAL_FILE_MEDIA = 2, + DIGITAL_STREAM_MEDIA = 3 +} MediaTypes; + +//----------------------------------------------------------------------------- +#define MAX_TOC_LEN 2048 +typedef struct +{ + // media descriptors + CHAR mediaFile[MAX_PATH]; + MediaTypes mediaType; + + // cd audio media info + CHAR cd_mediaTOC[MAX_TOC_LEN]; + int cd_numTracks; + int cd_hasAudio; + + // operation info + int op_canSeek; + + // not used + int reserved[4]; + +} MediaInfo; + + +//----------------------------------------------------------------------------- +// When subclassing the parent window, a plugin can watch for these messages +// to react to events going on between plugins and player +// DO NOT SEND THESE MESSAGES - can only watch for them + +// Plugin to Player Notifiers +#define WM_PN_POSITIONUPDATE (WM_USER + 100) // playback progress updated +#define WM_PN_PLAYSTARTED (WM_USER + 101) // playback has started +#define WM_PN_PLAYSTOPPED (WM_USER + 102) // playback has stopped by user +#define WM_PN_PLAYPAUSED (WM_USER + 103) // playback has been paused +#define WM_PN_PLAYDONE (WM_USER + 104) // playback has finished (track completed) +#define WM_PN_MEDIAEJECTED (WM_USER + 105) // a CD was ejected (lParam = (LPCSTR)medianame) +#define WM_PN_MEDIAINSERTED (WM_USER + 106) // a CD was inserted (lParam = (LPCSTR)medianame) +#define WM_PN_INFOCHANGED (WM_USER + 107) // track information was updated (lParam = (LPCSTR)medianame) +#define WM_PN_TRACKCHANGED (WM_USER + 109) // current track playing has changed (relevant from CD plugin) (lParam = (LPCSTR)medianame) + +// Player to Plugin Notifiers +#define WM_PN_PLAYLISTCHANGED (WM_USER + 200) // playlist has changed in some way (add, delete, sort, shuffle, drag-n-drop, etc...) + +// For intercepting main menu display +// (so you can get handle, modify, and display your own) +#define WM_SHOWMAINMENU (WM_USER + 20) + +//----------------------------------------------------------------------------- +// To shutdown player, send this command +#define WM_SHUTDOWN (WM_USER + 5) + +//----------------------------------------------------------------------------- +// opSetStatusMessage textflags +#define TEXT_DEFAULT 0x0 // message scrolls by in status window +#define TEXT_TOOLTIP 0x1 // message acts as tooltip in status window +#define TEXT_URGENT 0x2 // forces message to appear even if no status window (using msg box) +#define TEXT_HOLD 0x4 // tooltip message stays up (no fade out) + + +#endif //QCDMODDEFS_H \ No newline at end of file diff --git a/faad2/src/plugins/QCD/QCDModInput.h b/faad2/src/plugins/QCD/QCDModInput.h new file mode 100644 index 0000000..40a7ae5 --- /dev/null +++ b/faad2/src/plugins/QCD/QCDModInput.h @@ -0,0 +1,117 @@ +//----------------------------------------------------------------------------- +// +// File: QCDModInput.h +// +// About: Input plugin module interface. This file is published with the +// Input plugin SDK. +// +// Authors: Written by Paul Quinn and Richard Carlson. +// +// Copyright: +// +// QCD multimedia player application Software Development Kit Release 1.0. +// +// Copyright (C) 1997-2002 Quinnware +// +// This code is free. If you redistribute it in any form, leave this notice +// here. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +//----------------------------------------------------------------------------- + +#ifndef QCDMODINPUT_H +#define QCDMODINPUT_H + +#include "QCDModDefs.h" + +// name of the DLL export for input plugins +#define INPUTDLL_ENTRY_POINT QInputModule2 // (updated plugin api version 240+) + +// media insert flags +#define MEDIAINSERT_PLAY 0x1 +#define MEDIAINSERT_ADDTRACKS 0x2 +#define MEDIAINSERT_ADDSEGMENTS 0x4 +#define MEDIAINSERT_CLEARPLAYLIST 0x8 + +// Stop will receive one of these flags (pass to output plugin's stop()) +#define STOPFLAG_FORCESTOP 0 // stop occuring due to user action or other event +#define STOPFLAG_PLAYDONE 1 // stop occuring due to playlist completion + +// play flags +#define PLAYFLAG_PLAYBACK 0x0 +#define PLAYFLAG_ENCODING 0x1 +#define PLAYFLAG_SEEKING 0x2 + +// Wave Marker flags +#define WAVE_VIS_DATA_ONLY -1 // set to WaveDataStruct.markerstart in OutputWrite() call have data only go to vis + // and not to output plugin +// pause flags +#define PAUSE_DISABLED 0 // Pause() call is to unpause playback +#define PAUSE_ENABLED 1 // Pause() call is to pause playback + +//----------------------------------------------------------------------------- +// Input Module +//----------------------------------------------------------------------------- +typedef struct +{ + unsigned int size; // size of init structure + unsigned int version; // plugin structure version (set to PLUGIN_API_VERSION) + PluginServiceFunc Service; // player supplied services callback + + struct + { + void (*PositionUpdate)(unsigned int position); + void (*PlayStopped)(const char* medianame); // notify player of play stop + void (*PlayStarted)(const char* medianame); // notify player of play start + void (*PlayPaused)(const char* medianame, int flags); // notify player of play pause + void (*PlayDone)(const char* medianame); // notify player when play done + void (*PlayTrackChanged)(const char* medianame); // notify player when playing track changes (cd audio relevant only) + void (*MediaEjected)(const char* medianame); // notify player of media eject (cd audio relevant) + void (*MediaInserted)(const char* medianame, int flags); // notify player of media insert (cd audio relevant) + + // output plugin calls + int (*OutputOpen)(const char* medianame, WAVEFORMATEX*); // open output for wave data + int (*OutputWrite)(WriteDataStruct*); // send PCM audio data to output + // (blocks until write completes, thus if output is paused can + // block until unpaused) + int (*OutputDrain)(int flags); // wait for all output to complete (blocking) + int (*OutputDrainCancel)(int flags); // break a drain in progress + int (*OutputFlush)(unsigned int marker); // flush output upto marker + int (*OutputStop)(int flags); // stop output + int (*OutputPause)(int flags); // pause output + + int (*OutputSetVol)(int levelleft, int levelright, int flags); + int (*OutputGetCurrentPosition)(unsigned int *position, int flags); + + void *Reserved[10]; + } toPlayer; + + struct + { + int (*Initialize)(QCDModInfo *modInfo, int flags); // initialize plugin + void (*ShutDown)(int flags); // shutdown plugin + + int (*Play)(const char* medianame, int playfrom, int playto, int flags); // start playing playfrom->playto + int (*Stop)(const char* medianame, int flags); // stop playing + int (*Pause)(const char* medianame, int flags); // pause playback + int (*Eject)(const char* medianame, int flags); // eject media + void (*SetEQ)(EQInfo*); // update EQ settings + + int (*GetMediaSupported)(const char* medianame, MediaInfo *mediaInfo); // does plugin support medianame (and provides info for media) + int (*GetTrackExtents)(const char* medianame, TrackExtents *ext, int flags); // get media start, end & units + int (*GetCurrentPosition)(const char* medianame, long *track, long *offset); // get playing media's position + + void (*Configure)(int flags); // launch configuration + void (*About)(int flags); // launch about info + + void (*SetVolume)(int levelleft, int levelright, int flags); // level 0 - 100 + + void *Reserved[10]; + } toModule; + +} QCDModInitIn; + +#endif //QCDMODINPUT_H diff --git a/faad2/src/plugins/QCD/ReadMe.txt b/faad2/src/plugins/QCD/ReadMe.txt new file mode 100644 index 0000000..2e89c09 --- /dev/null +++ b/faad2/src/plugins/QCD/ReadMe.txt @@ -0,0 +1,11 @@ +QCDFAAD.dll input Plugin for Quintessential Player (QCD) +Please goto http://www.quinnware.com to download the latest version of QCD. + +About Tagging music file: + +Because QCD support ID3v1 & ID3v2 functions. So you can add a string -- ":AAC" +in the configuration dialog box of QCDcddb.dll Libarary Plugin. +(I think you will find it and will know how to do it, +otherwise you can visite the message forum on the web site.) + +Have a good time:) \ No newline at end of file diff --git a/faad2/src/plugins/QCD/logo.bmp b/faad2/src/plugins/QCD/logo.bmp new file mode 100644 index 0000000..a01eb84 Binary files /dev/null and b/faad2/src/plugins/QCD/logo.bmp differ diff --git a/faad2/src/plugins/QCD/plugin_dlg.rc b/faad2/src/plugins/QCD/plugin_dlg.rc new file mode 100644 index 0000000..1316be9 --- /dev/null +++ b/faad2/src/plugins/QCD/plugin_dlg.rc @@ -0,0 +1,141 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 179, 133 +STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "FAAC Decoder Configuration" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + CONTROL "Enable variable bitrate display",VARBITRATE_CHK,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,7,140,10 + EDITTEXT STREAM_BUFFER_TXT,87,21,21,12,ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT LOCAL_BUFFER_TXT,87,38,21,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "Buffer entire files into memory",IDC_MEMMAP,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,60,140,10 + CONTROL "Slider1",THREAD_PRIORITY_SLIDER,"msctls_trackbar32", + TBS_AUTOTICKS | WS_TABSTOP,7,89,165,11,WS_EX_TRANSPARENT + PUSHBUTTON "OK",OK_BTN,64,112,50,14 + PUSHBUTTON "Cancel",CANCEL_BTN,121,112,50,14 + LTEXT "HTTP stream buffer:",IDC_STATIC,7,22,77,8 + LTEXT "Decode Thread Priority: Highest (default)",IDC_STATIC2, + 7,78,165,8 + LTEXT "Local file buffer: ",IDC_STATIC,7,40,77,8 + PUSHBUTTON "Reset",RESET_BTN,7,112,50,14 +END + +IDD_ABOUT DIALOG DISCARDABLE 0, 0, 191, 168 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About FAAD Plug-in" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,70,147,50,14 + CTEXT "",IDC_PLUGINVER,29,73,133,16 + CTEXT "",IDC_FAADVER,40,123,111,8 + LTEXT "QCD Input Plug-in by",IDC_STATIC,62,97,67,8 + CONTROL 107,IDC_LOGO,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_REALSIZEIMAGE,7,0,177,68 + LTEXT "Shao Hao",IDC_MAIL1,79,111,33,8 + LTEXT "M. Bakker",IDC_MAIL3,59,134,34,8 + LTEXT "menno",IDC_MAIL2,109,134,22,8 + LTEXT "&&",IDC_STATIC,97,134,8,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 172 + TOPMARGIN, 7 + BOTTOMMARGIN, 126 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 184 + BOTTOMMARGIN, 161 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_LOGO BITMAP DISCARDABLE "logo.bmp" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/faad2/src/plugins/QCD/resource.h b/faad2/src/plugins/QCD/resource.h new file mode 100644 index 0000000..7837a2c --- /dev/null +++ b/faad2/src/plugins/QCD/resource.h @@ -0,0 +1,33 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by plugin_dlg.rc +// +#define IDD_CONFIG 101 +#define IDD_ABOUT 106 +#define IDB_LOGO 107 +#define VARBITRATE_CHK 1004 +#define THREAD_PRIORITY_SLIDER 1007 +#define IDC_STATIC2 1034 +#define LOCAL_BUFFER_TXT 1035 +#define STREAM_BUFFER_TXT 1036 +#define IDC_MEMMAP 1037 +#define OK_BTN 1038 +#define CANCEL_BTN 1039 +#define RESET_BTN 1047 +#define IDC_LOGO 1048 +#define IDC_PLUGINVER 1050 +#define IDC_FAADVER 1051 +#define IDC_MAIL1 1052 +#define IDC_MAIL2 1053 +#define IDC_MAIL3 1054 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 109 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1055 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif -- cgit v1.2.3