123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- //#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;
- }
- }
|