ref: 3501993184b7b711ab99d442ac651a6fb1310b6f
parent: 58fc702265e87f43f286f958ca79cc1a47e926ce
author: menno <menno>
date: Sun Jan 20 11:59:26 EST 2002
MPEG-4 AAC Winamp input plugin!!
--- /dev/null
+++ b/plugins/in_mp4/in2.h
@@ -1,0 +1,104 @@
+#include "out.h"
+
+// note: exported symbol is now winampGetInModule2.
+
+#define IN_VER 0x100
+
+typedef struct
+{
+ int version; // module type (IN_VER)
+ char *description; // description of module, with version string
+
+ HWND hMainWindow; // winamp's main window (filled in by winamp)
+ HINSTANCE hDllInstance; // DLL instance handle (Also filled in by winamp)
+
+ char *FileExtensions; // "mp3\0Layer 3 MPEG\0mp2\0Layer 2 MPEG\0mpg\0Layer 1 MPEG\0"
+ // May be altered from Config, so the user can select what they want
+
+ int is_seekable; // is this stream seekable?
+ int UsesOutputPlug; // does this plug-in use the output plug-ins? (musn't ever change, ever :)
+
+ void (*Config)(HWND hwndParent); // configuration dialog
+ void (*About)(HWND hwndParent); // about dialog
+
+ void (*Init)(); // called at program init
+ void (*Quit)(); // called at program quit
+
+ void (*GetFileInfo)(char *file, char *title, int *length_in_ms); // if file == NULL, current playing is used
+ int (*InfoBox)(char *file, HWND hwndParent);
+
+ int (*IsOurFile)(char *fn); // called before extension checks, to allow detection of mms://, etc
+ // playback stuff
+ int (*Play)(char *fn); // return zero on success, -1 on file-not-found, some other value on other (stopping winamp) error
+ void (*Pause)(); // pause stream
+ void (*UnPause)(); // unpause stream
+ int (*IsPaused)(); // ispaused? return 1 if paused, 0 if not
+ void (*Stop)(); // stop (unload) stream
+
+ // time stuff
+ int (*GetLength)(); // get length in ms
+ int (*GetOutputTime)(); // returns current output time in ms. (usually returns outMod->GetOutputTime()
+ void (*SetOutputTime)(int time_in_ms); // seeks to point in stream (in ms). Usually you signal yoru thread to seek, which seeks and calls outMod->Flush()..
+
+ // volume stuff
+ void (*SetVolume)(int volume); // from 0 to 255.. usually just call outMod->SetVolume
+ void (*SetPan)(int pan); // from -127 to 127.. usually just call outMod->SetPan
+
+ // in-window builtin vis stuff
+
+ void (*SAVSAInit)(int maxlatency_in_ms, int srate); // call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open()
+ // call after opening audio device with max latency in ms and samplerate
+ void (*SAVSADeInit)(); // call in Stop()
+
+
+ // simple vis supplying mode
+ void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp);
+ // sets the spec data directly from PCM data
+ // quick and easy way to get vis working :)
+ // needs at least 576 samples :)
+
+ // advanced vis supplying mode, only use if you're cool. Use SAAddPCMData for most stuff.
+ int (*SAGetMode)(); // gets csa (the current type (4=ws,2=osc,1=spec))
+ // use when calling SAAdd()
+ void (*SAAdd)(void *data, int timestamp, int csa); // sets the spec data, filled in by winamp
+
+
+ // vis stuff (plug-in)
+ // simple vis supplying mode
+ void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the vis data directly from PCM data
+ // quick and easy way to get vis working :)
+ // needs at least 576 samples :)
+
+ // advanced vis supplying mode, only use if you're cool. Use VSAAddPCMData for most stuff.
+ int (*VSAGetMode)(int *specNch, int *waveNch); // use to figure out what to give to VSAAdd
+ void (*VSAAdd)(void *data, int timestamp); // filled in by winamp, called by plug-in
+
+
+ // call this in Play() to tell the vis plug-ins the current output params.
+ void (*VSASetInfo)(int nch, int srate);
+
+
+ // dsp plug-in processing:
+ // (filled in by winamp, called by input plug)
+
+ // returns 1 if active (which means that the number of samples returned by dsp_dosamples
+ // could be greater than went in.. Use it to estimate if you'll have enough room in the
+ // output buffer
+ int (*dsp_isactive)();
+
+ // returns number of samples to output. This can be as much as twice numsamples.
+ // be sure to allocate enough buffer for samples, then.
+ int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate);
+
+
+ // eq stuff
+ void (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore.
+
+ // info setting (filled in by winamp)
+ void (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :)
+
+ Out_Module *outMod; // filled in by winamp, optionally used :)
+} In_Module;
+
+
+
--- /dev/null
+++ b/plugins/in_mp4/in_mp4.c
@@ -1,0 +1,918 @@
+/*
+** 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: in_mp4.c,v 1.1 2002/01/20 16:59:26 menno Exp $
+**/
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <commctrl.h>
+#include <stdlib.h>
+#include <faad.h>
+#include <mp4.h>
+
+#include "resource.h"
+#include "in2.h"
+
+static char app_name[] = "AudioCoding.com MPEG-4 General Audio player";
+static long priority_table[] = {
+ 0,
+ THREAD_PRIORITY_HIGHEST,
+ THREAD_PRIORITY_ABOVE_NORMAL,
+ THREAD_PRIORITY_NORMAL,
+ THREAD_PRIORITY_BELOW_NORMAL,
+ THREAD_PRIORITY_LOWEST
+};
+static int res_id_table[] = {
+ IDC_16BITS,
+ IDC_24BITS,
+ IDC_32BITS
+};
+static int res_table[] = {
+ 16,
+ 24,
+ 32
+};
+static char info_fn[_MAX_PATH];
+
+// post this to the main window at end of file (after playback has stopped)
+#define WM_WA_AAC_EOF WM_USER+2
+
+typedef struct state
+{
+ faacDecHandle hDecoder;
+ MP4FileHandle *mp4file;
+ int mp4track;
+ MP4SampleId numSamples;
+ MP4SampleId sampleId;
+ int samplerate;
+ int channels;
+ int decode_pos_ms; // current decoding position, in milliseconds
+ int paused; // are we paused?
+ int seek_needed; // if != -1, it is the point that the decode thread should seek to, in ms.
+ char filename[_MAX_PATH];
+} state;
+
+static char INI_FILE[MAX_PATH];
+static int m_priority = 3;
+static int m_resolution = 0;
+static int m_show_errors = 1;
+
+static state mp4state;
+
+static In_Module module; // the output module (declared near the bottom of this file)
+
+static int killPlayThread;
+static int PlayThreadAlive = 0; // 1=play thread still running
+HANDLE play_thread_handle = INVALID_HANDLE_VALUE; // the handle to the decode thread
+
+/* Function definitions */
+DWORD WINAPI PlayThread(void *b); // the decode thread procedure
+
+void show_error(HWND hwnd, char *message, ...)
+{
+ if (m_show_errors)
+ MessageBox(hwnd, message, "Error", MB_OK);
+}
+
+int StringComp(char const *str1, char const *str2, unsigned long len)
+{
+ signed int c1 = 0, c2 = 0;
+
+ while (len--)
+ {
+ c1 = *str1++;
+ c2 = *str2++;
+
+ if (c1 == 0 || c1 != c2)
+ break;
+ }
+
+ return c1 - c2;
+}
+
+int GetAACTrack(MP4FileHandle *infile)
+{
+ /* find AAC track */
+ int i, rc;
+ int numTracks = MP4GetNumberOfTracks(infile, NULL);
+
+ for (i = 0; i < numTracks; i++)
+ {
+ MP4TrackId trackId = MP4FindTrackId(infile, i, NULL);
+ const char* trackType = MP4GetTrackType(infile, trackId);
+
+ if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE))
+ {
+ unsigned char *buff = NULL;
+ int buff_size = 0, dummy;
+ MP4GetTrackESConfiguration(infile, trackId, &buff, &buff_size);
+
+ if (buff)
+ {
+ rc = AudioSpecificConfig(buff, &dummy, &dummy, &dummy, &dummy);
+ free(buff);
+
+ if (rc < 0)
+ return -1;
+ return trackId;
+ }
+ }
+ }
+
+ /* can't decode this */
+ return -1;
+}
+
+int GetAudioTrack(MP4FileHandle *infile)
+{
+ /* find AAC track */
+ int i;
+ int numTracks = MP4GetNumberOfTracks(infile, NULL);
+
+ for (i = 0; i < numTracks; i++)
+ {
+ MP4TrackId trackId = MP4FindTrackId(infile, i, NULL);
+ const char* trackType = MP4GetTrackType(infile, trackId);
+
+ if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE))
+ {
+ return trackId;
+ }
+ }
+
+ /* can't decode this */
+ return -1;
+}
+
+int GetVideoTrack(MP4FileHandle *infile)
+{
+ /* find AAC track */
+ int i;
+ int numTracks = MP4GetNumberOfTracks(infile, NULL);
+
+ for (i = 0; i < numTracks; i++)
+ {
+ MP4TrackId trackId = MP4FindTrackId(infile, i, NULL);
+ const char* trackType = MP4GetTrackType(infile, trackId);
+
+ if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE))
+ {
+ return trackId;
+ }
+ }
+
+ /* can't decode this */
+ return -1;
+}
+
+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))
+
+
+
+static void config_init()
+{
+ char *p=INI_FILE;
+ GetModuleFileName(NULL,INI_FILE,sizeof(INI_FILE));
+ while (*p) p++;
+ while (p >= INI_FILE && *p != '.') p--;
+ strcpy(p+1,"ini");
+}
+
+void config_read()
+{
+ char priority[10];
+ char resolution[10];
+ char show_errors[10];
+
+ config_init();
+
+ RS(priority);
+ RS(resolution);
+ RS(show_errors);
+
+ m_priority = atoi(priority);
+ m_resolution = atoi(resolution);
+ m_show_errors = atoi(show_errors);
+}
+
+void config_write()
+{
+ char priority[10];
+ char resolution[10];
+ char show_errors[10];
+
+ itoa(m_priority, priority, 10);
+ itoa(m_resolution, resolution, 10);
+ itoa(m_show_errors, show_errors, 10);
+
+ WS(priority);
+ WS(resolution);
+ WS(show_errors);
+}
+
+void init()
+{
+ config_read();
+}
+
+void quit()
+{
+}
+
+BOOL CALLBACK info_dialog_proc(HWND hwndDlg, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ int i, width, height, numFrames, ch, sf;
+ float fps;
+ MP4FileHandle file;
+ int track;
+ char info[256];
+
+ static const char* mpeg4AudioNames[] = {
+ "MPEG-4 Null (Raw PCM)",
+ "MPEG-4 AAC Main",
+ "MPEG-4 AAC LC",
+ "MPEG-4 AAC SSR",
+ "MPEG-4 AAC LTP",
+ "Reserved",
+ "MPEG-4 AAC Scalable",
+ "MPEG-4 TwinVQ",
+ "MPEG-4 CELP",
+ "MPEG-4 HVXC",
+ "Reserved",
+ "Reserved",
+ "MPEG-4 TTSI",
+ "MPEG-4 Wavetable synthesis",
+ "MPEG-4 General MIDI",
+ "MPEG-4 Algorithmic Synthesis and Audio FX",
+ "Reserved"
+ };
+ static int numMpeg4AudioTypes =
+ sizeof(mpeg4AudioNames)/sizeof(char*);
+
+ static const char* mpeg4VideoNames[] = {
+ "MPEG-4 Simple @ L3",
+ "MPEG-4 Simple @ L2",
+ "MPEG-4 Simple @ L1",
+ "MPEG-4 Simple Scalable @ L2",
+ "MPEG-4 Simple Scalable @ L1",
+ "MPEG-4 Core @ L2",
+ "MPEG-4 Core @ L1",
+ "MPEG-4 Main @ L4",
+ "MPEG-4 Main @ L3",
+ "MPEG-4 Main @ L2",
+ "MPEG-4 Main @ L1",
+ "MPEG-4 N-Bit @ L2",
+ "MPEG-4 Hybrid @ L2",
+ "MPEG-4 Hybrid @ L1",
+ "MPEG-4 Hybrid @ L1"
+ };
+ static int numMpeg4VideoTypes =
+ sizeof(mpeg4VideoNames) / sizeof(char*);
+
+ static int mpegVideoTypes[] = {
+ MP4_MPEG2_SIMPLE_VIDEO_TYPE, // 0x60
+ MP4_MPEG2_MAIN_VIDEO_TYPE, // 0x61
+ MP4_MPEG2_SNR_VIDEO_TYPE, // 0x62
+ MP4_MPEG2_SPATIAL_VIDEO_TYPE, // 0x63
+ MP4_MPEG2_HIGH_VIDEO_TYPE, // 0x64
+ MP4_MPEG2_442_VIDEO_TYPE, // 0x65
+ MP4_MPEG1_VIDEO_TYPE, // 0x6A
+ MP4_JPEG_VIDEO_TYPE // 0x6C
+ };
+ static const char* mpegVideoNames[] = {
+ "MPEG-2 Simple",
+ "MPEG-2 Main",
+ "MPEG-2 SNR",
+ "MPEG-2 Spatial",
+ "MPEG-2 High",
+ "MPEG-2 4:2:2",
+ "MPEG-1",
+ "JPEG"
+ };
+ static int numMpegVideoTypes =
+ sizeof(mpegVideoTypes) / sizeof(u_int8_t);
+
+ unsigned long long msDuration;
+ MP4Duration trackDuration;
+ unsigned int timeScale, avgBitRate;
+ int type;
+ const char* typeName;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ file = MP4Read(info_fn, 0);
+ if (!file)
+ return FALSE;
+
+ if ((track = GetAudioTrack(file)) >= 0)
+ {
+ unsigned char *buff = NULL;
+ int buff_size = 0;
+ MP4GetTrackESConfiguration(file, track, &buff, &buff_size);
+
+ if (buff)
+ {
+ AudioSpecificConfig(buff, &timeScale, &ch, &sf, &type);
+ typeName = mpeg4AudioNames[type];
+ free(buff);
+
+ sprintf(info, "%d", ch);
+ SetDlgItemText(hwndDlg, IDC_CHANNELS, info);
+
+ sprintf(info, "%d Hz", timeScale);
+ SetDlgItemText(hwndDlg, IDC_SAMPLERATE, info);
+ } else {
+ typeName = "Unknown";
+ SetDlgItemText(hwndDlg, IDC_CHANNELS, "n/a");
+ SetDlgItemText(hwndDlg, IDC_SAMPLERATE, "n/a");
+ }
+ trackDuration = MP4GetTrackDuration(file, track);
+
+ msDuration = MP4ConvertFromTrackDuration(file, track,
+ trackDuration, MP4_MSECS_TIME_SCALE);
+
+ avgBitRate = MP4GetTrackIntegerProperty(file, track,
+ "mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.avgBitrate");
+
+ SetDlgItemText(hwndDlg, IDC_TYPE, typeName);
+
+ sprintf(info, "%.3f secs", (float)msDuration/1000.0);
+ SetDlgItemText(hwndDlg, IDC_DURATION, info);
+
+ sprintf(info, "%u Kbps", (avgBitRate+500)/1000);
+ SetDlgItemText(hwndDlg, IDC_BITRATE, info);
+ }
+
+ if ((track = GetVideoTrack(file)) >= 0)
+ {
+ type = MP4GetTrackVideoType(file, track);
+ typeName = "Unknown";
+
+ if (type == MP4_MPEG4_VIDEO_TYPE) {
+ type = MP4GetVideoProfileLevel(file);
+ if (type > 0 && type <= numMpeg4VideoTypes) {
+ typeName = mpeg4VideoNames[type - 1];
+ } else {
+ typeName = "MPEG-4";
+ }
+ } else {
+ for (i = 0; i < numMpegVideoTypes; i++) {
+ if (type == mpegVideoTypes[i]) {
+ typeName = mpegVideoNames[i];
+ break;
+ }
+ }
+ }
+
+ trackDuration = MP4GetTrackDuration(file, track);
+ msDuration = MP4ConvertFromTrackDuration(file, track,
+ trackDuration, MP4_MSECS_TIME_SCALE);
+
+ avgBitRate = MP4GetTrackIntegerProperty(file, track,
+ "mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.avgBitrate");
+
+ // Note not all mp4 implementations set width and height correctly
+ // The real answer can be buried inside the ES configuration info
+ width = MP4GetTrackIntegerProperty(file, track,
+ "mdia.minf.stbl.stsd.mp4v.width");
+
+ height = MP4GetTrackIntegerProperty(file, track,
+ "mdia.minf.stbl.stsd.mp4v.height");
+
+ // Note if variable rate video is being used the fps is an average
+ numFrames = MP4GetTrackNumberOfSamples(file, track);
+
+ fps = ((float)numFrames/(float)msDuration) * 1000;
+
+ SetDlgItemText(hwndDlg, IDC_VTYPE, typeName);
+
+ sprintf(info, "%.3f secs", (float)msDuration/1000.0);
+ SetDlgItemText(hwndDlg, IDC_VDURATION, info);
+
+ sprintf(info, "%u Kbps", (avgBitRate+500)/1000);
+ SetDlgItemText(hwndDlg, IDC_VBITRATE, info);
+
+ sprintf(info, "%dx%d", width, height);
+ SetDlgItemText(hwndDlg, IDC_VSIZE, info);
+
+ sprintf(info, "%.2f", fps);
+ SetDlgItemText(hwndDlg, IDC_VFPS, info);
+ }
+
+ MP4Close(file);
+
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ case IDOK:
+ EndDialog(hwndDlg, wParam);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+int infoDlg(char *fn, HWND hwndParent)
+{
+ lstrcpy(info_fn, fn);
+
+ DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_INFO),
+ hwndParent, info_dialog_proc);
+
+ return 0;
+}
+
+BOOL CALLBACK config_dialog_proc(HWND hwndDlg, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ int i;
+
+ switch (message) {
+ case WM_INITDIALOG:
+ SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_SETRANGE, TRUE, MAKELONG(1,5));
+ SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_SETPOS, TRUE, m_priority);
+ SendMessage(GetDlgItem(hwndDlg, res_id_table[m_resolution]), BM_SETCHECK, BST_CHECKED, 0);
+ if (m_show_errors)
+ SendMessage(GetDlgItem(hwndDlg, IDC_ERROR), BM_SETCHECK, BST_CHECKED, 0);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ EndDialog(hwndDlg, wParam);
+ return TRUE;
+ case IDOK:
+ m_show_errors = SendMessage(GetDlgItem(hwndDlg, IDC_ERROR), BM_GETCHECK, 0, 0);
+ m_priority = SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_GETPOS, 0, 0);
+ for (i = 0; i < 3; i++)
+ {
+ int set = SendMessage(GetDlgItem(hwndDlg, res_id_table[i]), BM_GETCHECK, 0, 0);
+ if (set)
+ {
+ m_resolution = i;
+ break;
+ }
+ }
+
+ /* save config */
+ config_write();
+ EndDialog(hwndDlg, wParam);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void config(HWND hwndParent)
+{
+ DialogBox(module.hDllInstance, MAKEINTRESOURCE(IDD_CONFIG),
+ hwndParent, config_dialog_proc);
+
+ return;
+}
+
+void about(HWND hwndParent)
+{
+ MessageBox(hwndParent,
+ "AudioCoding.com MPEG-4 General Audio player.\n"
+ "Visit the website for more info.\n"
+ "Copyright 2002 AudioCoding.com",
+ "About",
+ MB_OK);
+}
+
+int isourfile(char *fn)
+{
+ if(StringComp(fn + strlen(fn) - 3, "mp4", 3) == 0)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+int play(char *fn)
+{
+ int maxlatency;
+ int thread_id;
+ int avg_bitrate;
+ void *sample_buffer;
+ unsigned char *buffer;
+ int buffer_size;
+ faacDecFrameInfo frameInfo;
+ faacDecConfigurationPtr config;
+
+ mp4state.channels = 0;
+ mp4state.samplerate = 0;
+
+ strcpy(mp4state.filename, fn);
+
+ mp4state.mp4file = MP4Read(fn, 0);
+ if (!mp4state.mp4file)
+ {
+ show_error(module.hMainWindow, "Unable to open file.");
+ return -1;
+ }
+
+ if ((mp4state.mp4track = GetAACTrack(mp4state.mp4file)) < 0)
+ {
+ show_error(module.hMainWindow, "Unsupported Audio track type.");
+ MP4Close(mp4state.mp4file);
+ return -1;
+ }
+
+ mp4state.hDecoder = faacDecOpen();
+
+ buffer = NULL;
+ buffer_size = 0;
+ MP4GetTrackESConfiguration(mp4state.mp4file, mp4state.mp4track,
+ &buffer, &buffer_size);
+ if (!buffer)
+ {
+ faacDecClose(mp4state.hDecoder);
+ MP4Close(mp4state.mp4file);
+ return -1;
+ }
+
+ if(faacDecInit2(mp4state.hDecoder, buffer, buffer_size,
+ &mp4state.samplerate, &mp4state.channels) < 0)
+ {
+ /* If some error initializing occured, skip the file */
+ faacDecClose(mp4state.hDecoder);
+ MP4Close(mp4state.mp4file);
+ return -1;
+ }
+ free(buffer);
+
+ config = faacDecGetCurrentConfiguration(mp4state.hDecoder);
+ config->outputFormat = m_resolution + 1;
+ faacDecSetConfiguration(mp4state.hDecoder, config);
+
+ if (mp4state.channels == 0)
+ {
+ show_error(module.hMainWindow, "Number of channels not supported for playback.");
+ faacDecClose(mp4state.hDecoder);
+ MP4Close(mp4state.mp4file);
+ return -1;
+ }
+
+ maxlatency = module.outMod->Open(mp4state.samplerate, mp4state.channels,
+ res_table[m_resolution], -1,-1);
+ if (maxlatency < 0) // error opening device
+ {
+ faacDecClose(mp4state.hDecoder);
+ MP4Close(mp4state.mp4file);
+ return -1;
+ }
+
+ avg_bitrate = MP4GetTrackIntegerProperty(mp4state.mp4file, mp4state.mp4track,
+ "mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.avgBitrate");
+
+ mp4state.numSamples = MP4GetTrackNumberOfSamples(mp4state.mp4file, mp4state.mp4track);
+ mp4state.sampleId = 1;
+
+ mp4state.paused = 0;
+ mp4state.decode_pos_ms = 0;
+ mp4state.seek_needed = -1;
+
+ module.is_seekable = 1;
+
+ // initialize vis stuff
+ module.SAVSAInit(maxlatency, mp4state.samplerate);
+ module.VSASetInfo(mp4state.samplerate, mp4state.channels);
+
+ module.SetInfo((avg_bitrate + 500)/1000, mp4state.samplerate/1000, mp4state.channels, 1);
+
+ module.outMod->SetVolume(-666); // set the output plug-ins default volume
+
+ killPlayThread = 0;
+
+ if((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlayThread, (void *)&killPlayThread, 0, &thread_id)) == NULL)
+ {
+ show_error(module.hMainWindow, "Cannot create playback thread");
+ faacDecClose(mp4state.hDecoder);
+ MP4Close(mp4state.mp4file);
+ return -1;
+ }
+
+ if (m_priority != 3)
+ SetThreadPriority(play_thread_handle, priority_table[m_priority]);
+
+ return 0;
+}
+
+void pause()
+{
+ mp4state.paused = 1;
+ module.outMod->Pause(1);
+}
+
+void unpause()
+{
+ mp4state.paused = 0;
+ module.outMod->Pause(0);
+}
+
+int ispaused()
+{
+ return mp4state.paused;
+}
+
+void setvolume(int volume)
+{
+ module.outMod->SetVolume(volume);
+}
+
+void setpan(int pan)
+{
+ module.outMod->SetPan(pan);
+}
+
+void stop()
+{
+ killPlayThread = 1;
+
+ if (play_thread_handle != INVALID_HANDLE_VALUE)
+ {
+ if (WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT)
+ TerminateThread(play_thread_handle,0);
+ CloseHandle(play_thread_handle);
+ play_thread_handle = INVALID_HANDLE_VALUE;
+ }
+
+ faacDecClose(mp4state.hDecoder);
+ MP4Close(mp4state.mp4file);
+ module.outMod->Close();
+ module.SAVSADeInit();
+}
+
+int getsonglength(char *fn)
+{
+ int track;
+ long long msDuration;
+ MP4Duration length;
+ MP4FileHandle file;
+
+ file = MP4Read(fn, 0);
+ if (!file)
+ return 0;
+
+ if ((track = GetAACTrack(file)) < 0)
+ {
+ MP4Close(file);
+ return -1;
+ }
+
+ length = MP4GetTrackDuration(file, track);
+
+ msDuration = MP4ConvertFromTrackDuration(file, track,
+ length, MP4_MSECS_TIME_SCALE);
+
+ MP4Close(file);
+
+ return msDuration;
+}
+
+int getlength()
+{
+ return getsonglength(mp4state.filename);
+}
+
+int getoutputtime()
+{
+ return mp4state.decode_pos_ms+(module.outMod->GetOutputTime()-module.outMod->GetWrittenTime());
+}
+
+void setoutputtime(int time_in_ms)
+{
+ mp4state.seek_needed = time_in_ms;
+}
+
+LPTSTR PathFindFileName(LPCTSTR pPath)
+{
+ LPCTSTR pT;
+
+ for (pT = pPath; *pPath; pPath = CharNext(pPath)) {
+ if ((pPath[0] == TEXT('\\') || pPath[0] == TEXT(':')) && pPath[1] && (pPath[1] != TEXT('\\')))
+ pT = pPath + 1;
+ }
+
+ return (LPTSTR)pT; // const -> non const
+}
+
+void getfileinfo(char *filename, char *title, int *length_in_ms)
+{
+ if (!filename || !*filename) /* currently playing file */
+ {
+ if (length_in_ms)
+ *length_in_ms = getlength();
+
+ if (title)
+ {
+ char *tmp = PathFindFileName(mp4state.filename);
+ strcpy(title, tmp);
+ }
+ }
+ else // some other file
+ {
+ if (length_in_ms)
+ *length_in_ms = getsonglength(filename);
+
+ if (title)
+ {
+ char *tmp = PathFindFileName(filename);
+ strcpy(title, tmp);
+ }
+ }
+}
+
+void eq_set(int on, char data[10], int preamp)
+{
+}
+
+int last_frame;
+
+DWORD WINAPI PlayThread(void *b)
+{
+ int done=0;
+ int l;
+ int decoded_frames=0;
+ int br_calc_frames=0;
+ int br_bytes_consumed=0;
+ unsigned long bytesconsumed;
+
+ void *sample_buffer;
+ unsigned char *buffer;
+ int buffer_size;
+ faacDecFrameInfo frameInfo;
+
+ PlayThreadAlive = 1;
+ last_frame = 0;
+
+ while (!*((int *)b))
+ {
+ /* seeking */
+ if (mp4state.seek_needed != -1)
+ {
+ MP4Duration duration;
+
+ module.outMod->Flush(mp4state.decode_pos_ms);
+ duration = MP4ConvertToTrackDuration(mp4state.mp4file,
+ mp4state.mp4track, mp4state.seek_needed, MP4_MSECS_TIME_SCALE);
+ mp4state.sampleId = MP4GetSampleIdFromTime(mp4state.mp4file,
+ mp4state.mp4track, duration, 0);
+
+ mp4state.decode_pos_ms = mp4state.seek_needed;
+ mp4state.seek_needed = -1;
+ }
+
+ if (done)
+ {
+ module.outMod->CanWrite();
+
+ if (!module.outMod->IsPlaying())
+ {
+ PostMessage(module.hMainWindow, WM_WA_AAC_EOF, 0, 0);
+ PlayThreadAlive = 0;
+ return 0;
+ }
+
+ Sleep(10);
+ }
+ else if (module.outMod->CanWrite() >=
+ ((1024*mp4state.channels*sizeof(short))<<(module.dsp_isactive()?1:0)))
+ {
+ if(last_frame)
+ {
+ done = 1;
+ } else {
+ int rc;
+
+ /* get acces unit from MP4 file */
+ buffer = NULL;
+ buffer_size = 0;
+
+ rc = MP4ReadSample(mp4state.mp4file, mp4state.mp4track,
+ mp4state.sampleId++, &buffer, &buffer_size,
+ NULL, NULL, NULL, NULL);
+ if (rc == 0)
+ {
+ last_frame = 1;
+ } else {
+ sample_buffer = faacDecDecode(mp4state.hDecoder, &frameInfo, buffer);
+ }
+ if (frameInfo.error > 0)
+ {
+ show_error(module.hMainWindow, faacDecGetErrorMessage(frameInfo.error));
+ last_frame = 1;
+ }
+ if (mp4state.sampleId >= mp4state.numSamples)
+ last_frame = 1;
+
+ if (buffer) free(buffer);
+
+ if (!killPlayThread && (frameInfo.samples > 0))
+ {
+ module.SAAddPCMData(sample_buffer, mp4state.channels, res_table[m_resolution],
+ mp4state.decode_pos_ms);
+ module.VSAAddPCMData(sample_buffer, mp4state.channels, res_table[m_resolution],
+ mp4state.decode_pos_ms);
+ mp4state.decode_pos_ms += (1024*1000)/mp4state.samplerate;
+
+ if (module.dsp_isactive())
+ {
+ l = module.dsp_dosamples((short*)sample_buffer,
+ frameInfo.samples*sizeof(short)/mp4state.channels/(res_table[m_resolution]/8),
+ res_table[m_resolution],
+ mp4state.channels,mp4state.samplerate)*(mp4state.channels*(res_table[m_resolution]/8));
+ } else {
+ l = frameInfo.samples*(res_table[m_resolution]/8);
+ }
+
+ module.outMod->Write(sample_buffer, l);
+ }
+ }
+ }
+ else
+ {
+ Sleep(10);
+ }
+ }
+
+ PlayThreadAlive = 0;
+
+ return 0;
+}
+
+static In_Module module =
+{
+ IN_VER,
+ "AudioCoding.com MPEG-4 General Audio player: " __DATE__,
+ 0, // hMainWindow
+ 0, // hDllInstance
+ "MP4\0MPEG-4 Files (*.MP4)\0"
+ ,
+ 1, // is_seekable
+ 1, // uses output
+ config,
+ about,
+ init,
+ quit,
+ getfileinfo,
+ infoDlg,
+ isourfile,
+ play,
+ pause,
+ unpause,
+ ispaused,
+ stop,
+
+ getlength,
+ getoutputtime,
+ setoutputtime,
+
+ setvolume,
+ setpan,
+
+ 0,0,0,0,0,0,0,0,0, // vis stuff
+
+
+ 0,0, // dsp
+
+ eq_set,
+
+ NULL, // setinfo
+
+ 0 // out_mod
+};
+
+__declspec(dllexport) In_Module* winampGetInModule2()
+{
+ return &module;
+}
--- /dev/null
+++ b/plugins/in_mp4/in_mp4.dsp
@@ -1,0 +1,123 @@
+# Microsoft Developer Studio Project File - Name="in_mp4" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=in_mp4 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "in_mp4.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "in_mp4.mak" CFG="in_mp4 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "in_mp4 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "in_mp4 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=xicl6.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "in_mp4 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /I "..\..\common\mp4v2" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x413 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=xilink6.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+
+!ELSEIF "$(CFG)" == "in_mp4 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "..\..\common\mp4v2" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x413 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=xilink6.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "in_mp4 - Win32 Release"
+# Name "in_mp4 - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\in_mp4.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\include\faad.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\in2.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\out.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\in_mp4.rc
+# End Source File
+# End Group
+# End Target
+# End Project
--- /dev/null
+++ b/plugins/in_mp4/in_mp4.dsw
@@ -1,0 +1,59 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "in_mp4"=.\in_mp4.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libfaad
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libmp4v2_st
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libfaad"=..\..\libfaad\libfaad.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libmp4v2_st"=..\..\common\mp4v2\libmp4v2_st60.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+++ b/plugins/in_mp4/in_mp4.rc
@@ -1,0 +1,150 @@
+//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
+
+/////////////////////////////////////////////////////////////////////////////
+// Dutch (Netherlands) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NLD)
+#ifdef _WIN32
+LANGUAGE LANG_DUTCH, SUBLANG_DUTCH
+#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_INFO DIALOG DISCARDABLE 0, 0, 191, 207
+STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "MPEG-4 File Info"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,134,186,50,14
+ LTEXT "Type:",IDC_STATIC,14,22,19,8
+ LTEXT "Average bitrate:",IDC_STATIC,14,48,51,8
+ LTEXT "Duration:",IDC_STATIC,14,35,30,8
+ LTEXT "Samplerate:",IDC_STATIC,14,61,38,8
+ GROUPBOX "MPEG-4 Audio Track",IDC_STATIC,7,7,177,84
+ LTEXT "n/a",IDC_TYPE,71,22,102,8
+ LTEXT "n/a",IDC_BITRATE,71,48,102,8
+ LTEXT "n/a",IDC_DURATION,71,35,102,8
+ LTEXT "n/a",IDC_SAMPLERATE,71,61,102,8
+ LTEXT "Type:",IDC_STATIC,14,113,19,8
+ LTEXT "Average bitrate:",IDC_STATIC,14,139,51,8
+ LTEXT "Duration:",IDC_STATIC,14,126,30,8
+ LTEXT "Size:",IDC_STATIC,14,152,16,8
+ GROUPBOX "MPEG-4 Video Track",IDC_STATIC,7,98,177,84
+ LTEXT "n/a",IDC_VTYPE,71,113,102,8
+ LTEXT "n/a",IDC_VBITRATE,71,139,102,8
+ LTEXT "n/a",IDC_VDURATION,71,126,102,8
+ LTEXT "n/a",IDC_VSIZE,71,152,102,8
+ LTEXT "Frames/second:",IDC_STATIC,14,165,52,8
+ LTEXT "n/a",IDC_VFPS,71,165,102,8
+ LTEXT "Channels:",IDC_STATIC,14,74,32,8
+ LTEXT "n/a",IDC_CHANNELS,71,74,102,8
+END
+
+IDD_CONFIG DIALOG DISCARDABLE 0, 0, 125, 95
+STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Configuration"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Slider1",IDC_PRIORITY,"msctls_trackbar32",TBS_VERT |
+ TBS_NOTICKS | WS_TABSTOP,13,15,18,39
+ CONTROL "16 bits",IDC_16BITS,"Button",BS_AUTORADIOBUTTON,77,18,
+ 37,10
+ CONTROL "24 bits",IDC_24BITS,"Button",BS_AUTORADIOBUTTON,77,30,
+ 37,10
+ CONTROL "32 bits",IDC_32BITS,"Button",BS_AUTORADIOBUTTON,77,42,
+ 37,10
+ CONTROL "Show errors",IDC_ERROR,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,7,60,53,10
+ DEFPUSHBUTTON "OK",IDOK,68,74,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,7,74,50,14
+ GROUPBOX "Priority",IDC_STATIC,7,7,57,49
+ LTEXT "Highest",IDC_STATIC,34,18,25,8
+ LTEXT "Normal",IDC_STATIC,34,29,23,8
+ LTEXT "Lowest",IDC_STATIC,34,40,24,8
+ GROUPBOX "Resolution",IDC_STATIC,71,7,47,49
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_INFO, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 184
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 200
+ END
+
+ IDD_CONFIG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 118
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // Dutch (Netherlands) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
--- /dev/null
+++ b/plugins/in_mp4/out.h
@@ -1,0 +1,52 @@
+#define OUT_VER 0x10
+
+typedef struct
+{
+ int version; // module version (OUT_VER)
+ char *description; // description of module, with version string
+ int id; // module id. each input module gets its own. non-nullsoft modules should
+ // be >= 65536.
+
+ HWND hMainWindow; // winamp's main window (filled in by winamp)
+ HINSTANCE hDllInstance; // DLL instance handle (filled in by winamp)
+
+ void (*Config)(HWND hwndParent); // configuration dialog
+ void (*About)(HWND hwndParent); // about dialog
+
+ void (*Init)(); // called when loaded
+ void (*Quit)(); // called when unloaded
+
+ int (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms);
+ // returns >=0 on success, <0 on failure
+ // NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins.
+ // ... so don't expect the max latency returned to be what you asked for.
+ // returns max latency in ms (0 for diskwriters, etc)
+ // bufferlenms and prebufferms must be in ms. 0 to use defaults.
+ // prebufferms must be <= bufferlenms
+
+ void (*Close)(); // close the ol' output device.
+
+ int (*Write)(char *buf, int len);
+ // 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data.
+ // 1 returns not able to write (yet). Non-blocking, always.
+
+ int (*CanWrite)(); // returns number of bytes possible to write at a given time.
+ // Never will decrease unless you call Write (or Close, heh)
+
+ int (*IsPlaying)(); // non0 if output is still going or if data in buffers waiting to be
+ // written (i.e. closing while IsPlaying() returns 1 would truncate the song
+
+ int (*Pause)(int pause); // returns previous pause state
+
+ void (*SetVolume)(int volume); // volume is 0-255
+ void (*SetPan)(int pan); // pan is -128 to 128
+
+ void (*Flush)(int t); // flushes buffers and restarts output at time t (in ms)
+ // (used for seeking)
+
+ int (*GetOutputTime)(); // returns played time in MS
+ int (*GetWrittenTime)(); // returns time written in MS (used for synching up vis stuff)
+
+} Out_Module;
+
+
--- /dev/null
+++ b/plugins/in_mp4/resource.h
@@ -1,0 +1,32 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by in_mp4.rc
+//
+#define IDD_INFO 101
+#define IDD_CONFIG 102
+#define IDC_TYPE 1000
+#define IDC_DURATION 1001
+#define IDC_BITRATE 1002
+#define IDC_SAMPLERATE 1003
+#define IDC_VTYPE 1004
+#define IDC_PRIORITY 1004
+#define IDC_VBITRATE 1005
+#define IDC_ERROR 1005
+#define IDC_VDURATION 1006
+#define IDC_16BITS 1006
+#define IDC_VSIZE 1007
+#define IDC_24BITS 1007
+#define IDC_VFPS 1008
+#define IDC_32BITS 1008
+#define IDC_CHANNELS 1009
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 103
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1007
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif