aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Input/in_mp3/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Plugins/Input/in_mp3/main.cpp')
-rw-r--r--Src/Plugins/Input/in_mp3/main.cpp342
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