diff options
Diffstat (limited to 'Src/Plugins/Input/in_mp3/main.cpp')
-rw-r--r-- | Src/Plugins/Input/in_mp3/main.cpp | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_mp3/main.cpp b/Src/Plugins/Input/in_mp3/main.cpp new file mode 100644 index 00000000..e0fb5df2 --- /dev/null +++ b/Src/Plugins/Input/in_mp3/main.cpp @@ -0,0 +1,342 @@ +//#define PLUGIN_NAME "Nullsoft MPEG Audio Decoder" +#include "main.h" +#include <time.h> +#include "DecodeThread.h" +#include "api__in_mp3.h" +#include "../Winamp/wa_ipc.h" +#include "../nu/ServiceBuilder.h" +#include "config.h" +#include "AlbumArt.h" +#include "MetadataFactory.h" +#include "../nu/Singleton.h" +#include "RawMediaReader.h" + +char lastfn_status[256] = {0}; +int lastfn_status_err = 0; +CRITICAL_SECTION g_lfnscs; +CRITICAL_SECTION streamInfoLock; + +int lastfn_data_ready; + +int config_fastvis=0; +unsigned char config_miscopts=0; +unsigned char allow_sctitles=1; +unsigned char sctitle_format=1; +unsigned char config_eqmode=4,config_http_proxynonport80=1; +unsigned int winampVersion=0x00005010; // default version # to use if winamp version is 5.1 or less (and therefore doesn't have a valid HWND during Init) +char config_http_save_dir[MAX_PATH] = "C:\\"; +int config_http_buffersize=64, config_http_prebuffer=40, config_http_prebuffer_underrun=10; +unsigned char config_downmix=0, config_downsample=0, allow_scartwork=1; + +int config_max_bufsize_k=128; +int config_gapless=1; +char INI_FILE[MAX_PATH] = {0}; + +wchar_t lastfn[8192] = {0}; // currently playing file (used for getting info on the current file) + +// Used for correcting DSP plug-in pitch changes +int paused = 0; // are we paused? + +int m_is_stream = 0; +bool m_is_stream_seekable = true; + +volatile int killDecodeThread=0; // the kill switch for the decode thread +HANDLE thread_handle=INVALID_HANDLE_VALUE; // the handle to the decode thread + +DWORD WINAPI DecodeThread(LPVOID b); // the decode thread procedure + +extern char *getfileextensions(); + + +#include "api/service/waservicefactory.h" + +#include "FactoryHelper.h" + +// wasabi based services for localisation support +HINSTANCE WASABI_API_LNG_HINST = 0; +HINSTANCE WASABI_API_ORIG_HINST = 0; + +api_language *WASABI_API_LNG = 0; +api_application *WASABI_API_APP = 0; +api_config *AGAVE_API_CONFIG = 0; +api_memmgr *WASABI_API_MEMMGR = 0; + +AlbumArtFactory albumArtFactory; +MetadataFactory metadataFactory; + +static RawMediaReaderService raw_media_reader_service; +static SingletonServiceFactory<svc_raw_media_reader, RawMediaReaderService> raw_factory; + +int init() +{ + if (!IsWindow(mod.hMainWindow)) + return IN_INIT_FAILURE; + + winampVersion = (unsigned int)SendMessage(mod.hMainWindow, WM_WA_IPC, 0, IPC_GETVERSION); + mod.service->service_register(&metadataFactory); + mod.service->service_register(&albumArtFactory); + raw_factory.Register(mod.service, &raw_media_reader_service); + + ServiceBuild(AGAVE_API_CONFIG, AgaveConfigGUID); + ServiceBuild(WASABI_API_LNG, languageApiGUID); + ServiceBuild(WASABI_API_APP, applicationApiServiceGuid); + ServiceBuild(WASABI_API_MEMMGR, memMgrApiServiceGuid); + + // need to have this initialised before we try to do anything with localisation features + WASABI_API_START_LANG(mod.hDllInstance,InMp3LangGUID); + + static wchar_t szDescription[256]; + swprintf(szDescription, 256, WASABI_API_LNGSTRINGW(IDS_NULLSOFT_MPEG_AUDIO_DECODER), PLUGIN_VERSION); + mod.description = (char*)szDescription; + + InitializeCriticalSection(&g_lfnscs); + InitializeCriticalSection(&streamInfoLock); + mod.UsesOutputPlug|=2; + config_read(); + mod.FileExtensions=getfileextensions(); + return IN_INIT_SUCCESS; +} + +void quit() +{ + DeleteCriticalSection(&g_lfnscs); + DeleteCriticalSection(&streamInfoLock); + ServiceRelease(mod.service, AGAVE_API_CONFIG, AgaveConfigGUID); + ServiceRelease(mod.service, WASABI_API_APP, applicationApiServiceGuid); + ServiceRelease(mod.service, WASABI_API_MEMMGR, memMgrApiServiceGuid); + mod.service->service_deregister(&albumArtFactory); + raw_factory.Deregister(mod.service); +} + +int g_eq_ok; + +int isourfile(const wchar_t *fn) +{ + if (!_wcsnicmp(fn,L"uvox://",7)) return 1; + if (!_wcsnicmp(fn,L"icy://",6)) return 1; + if (!_wcsnicmp(fn,L"sc://",5)) return 1; + if (!_wcsnicmp(fn,L"shoutcast://",12)) return 1; + return 0; +} + + +int m_force_seek=-1; + +// called when winamp wants to play a file +int play(const in_char *fn) +{ + DWORD thread_id; + lastfn_status_err=0; + paused=0; + g_length=-1000; + decode_pos_ms=0; + seek_needed=m_force_seek; + m_force_seek=-1; + m_is_stream = 0; + m_is_stream_seekable = false; + killDecodeThread=0; + g_sndopened=0; + lastfn_data_ready=0; + lastfn_status[0]=0; + g_bufferstat=0; + g_closeaudio=0; + lstrcpynW(lastfn,fn, 8192); + mod.is_seekable = 0; + mod.SetInfo(0,0,0,0); + + g_ds=config_downsample; + + g_eq_ok=1; + // launch decode thread + thread_handle = (HANDLE)CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) DecodeThread,NULL,0,&thread_id); + SetThreadPriority(thread_handle, (int)AGAVE_API_CONFIG->GetInt(playbackConfigGroupGUID, L"priority", THREAD_PRIORITY_HIGHEST)); + + return 0; +} + +// standard pause implementation +void pause() +{ + paused=1; + if (g_sndopened) + mod.outMod->Pause(1); +} + +void unpause() +{ + paused=0; + if (g_sndopened) + mod.outMod->Pause(0); +} + +int ispaused() +{ + return paused; +} + +// stop playing. +void stop() +{ + killDecodeThread=1; + WaitForSingleObject(thread_handle,INFINITE); + CloseHandle(thread_handle); + g_eq_ok=0; + thread_handle = INVALID_HANDLE_VALUE; + g_length=-1000; + lastfn[0]=0; + if (g_closeaudio) + { + g_closeaudio=0; + mod.outMod->Close(); + mod.SAVSADeInit(); + } + g_sndopened=0; + m_force_seek=-1; +} + + +// returns length of playing track +int getlength() +{ + return g_length; +} + + +// returns current output position, in ms. +// you could just use return mod.outMod->GetOutputTime(), +// but the dsp plug-ins that do tempo changing tend to make +// that wrong. +int getoutputtime() +{ + if (g_bufferstat) + return g_bufferstat; + + if (!lastfn_data_ready||!g_sndopened) + return 0; + + if (seek_needed!=-1) + return seek_needed; + + return decode_pos_ms + + (mod.outMod->GetOutputTime()-mod.outMod->GetWrittenTime()); +} + + +// called when the user releases the seek scroll bar. +// usually we use it to set seek_needed to the seek +// point (seek_needed is -1 when no seek is needed) +// and the decode thread checks seek_needed. +void setoutputtime(int time_in_ms) +{ + + + if (m_is_stream == 0 || (m_is_stream !=0 && m_is_stream_seekable)) + { + seek_needed=time_in_ms; + m_force_seek=-1; + } +} + + +// standard volume/pan functions +void setvolume(int volume) +{ + mod.outMod->SetVolume(volume); +} +void setpan(int pan) +{ + mod.outMod->SetPan(pan); +} + + +// this is an odd function. it is used to get the title and/or +// length of a track. +// if filename is either NULL or of length 0, it means you should +// return the info of lastfn. Otherwise, return the information +// for the file in filename. +// if title is NULL, no title is copied into it. +// if length_in_ms is NULL, no length is copied into it. + +static int memcmpv(char *d, char v, int l) +{ + while (l--) + if (*d++ != v) return 1; + return 0; +} + +void eq_set(int on, char data[10], int preamp) +{ + int x; + eq_preamp = preamp; + eq_enabled = on; + for (x = 0; x < 10; x ++) + eq_tab[x] = data[x]; + + // if eq zeroed out, dont use eq + if (eq_enabled && preamp==31 && !memcmpv(data,31,10)) + eq_enabled=0; +} + + + +// render 576 samples into buf. +// this function is only used by DecodeThread. + +// note that if you adjust the size of sample_buffer, for say, 1024 +// sample blocks, it will still work, but some of the visualization +// might not look as good as it could. Stick with 576 sample blocks +// if you can, and have an additional auxiliary (overflow) buffer if +// necessary.. + + +// module definition. + +extern In_Module mod = +{ + IN_VER_RET, // defined in IN2.H + "nullsoft(in_mp3.dll)", + 0, // hMainWindow (filled in by winamp) + 0, // hDllInstance (filled in by winamp) + 0, + // this is a double-null limited list. "EXT\0Description\0EXT\0Description\0" etc. + 0, // is_seekable + 1, // uses output plug-in system + config, + about, + init, + quit, + getfileinfo, + id3Dlg, + isourfile, + play, + pause, + unpause, + ispaused, + stop, + + getlength, + getoutputtime, + setoutputtime, + + setvolume, + setpan, + + 0,0,0,0,0,0,0,0,0, // visualization calls filled in by winamp + + 0,0, // dsp calls filled in by winamp + + eq_set, + + NULL, // setinfo call filled in by winamp + + 0, // out_mod filled in by winamp +}; + +// exported symbol. Returns output module. +extern "C" +{ + __declspec(dllexport) In_Module * winampGetInModule2() + { + return &mod; + } +}
\ No newline at end of file |