4785 lines
134 KiB
C
4785 lines
134 KiB
C
/*
|
|
FMOD.EXE
|
|
Copyright (c), Firelight Technologies Pty, Ltd, 1999-2004.
|
|
|
|
This example really demonstrates the FMOD music system at work, and is a standalone
|
|
mod/wav/mp3 player!
|
|
It displays a lot of information and uses the DSP engine as well to provide DSP effects under
|
|
MMX only.
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <commctrl.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "../../api/inc/fmod.h"
|
|
#include "../../api/inc/fmod_errors.h" /* optional */
|
|
|
|
#include "resource.h"
|
|
#include "sdriver.h"
|
|
#include "lowpass.h"
|
|
#include "reverb.h"
|
|
|
|
|
|
/*
|
|
DEFINITIONS
|
|
*/
|
|
#define NAME "FSOUND TESTBED"
|
|
#define TITLE "FMOD"
|
|
#define NUMCHANNELS 128
|
|
#define MAXSONGS 512
|
|
#define FSOUND_BUFFERSIZE 200 /* millisecond value for FMOD buffersize. */
|
|
#define MRU_MAX 16
|
|
#define STREAM_PLAYING 255
|
|
|
|
const float WINDOW_WIDTH = 675.0f;
|
|
const float WINDOW_HEIGHT = 324.0f;
|
|
const int TEXT_CHANNELSPLAYING_X = 636;
|
|
const int TEXT_CHANNELSPLAYING_Y = 237;
|
|
const int TEXT_CPUUSAGE_X = 622;
|
|
const int TEXT_CPUUSAGE_Y = 273;
|
|
|
|
enum
|
|
{
|
|
GRAPHICWINDOW_MODINFO = 0,
|
|
GRAPHICWINDOW_EQUALISER,
|
|
GRAPHICWINDOW_WAVE,
|
|
GRAPHICWINDOW_MAX
|
|
};
|
|
|
|
enum
|
|
{
|
|
SONGTYPE_NONE = 0,
|
|
SONGTYPE_MOD,
|
|
SONGTYPE_STREAM,
|
|
SONGTYPE_NETSTREAM,
|
|
SONGTYPE_CD,
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
FMUSIC_MODULE *mod;
|
|
FSOUND_STREAM *stream;
|
|
int channel;
|
|
char *url;
|
|
int last_status;
|
|
int last_netstatus;
|
|
char *server_status;
|
|
char *title;
|
|
char *artist;
|
|
char *protocol;
|
|
char *format;
|
|
char *streamname;
|
|
int metadata;
|
|
char *listname;
|
|
int cdtrack;
|
|
unsigned int cdtrack_length;
|
|
} SONGTYPE;
|
|
|
|
typedef struct
|
|
{
|
|
int count;
|
|
void **name;
|
|
void **displayname;
|
|
} Playlist;
|
|
|
|
/*
|
|
GLOBALS
|
|
*/
|
|
|
|
HWND mainhwnd;
|
|
HWND streaminfo_hwnd;
|
|
HWND netstreaminfo_hwnd;
|
|
HWND modinfo_hwnd;
|
|
HWND cdinfo_hwnd;
|
|
HWND songlist_hwnd;
|
|
|
|
#ifdef _WIN64
|
|
UINT_PTR timerid=0;
|
|
#else
|
|
UINT timerid=0;
|
|
#endif
|
|
|
|
SONGTYPE song[MAXSONGS + 1];
|
|
|
|
int DraggingCDSlider = FALSE;
|
|
int DSP_Ready = FALSE;
|
|
int outputfreq = 44100; /* default output freq */
|
|
int playlistsong = 0;
|
|
char cddevice = 0; /* 0 is the default device, could be 'D' or 'E' etc */
|
|
float scalex = 1.0f, scaley = 1.0f;
|
|
|
|
/*
|
|
Lowpass stuff
|
|
*/
|
|
FSOUND_DSPUNIT *LowPassUnit;
|
|
signed char *LowPassBuffer;
|
|
float LowPassCutoffFrequency = 5000.0f;
|
|
float LowPassResonance = 1.0f;
|
|
|
|
/*
|
|
Echo stuff
|
|
*/
|
|
#define MAXECHOLEN (500 * outputfreq / 1000)
|
|
|
|
FSOUND_DSPUNIT *EchoUnit = NULL;
|
|
signed char *EchoBuffer = NULL;
|
|
int EchoOffset=0, EchoLen=0;
|
|
|
|
/*
|
|
Graphical window stuff for Spectrum and oscilliscope.
|
|
*/
|
|
|
|
#define GRAPHICWINDOW_WIDTH 256
|
|
#define GRAPHICWINDOW_HEIGHT 116
|
|
|
|
int GraphicWindowCurrent = GRAPHICWINDOW_MODINFO;
|
|
BITMAPINFO GraphicWindowBitmap;
|
|
RGBQUAD GraphicWindowBitmapData[GRAPHICWINDOW_WIDTH * GRAPHICWINDOW_HEIGHT];
|
|
int graphic_window_x;
|
|
int graphic_window_y;
|
|
|
|
|
|
/*
|
|
Oscilliscope stuff
|
|
*/
|
|
|
|
FSOUND_DSPUNIT *OscUnit = NULL;
|
|
static signed short *OscBuffer = NULL;
|
|
static int OscBlock = 0;
|
|
|
|
|
|
/*
|
|
SETTINGS
|
|
*/
|
|
|
|
int setting_xpos = 0;
|
|
int setting_ypos = 0;
|
|
int setting_output = 0;
|
|
int setting_driver = 0;
|
|
int setting_mixer = 0;
|
|
int setting_outputrate = 44100;
|
|
int setting_buffersize = 64000;
|
|
int setting_prebuffer_percent = 95;
|
|
int setting_rebuffer_percent = 95;
|
|
char setting_http_proxy[2048];
|
|
int setting_cdda = 1;
|
|
int setting_jitter = 1;
|
|
int setting_forceaspi = 0;
|
|
char setting_cdletter[4] = "C:";
|
|
|
|
char url_to_load[4096];
|
|
HINSTANCE g_hinst;
|
|
char *mru[MRU_MAX];
|
|
signed char play_button_play = TRUE;
|
|
|
|
FSOUND_STREAM *cdda_stream = 0;
|
|
int cdda_channel = -1;
|
|
int cdda_track = 0;
|
|
int cdda_stream_state = -2;
|
|
|
|
/*
|
|
PROTOTYPES
|
|
*/
|
|
|
|
void CloseDown();
|
|
BOOL PlaySong(int index);
|
|
BOOL AddToMRU(char *url);
|
|
BOOL UpdateModInfo(int songid, BOOL forceupdate);
|
|
BOOL UpdateStreamInfo(int songid, BOOL forceupdate);
|
|
BOOL UpdateNetStreamInfo(int songid, BOOL forceupdate, BOOL forcequiet);
|
|
BOOL UpdateCDInfo(int songid, BOOL forceupdate);
|
|
void SelectInfoWindow();
|
|
char *GetCommentValue(FSOUND_STREAM *stream, char *tag);
|
|
signed char FreePlaylist(Playlist *playlist);
|
|
void DeleteSong(int songid);
|
|
void DeleteAllCDTracks();
|
|
signed char StopCDTrack();
|
|
|
|
WNDPROC oldprogressproc;
|
|
WNDPROC oldcdtimeproc;
|
|
|
|
#ifdef _WIN64
|
|
INT_PTR CALLBACK FMOD_LoadURLDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
#else
|
|
BOOL CALLBACK FMOD_LoadURLDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
#endif
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
signed char F_CALLBACKAPI MetadataCallback(char *name, char *value, void *userdata)
|
|
{
|
|
char *tmp;
|
|
int index = (int)userdata;
|
|
|
|
if (!strcmp("ARTIST", name))
|
|
{
|
|
if (song[index].artist)
|
|
{
|
|
free(song[index].artist);
|
|
}
|
|
tmp = strdup(value);
|
|
song[index].artist = tmp;
|
|
song[index].metadata++;
|
|
}
|
|
else if (!strcmp("TITLE", name))
|
|
{
|
|
if (song[index].title)
|
|
{
|
|
free(song[index].title);
|
|
}
|
|
tmp = strdup(value);
|
|
song[index].title = tmp;
|
|
song[index].metadata++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
char *stristr(char *string2, char *string1)
|
|
{
|
|
char *s1 = strdup(string1);
|
|
char *s2 = strdup(string2);
|
|
char *ret = 0;
|
|
int i, j;
|
|
int len1 = (int)strlen(string1);
|
|
int len2 = (int)strlen(string2);
|
|
|
|
for (i=0;s1[i];i++) s1[i] = tolower(s1[i]);
|
|
for (i=0;s2[i];i++) s2[i] = tolower(s2[i]);
|
|
|
|
for (j=0;j < (len2 - len1);j++)
|
|
{
|
|
char *a = s1;
|
|
char *b = &s2[j];
|
|
|
|
for (i=0;(i < len1) && *a && *b;a++, b++, i++)
|
|
{
|
|
if (*a != *b)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == len1)
|
|
{
|
|
ret = &string2[j];
|
|
break;
|
|
}
|
|
}
|
|
|
|
free(s1);
|
|
free(s2);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
void SetFirstCDLetter()
|
|
{
|
|
int count;
|
|
char str[256];
|
|
|
|
for (count=2;count < 26;count++)
|
|
{
|
|
sprintf(str, "%c:\\", (char)('A' + count));
|
|
if (GetDriveType(str) == DRIVE_CDROM)
|
|
{
|
|
strncpy(setting_cdletter, str, 2);
|
|
cddevice = str[0];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
void LoadSettings()
|
|
{
|
|
HKEY key;
|
|
DWORD result,size=4;
|
|
int i;
|
|
|
|
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\FMOD\\Settings", 0, KEY_QUERY_VALUE , &key);
|
|
|
|
setting_output = FSOUND_OUTPUT_DSOUND;
|
|
setting_driver = 0;
|
|
setting_mixer = FSOUND_MIXER_QUALITY_AUTODETECT;
|
|
setting_outputrate = 44100;
|
|
|
|
SetFirstCDLetter();
|
|
|
|
if (result != ERROR_SUCCESS)
|
|
{
|
|
return;
|
|
}
|
|
|
|
RegQueryValueEx(key, "xpos", 0, NULL, (LPBYTE)&setting_xpos, &size);
|
|
RegQueryValueEx(key, "ypos", 0, NULL, (LPBYTE)&setting_ypos, &size);
|
|
|
|
RegQueryValueEx(key, "output", 0, NULL, (LPBYTE)&setting_output, &size);
|
|
RegQueryValueEx(key, "driver", 0, NULL, (LPBYTE)&setting_driver, &size);
|
|
RegQueryValueEx(key, "mixer", 0, NULL, (LPBYTE)&setting_mixer, &size);
|
|
RegQueryValueEx(key, "outputrate", 0, NULL, (LPBYTE)&setting_outputrate, &size);
|
|
|
|
/*
|
|
It is not possible to select nosound from dialog box, so it must be an uninitialized
|
|
registry key.. anyway, however it was 0, set it to directsound if it is.
|
|
*/
|
|
if (!setting_output)
|
|
{
|
|
setting_output = FSOUND_OUTPUT_DSOUND;
|
|
}
|
|
if (setting_outputrate < 4000)
|
|
{
|
|
setting_outputrate = 44100;
|
|
}
|
|
|
|
for (i=0;i < MRU_MAX;i++)
|
|
{
|
|
char s[16];
|
|
char *tmp;
|
|
|
|
size = 0;
|
|
|
|
if (mru[i])
|
|
{
|
|
free(mru[i]);
|
|
mru[i] = 0;
|
|
}
|
|
|
|
sprintf(s, "MRU%d", i);
|
|
|
|
if (RegQueryValueEx(key, s, 0, NULL, (LPBYTE)s, &size) == ERROR_MORE_DATA)
|
|
{
|
|
tmp = (char *)malloc(size);
|
|
if (!tmp)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (RegQueryValueEx(key, s, 0, NULL, tmp, &size) == ERROR_SUCCESS)
|
|
{
|
|
mru[i] = tmp;
|
|
}
|
|
}
|
|
}
|
|
|
|
RegQueryValueEx(key, "buffersize", 0, NULL, (LPBYTE)&setting_buffersize, &size);
|
|
RegQueryValueEx(key, "prebuffer_percent", 0, NULL, (LPBYTE)&setting_prebuffer_percent, &size);
|
|
RegQueryValueEx(key, "rebuffer_percent", 0, NULL, (LPBYTE)&setting_rebuffer_percent, &size);
|
|
FSOUND_Stream_Net_SetBufferProperties(setting_buffersize, setting_prebuffer_percent, setting_rebuffer_percent);
|
|
|
|
size = 2048;
|
|
setting_http_proxy[0] = 0;
|
|
RegQueryValueEx(key, "http_proxy", 0, NULL, setting_http_proxy, &size);
|
|
FSOUND_Stream_Net_SetProxy(setting_http_proxy);
|
|
|
|
RegQueryValueEx(key, "cdda", 0, NULL, (LPBYTE)&setting_cdda, &size);
|
|
RegQueryValueEx(key, "jitter", 0, NULL, (LPBYTE)&setting_jitter, &size);
|
|
RegQueryValueEx(key, "forceaspi", 0, NULL, (LPBYTE)&setting_forceaspi, &size);
|
|
|
|
size = 3;
|
|
setting_cdletter[0] = 0;
|
|
RegQueryValueEx(key, "cdletter", 0, NULL, setting_cdletter, &size);
|
|
|
|
/*
|
|
If it doesn't have a valid cd drive letter in the registry then set the first cd drive letter
|
|
*/
|
|
if (GetDriveType(setting_cdletter) != DRIVE_CDROM)
|
|
{
|
|
SetFirstCDLetter();
|
|
}
|
|
|
|
RegCloseKey(key);
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
void SaveSettings()
|
|
{
|
|
HKEY key;
|
|
DWORD result;
|
|
int i;
|
|
|
|
setting_output = FSOUND_GetOutput();
|
|
setting_driver = FSOUND_GetDriver();
|
|
setting_mixer = FSOUND_GetMixer();
|
|
setting_outputrate = FSOUND_GetOutputRate();
|
|
|
|
RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\FMOD\\Settings", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &result);
|
|
RegSetValueEx(key, "xpos", 0, REG_DWORD, (LPBYTE)&setting_xpos, 4);
|
|
RegSetValueEx(key, "ypos", 0, REG_DWORD, (LPBYTE)&setting_ypos, 4);
|
|
|
|
RegSetValueEx(key, "output", 0, REG_DWORD, (LPBYTE)&setting_output, 4);
|
|
RegSetValueEx(key, "driver", 0, REG_DWORD, (LPBYTE)&setting_driver, 4);
|
|
RegSetValueEx(key, "mixer", 0, REG_DWORD, (LPBYTE)&setting_mixer, 4);
|
|
RegSetValueEx(key, "outputrate", 0, REG_DWORD, (LPBYTE)&setting_outputrate, 4);
|
|
|
|
for (i=0;i < MRU_MAX;i++)
|
|
{
|
|
char s[16];
|
|
|
|
sprintf(s, "MRU%d", i);
|
|
|
|
if (mru[i])
|
|
{
|
|
RegSetValueEx(key, s, 0, REG_SZ, mru[i], (int)strlen(mru[i]) + 1);
|
|
}
|
|
else
|
|
{
|
|
RegDeleteValue(key, s);
|
|
}
|
|
}
|
|
|
|
FSOUND_Stream_Net_GetBufferProperties(&setting_buffersize, &setting_prebuffer_percent, &setting_rebuffer_percent);
|
|
RegSetValueEx(key, "buffersize", 0, REG_DWORD, (LPBYTE)&setting_buffersize, 4);
|
|
RegSetValueEx(key, "prebuffer_percent", 0, REG_DWORD, (LPBYTE)&setting_prebuffer_percent, 4);
|
|
RegSetValueEx(key, "rebuffer_percent", 0, REG_DWORD, (LPBYTE)&setting_rebuffer_percent, 4);
|
|
|
|
if (setting_http_proxy[0])
|
|
{
|
|
RegSetValueEx(key, "http_proxy", 0, REG_SZ, setting_http_proxy, (int)strlen(setting_http_proxy) + 1);
|
|
}
|
|
else
|
|
{
|
|
RegDeleteValue(key, "http_proxy");
|
|
}
|
|
|
|
RegSetValueEx(key, "cdda", 0, REG_DWORD, (LPBYTE)&setting_cdda, 4);
|
|
RegSetValueEx(key, "jitter", 0, REG_DWORD, (LPBYTE)&setting_jitter, 4);
|
|
RegSetValueEx(key, "forceaspi", 0, REG_DWORD, (LPBYTE)&setting_forceaspi, 4);
|
|
RegSetValueEx(key, "cdletter", 0, REG_SZ, setting_cdletter, (int)strlen(setting_cdletter) + 1);
|
|
|
|
RegCloseKey(key);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
A slow and quite unscientific 4th order low pass filter, which leaves the source mix
|
|
buffer in tact, and returns a pointer to the new 'dirty' buffer.
|
|
|
|
[PARAMETERS]
|
|
'originalbuffer' Pointer to the original mixbuffer, not any buffers passed down
|
|
through the dsp chain. They are in newbuffer.
|
|
'newbuffer' Pointer to buffer passed from previous DSP unit.
|
|
'length' Length in SAMPLES of buffer being passed.
|
|
'param' User parameter. In this case it is a pointer to LowPassBuffer.
|
|
|
|
[RETURN_VALUE]
|
|
A pointer to the new modified lowpass buffer, leaving the original buffer untouched.
|
|
|
|
[REMARKS]
|
|
Leaving the original source data untouched means we still have clean source data to
|
|
work with using other chained filters.
|
|
]
|
|
*/
|
|
void * F_CALLBACKAPI LowPassCallback(void *originalbuffer, void *newbuffer, int length, void *userdata)
|
|
{
|
|
int count;
|
|
int mixertype = FSOUND_GetMixer();
|
|
union sample
|
|
{
|
|
void *vptr;
|
|
signed int *dptr;
|
|
signed short *wptr;
|
|
float *fptr;
|
|
};
|
|
union sample srcleft, srcright, destleft, destright;
|
|
|
|
/*
|
|
Must be 16bit stereo integer buffer.. sorry blendmode (32bit) and fpu (32bit float) dont support this.
|
|
*/
|
|
srcleft.vptr = newbuffer;
|
|
destleft.vptr = userdata;
|
|
if (mixertype == FSOUND_MIXER_QUALITY_FPU)
|
|
{
|
|
srcright.fptr = (float *)newbuffer + 1;
|
|
destright.fptr = (float *)userdata + 1;
|
|
}
|
|
else if (mixertype == FSOUND_MIXER_MMXP5 || mixertype == FSOUND_MIXER_MMXP6 || mixertype == FSOUND_MIXER_QUALITY_MMXP5 || mixertype == FSOUND_MIXER_QUALITY_MMXP6)
|
|
{
|
|
srcright.wptr = (signed short *)newbuffer + 1;
|
|
destright.wptr = (signed short *)userdata + 1;
|
|
}
|
|
else
|
|
{
|
|
srcright.dptr = (signed int *)newbuffer + 1;
|
|
destright.dptr = (signed int *)userdata + 1;
|
|
}
|
|
|
|
length <<= 1; /* *2 for stereo (number of 16 bit samples) */
|
|
|
|
for (count=0; count<length; count+=2)
|
|
{
|
|
signed int l, r;
|
|
float fl, fr;
|
|
|
|
if (mixertype == FSOUND_MIXER_QUALITY_FPU)
|
|
{
|
|
fl = srcleft.fptr[count];
|
|
fr = srcright.fptr[count];
|
|
}
|
|
else if (mixertype == FSOUND_MIXER_MMXP5 || mixertype == FSOUND_MIXER_MMXP6 || mixertype == FSOUND_MIXER_QUALITY_MMXP5 || mixertype == FSOUND_MIXER_QUALITY_MMXP6)
|
|
{
|
|
fl = (float)srcleft.wptr[count];
|
|
fr = (float)srcright.wptr[count];
|
|
}
|
|
else
|
|
{
|
|
fl = (float)(srcleft.dptr[count]);
|
|
fr = (float)(srcright.dptr[count]);
|
|
}
|
|
|
|
/*
|
|
This isnt correct lowpassing l and r with the same filter (ie it should have one
|
|
filter per channel) but its a quick hack and sounds ok for the moment.
|
|
*/
|
|
l = (signed int)LowPass_Filter(fl);
|
|
r = (signed int)LowPass_Filter(fr);
|
|
|
|
if (l < -32768) l = -32768;
|
|
else if (l > 32767) l = 32767;
|
|
if (r < -32768) r = -32768;
|
|
else if (r > 32767) r = 32767;
|
|
|
|
if (mixertype == FSOUND_MIXER_QUALITY_FPU)
|
|
{
|
|
destleft.fptr[count] = (float)l;
|
|
destright.fptr[count] = (float)r;
|
|
}
|
|
else if (mixertype == FSOUND_MIXER_MMXP5 || mixertype == FSOUND_MIXER_MMXP6 || mixertype == FSOUND_MIXER_QUALITY_MMXP5 || mixertype == FSOUND_MIXER_QUALITY_MMXP6)
|
|
{
|
|
destleft.wptr[count] = (signed short)l;
|
|
destright.wptr[count] = (signed short)r;
|
|
}
|
|
else
|
|
{
|
|
destleft.dptr[count] = l;
|
|
destright.dptr[count] = r;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Data has been copied into new buffer, old buffer is still in tact (clean) for another filter
|
|
*/
|
|
return userdata;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
Simple echo callback. It copies the data into its own history buffer, then copies the data back in.
|
|
|
|
[PARAMETERS]
|
|
'originalbuffer' Pointer to the original mixbuffer, not any buffers passed down
|
|
through the dsp chain. They are in newbuffer.
|
|
'newbuffer' Pointer to buffer passed from previous DSP unit.
|
|
'length' Length in SAMPLES of buffer being passed.
|
|
'param' User parameter. In this case it is a pointer to EchoBuffer.
|
|
|
|
[RETURN_VALUE]
|
|
A pointer to the new modified buffer. The buffer passed in has been modified, and
|
|
EchoBuffer has just been filled with a copy of the original information to keep
|
|
an echo history for later.
|
|
|
|
[REMARKS]
|
|
All the <<2 stuff is to convert samples to bytes, as all offsets and lengths are based
|
|
on samples not bytes. For mmx the output size is 4 bytes per sample.
|
|
|
|
[SEE_ALSO]
|
|
LowPassCallback
|
|
]
|
|
*/
|
|
void * F_CALLBACKAPI EchoCallback(void *originalbuffer, void *newbuffer, int length, void *userdata)
|
|
{
|
|
int mixertype = FSOUND_GetMixer();
|
|
char *echobuff = userdata;
|
|
int bytesperoutputsample;
|
|
int count;
|
|
union sample
|
|
{
|
|
void *vptr;
|
|
signed int *dptr;
|
|
signed short *wptr;
|
|
float *fptr;
|
|
};
|
|
|
|
|
|
if (mixertype == FSOUND_MIXER_MMXP5 || mixertype == FSOUND_MIXER_MMXP6 || mixertype == FSOUND_MIXER_QUALITY_MMXP5 || mixertype == FSOUND_MIXER_QUALITY_MMXP6)
|
|
{
|
|
bytesperoutputsample = 4; // 16bit stereo
|
|
}
|
|
else
|
|
{
|
|
bytesperoutputsample = 8; // 32bit stereo
|
|
}
|
|
|
|
/*
|
|
Echobuff is a ringbuffer that we copy the mixbuffer to.
|
|
If the length of the write exceeds the end of the echo buffer,
|
|
then do the mix in 2 parts, the end part, and the start part.
|
|
*/
|
|
if (EchoOffset + length > EchoLen)
|
|
{
|
|
int taillen = EchoLen - EchoOffset;
|
|
int startlen = length - taillen;
|
|
|
|
/*
|
|
Feedback history from echo buffer into mixbuffer
|
|
*/
|
|
FSOUND_DSP_MixBuffers(newbuffer, echobuff+(EchoOffset << 2), taillen, outputfreq, 128, FSOUND_STEREOPAN, FSOUND_STEREO | FSOUND_16BITS);
|
|
FSOUND_DSP_MixBuffers((char *)newbuffer + (taillen * bytesperoutputsample), echobuff, startlen, outputfreq, 128, FSOUND_STEREOPAN, FSOUND_STEREO | FSOUND_16BITS);
|
|
|
|
/*
|
|
Now copy result into echo buffer again for next time
|
|
*/
|
|
{
|
|
signed short *dest;
|
|
union sample src;
|
|
|
|
dest = (signed short *)(echobuff + (EchoOffset << 2));
|
|
src.vptr = newbuffer;
|
|
|
|
for (count=0; count < taillen * 2; count++)
|
|
{
|
|
int val;
|
|
|
|
if (mixertype == FSOUND_MIXER_QUALITY_FPU)
|
|
{
|
|
val = (int)src.fptr[count];
|
|
}
|
|
else if (mixertype == FSOUND_MIXER_MMXP5 || mixertype == FSOUND_MIXER_MMXP6 || mixertype == FSOUND_MIXER_QUALITY_MMXP5 || mixertype == FSOUND_MIXER_QUALITY_MMXP6)
|
|
{
|
|
val = (int)src.wptr[count];
|
|
}
|
|
else
|
|
{
|
|
val = (int)src.dptr[count];
|
|
}
|
|
|
|
val = (val > 32767 ? 32767 : val < -32768 ? -32768 : val);
|
|
dest[count] = val;
|
|
}
|
|
}
|
|
{
|
|
signed short *dest;
|
|
union sample src;
|
|
|
|
dest = (signed short *)echobuff; // always 16bit
|
|
src.vptr = (char *)newbuffer + (taillen * bytesperoutputsample);
|
|
|
|
for (count=0; count < startlen * 2; count++)
|
|
{
|
|
int val;
|
|
|
|
if (mixertype == FSOUND_MIXER_QUALITY_FPU)
|
|
{
|
|
val = (int)src.fptr[count];
|
|
}
|
|
else if (mixertype == FSOUND_MIXER_MMXP5 || mixertype == FSOUND_MIXER_MMXP6 || mixertype == FSOUND_MIXER_QUALITY_MMXP5 || mixertype == FSOUND_MIXER_QUALITY_MMXP6)
|
|
{
|
|
val = (int)src.wptr[count];
|
|
}
|
|
else
|
|
{
|
|
val = (int)src.dptr[count];
|
|
}
|
|
|
|
val = (val > 32767 ? 32767 : val < -32768 ? -32768 : val);
|
|
dest[count] = val;
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
No wrapping echo buffer write, just do a straight write
|
|
*/
|
|
else
|
|
{
|
|
/*
|
|
Feedback history from echo buffer into mixbuffer
|
|
*/
|
|
FSOUND_DSP_MixBuffers(newbuffer, echobuff + (EchoOffset << 2), length, outputfreq, 128, FSOUND_STEREOPAN, FSOUND_STEREO | FSOUND_16BITS);
|
|
|
|
/*
|
|
Now copy result into echo buffer again for next time
|
|
*/
|
|
{
|
|
signed short *dest;
|
|
union sample src = { newbuffer };
|
|
|
|
dest = (signed short *)(echobuff + (EchoOffset << 2));
|
|
|
|
for (count=0; count < length * 2; count++)
|
|
{
|
|
int val;
|
|
|
|
if (mixertype == FSOUND_MIXER_QUALITY_FPU)
|
|
{
|
|
val = (int)src.fptr[count];
|
|
}
|
|
else if (mixertype == FSOUND_MIXER_MMXP5 || mixertype == FSOUND_MIXER_MMXP6 || mixertype == FSOUND_MIXER_QUALITY_MMXP5 || mixertype == FSOUND_MIXER_QUALITY_MMXP6)
|
|
{
|
|
val = (int)src.wptr[count];
|
|
}
|
|
else
|
|
{
|
|
val = (int)src.dptr[count];
|
|
}
|
|
val = (val > 32767 ? 32767 : val < -32768 ? -32768 : val);
|
|
dest[count] = val;
|
|
}
|
|
}
|
|
}
|
|
|
|
EchoOffset+=length;
|
|
if (EchoOffset >= EchoLen)
|
|
{
|
|
EchoOffset -= EchoLen;
|
|
}
|
|
|
|
/*
|
|
Echo history has been mixed into new buffer, so return it.
|
|
*/
|
|
return newbuffer;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
Buffering code for oscilliscope.
|
|
|
|
[PARAMETERS]
|
|
'originalbuffer' Pointer to the original mixbuffer, not any buffers passed down
|
|
through the dsp chain. They are in newbuffer.
|
|
'newbuffer' Pointer to buffer passed from previous DSP unit.
|
|
'length' Length in SAMPLES of buffer being passed.
|
|
'param' User parameter. In this case it is 0.
|
|
|
|
[RETURN_VALUE]
|
|
A pointer to the new modified buffer.
|
|
|
|
[REMARKS]
|
|
All the <<2 stuff is to convert samples to bytes, as all offsets and lengths are based
|
|
on samples not bytes. For mmx the output size is 4 bytes per sample.
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
void * F_CALLBACKAPI OscCallback(void *originalbuffer, void *newbuffer, int length, void *userdata)
|
|
{
|
|
int mixertype = FSOUND_GetMixer();
|
|
int count;
|
|
int totalblocks;
|
|
signed short *dest;
|
|
|
|
totalblocks = FSOUND_DSP_GetBufferLengthTotal() / FSOUND_DSP_GetBufferLength();
|
|
|
|
/*
|
|
Convert and downmix into a mono short int buffer.
|
|
*/
|
|
|
|
dest = &OscBuffer[OscBlock * FSOUND_DSP_GetBufferLength()];
|
|
|
|
if (mixertype == FSOUND_MIXER_QUALITY_FPU)
|
|
{
|
|
float *src = (float *)newbuffer;
|
|
|
|
for (count=0; count < length; count++)
|
|
{
|
|
dest[count] = (signed short)((src[count << 1] + src[(count << 1) + 1]) * 0.5f);
|
|
}
|
|
}
|
|
else if (mixertype == FSOUND_MIXER_MMXP5 || mixertype == FSOUND_MIXER_MMXP6 || mixertype == FSOUND_MIXER_QUALITY_MMXP5 || mixertype == FSOUND_MIXER_QUALITY_MMXP6)
|
|
{
|
|
signed short *src = (signed short *)newbuffer;
|
|
|
|
for (count=0; count < length; count++)
|
|
{
|
|
dest[count] = (signed short)(((int)src[count << 1] + (int)src[(count << 1) + 1]) >> 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
signed int *src = (signed int *)newbuffer;
|
|
|
|
for (count=0; count < length; count++)
|
|
{
|
|
dest[count] = (signed short)((src[count << 1] + src[(count << 1) + 1]) >> 1);
|
|
}
|
|
}
|
|
|
|
OscBlock++;
|
|
if (OscBlock >= totalblocks)
|
|
{
|
|
OscBlock = 0;
|
|
}
|
|
|
|
return newbuffer;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
Plots a graphic spectrum using FSOUND_DSP_GetSpectrum
|
|
|
|
[PARAMETERS]
|
|
'hdc' Handle to device context to paint to.
|
|
|
|
[RETURN_VALUE]
|
|
void
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
FSOUND_DSP_GetSpectrum
|
|
FSOUND_DSP_GetFFTUnit
|
|
PlotOscilliscope
|
|
]
|
|
*/
|
|
void PlotSpectrum(HDC hdc)
|
|
{
|
|
int count, count2;
|
|
float *spectrum;
|
|
|
|
spectrum = FSOUND_DSP_GetSpectrum(); /* returns an array of 512 floats */
|
|
if (!spectrum)
|
|
{
|
|
return;
|
|
}
|
|
|
|
memset(GraphicWindowBitmapData, 0, GRAPHICWINDOW_WIDTH * GRAPHICWINDOW_HEIGHT * sizeof(RGBQUAD));
|
|
|
|
/*
|
|
Spectrum graphic is 256 entries wide, and the spectrum is 512 entries.
|
|
The upper band of frequencies at 44khz is pretty boring (ie 11-22khz), so we are only
|
|
going to display the first 256 frequencies, or (0-11khz)
|
|
*/
|
|
for (count=0; count < GRAPHICWINDOW_WIDTH; count++)
|
|
{
|
|
RGBQUAD *pixel;
|
|
int y;
|
|
|
|
#define calcoffset(_x, _y) (GRAPHICWINDOW_WIDTH * _y) + _x
|
|
|
|
y = (int)(spectrum[count] * 4.0f * (float)GRAPHICWINDOW_HEIGHT);
|
|
if (y >= GRAPHICWINDOW_HEIGHT)
|
|
{
|
|
y = GRAPHICWINDOW_HEIGHT - 1;
|
|
}
|
|
|
|
for (count2=0; count2<y; count2++)
|
|
{
|
|
pixel = &GraphicWindowBitmapData[calcoffset(count, count2)];
|
|
pixel->rgbRed = count2 << 1;
|
|
pixel->rgbGreen = 0xFF - (count2 << 1);
|
|
pixel->rgbBlue = 0x1F;
|
|
}
|
|
}
|
|
|
|
|
|
SetDIBitsToDevice(
|
|
hdc, // Target device HDC
|
|
graphic_window_x,
|
|
graphic_window_y,
|
|
GRAPHICWINDOW_WIDTH, // Destination width
|
|
GRAPHICWINDOW_HEIGHT, // Destination height
|
|
0, // X source position
|
|
0, // Adjusted Y source position
|
|
(UINT)0, // Start scan line
|
|
GraphicWindowBitmap.bmiHeader.biHeight, // Scan lines present
|
|
GraphicWindowBitmapData, // Image data
|
|
&GraphicWindowBitmap, // DIB header
|
|
DIB_RGB_COLORS); // Type of palette
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
Plots an oscilliscope.
|
|
|
|
[PARAMETERS]
|
|
'hdc' Handle to device context to paint to.
|
|
|
|
[RETURN_VALUE]
|
|
void
|
|
|
|
[REMARKS]
|
|
The oscilliscope data is buffer because the block of data received in a DSP unit is the block
|
|
being mixed ahead of time, not the block that is AUDIBLE.
|
|
|
|
[SEE_ALSO]
|
|
PlotSpectrum
|
|
]
|
|
*/
|
|
void PlotOscilliscope(HDC hdc)
|
|
{
|
|
memset(GraphicWindowBitmapData, 0, GRAPHICWINDOW_WIDTH * GRAPHICWINDOW_HEIGHT * sizeof(RGBQUAD));
|
|
|
|
if (OscBuffer)
|
|
{
|
|
int count, count2, offset;
|
|
float xoff, step;
|
|
signed short *src;
|
|
/*
|
|
The next pcmblock (Oscblock + 1) is the one that is audible.
|
|
*/
|
|
offset = (OscBlock + 1) * FSOUND_DSP_GetBufferLength();
|
|
if (offset >= FSOUND_DSP_GetBufferLengthTotal())
|
|
{
|
|
offset -= FSOUND_DSP_GetBufferLengthTotal();
|
|
}
|
|
|
|
src = &OscBuffer[offset];
|
|
|
|
/*
|
|
xoff is the x position that is scaled lookup of the dsp block according to the graphical
|
|
window size.
|
|
*/
|
|
xoff = 0;
|
|
step = (float)FSOUND_DSP_GetBufferLength() / (float)GRAPHICWINDOW_WIDTH;
|
|
|
|
for (count=0; count < GRAPHICWINDOW_WIDTH; count++)
|
|
{
|
|
RGBQUAD *pixel;
|
|
int x, y, y2;
|
|
|
|
#define calcoffset(_x, _y) (GRAPHICWINDOW_WIDTH * _y) + _x
|
|
|
|
x = (int)xoff;
|
|
y = (int)(((float)src[x] + 32768.0f) / 65536.0f * (float)GRAPHICWINDOW_HEIGHT);
|
|
y2 = (int)(((float)src[x+(int)step] + 32768.0f) / 65536.0f * (float)GRAPHICWINDOW_HEIGHT);
|
|
|
|
if (y > y2)
|
|
{
|
|
int tmp = y;
|
|
y = y2;
|
|
y2 = tmp;
|
|
}
|
|
|
|
for (count2=y; count2<=y2; count2++)
|
|
{
|
|
pixel = &GraphicWindowBitmapData[calcoffset(count, count2)];
|
|
pixel->rgbRed = 0xff;
|
|
pixel->rgbGreen = 0xff;
|
|
pixel->rgbBlue = 0xaf;
|
|
}
|
|
|
|
xoff += step;
|
|
}
|
|
}
|
|
|
|
|
|
SetDIBitsToDevice(
|
|
hdc, // Target device HDC
|
|
graphic_window_x,
|
|
graphic_window_y,
|
|
GRAPHICWINDOW_WIDTH, // Destination width
|
|
GRAPHICWINDOW_HEIGHT, // Destination height
|
|
0, // X source position
|
|
0, // Adjusted Y source position
|
|
(UINT)0, // Start scan line
|
|
GraphicWindowBitmap.bmiHeader.biHeight, // Scan lines present
|
|
GraphicWindowBitmapData, // Image data
|
|
&GraphicWindowBitmap, // DIB header
|
|
DIB_RGB_COLORS); // Type of palette
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
Playlist *ParsePlaylist(char *name)
|
|
{
|
|
struct _stat buf;
|
|
FILE *fp;
|
|
char *filebuf, *p;
|
|
Playlist *playlist = 0;
|
|
int buflen, count, i;
|
|
|
|
if (!name || stricmp((const char *)".pls", (const char *)(&name[strlen(name) - 4])))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (_stat(name, &buf))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
buflen = buf.st_size + 1;
|
|
|
|
filebuf = (char *)malloc(buflen);
|
|
if (!filebuf)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
fp = fopen(name, "rb");
|
|
if (!fp)
|
|
{
|
|
free(filebuf);
|
|
return 0;
|
|
}
|
|
|
|
if (fread(filebuf, 1, buf.st_size, fp) != (unsigned int)buf.st_size)
|
|
{
|
|
fclose(fp);
|
|
free(filebuf);
|
|
return 0;
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
filebuf[buflen - 1] = 0;
|
|
|
|
p = stristr(filebuf, "NumberOfEntries=");
|
|
if (!p)
|
|
{
|
|
goto ERR;
|
|
}
|
|
|
|
p += 16;
|
|
count = atoi(p);
|
|
|
|
if (!count)
|
|
{
|
|
goto ERR;
|
|
}
|
|
|
|
playlist = (Playlist *)calloc(sizeof(Playlist), 1);
|
|
if (!playlist)
|
|
{
|
|
goto ERR;
|
|
}
|
|
|
|
playlist->count = count;
|
|
|
|
playlist->name = (char **)calloc(sizeof(char *) * count, 1);
|
|
if (!playlist->name)
|
|
{
|
|
goto ERR;
|
|
}
|
|
|
|
playlist->displayname = (char **)calloc(sizeof(char *) * count, 1);
|
|
if (!playlist->displayname)
|
|
{
|
|
goto ERR;
|
|
}
|
|
|
|
for (i=0;i < count;i++)
|
|
{
|
|
char tmp[32];
|
|
char *filename, *displayname, *t;
|
|
|
|
filename = displayname = 0;
|
|
|
|
sprintf(tmp, "File%d=", i + 1);
|
|
p = strstr(filebuf, tmp);
|
|
if (p)
|
|
{
|
|
p += strlen(tmp);
|
|
t = p;
|
|
for (;*t && (*t != 0xa) && (*t != 0xd);t++);
|
|
if (*t)
|
|
{
|
|
char tmpc = *t;
|
|
*t = 0;
|
|
filename = strdup(p);
|
|
*t = tmpc;
|
|
}
|
|
}
|
|
|
|
if (strncmp(filename, "http://", 7) && strncmp(filename, "http:\\\\", 7))
|
|
{
|
|
char *tmpname = strdup(filename);
|
|
p = &tmpname[strlen(tmpname) - 1];
|
|
for (;(p > tmpname) && (*p != '\\') && (*p != '/');p--);
|
|
if ((*p == '\\') || (*p == '/'))
|
|
{
|
|
p++;
|
|
}
|
|
displayname = strdup(p);
|
|
free(tmpname);
|
|
}
|
|
|
|
playlist->name[i] = filename;
|
|
playlist->displayname[i] = displayname;
|
|
}
|
|
|
|
free(filebuf);
|
|
return playlist;
|
|
|
|
ERR:
|
|
FreePlaylist(playlist);
|
|
free(filebuf);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
signed char FreePlaylist(Playlist *playlist)
|
|
{
|
|
int i;
|
|
|
|
if (!playlist)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (playlist->name)
|
|
{
|
|
for (i=0;i < playlist->count;i++)
|
|
{
|
|
if (playlist->name[i])
|
|
{
|
|
free(playlist->name[i]);
|
|
}
|
|
}
|
|
|
|
free(playlist->name);
|
|
}
|
|
|
|
if (playlist->displayname)
|
|
{
|
|
for (i=0;i < playlist->count;i++)
|
|
{
|
|
if (playlist->displayname[i])
|
|
{
|
|
free(playlist->displayname[i]);
|
|
}
|
|
}
|
|
|
|
free(playlist->displayname);
|
|
}
|
|
|
|
free(playlist);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
Returns FALSE if there's no more room in the song list
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
signed char AddFileToSongList(char *name, char *displayname)
|
|
{
|
|
FMUSIC_MODULE *mod = NULL;
|
|
FSOUND_STREAM *stream = NULL;
|
|
int currsong = 0;
|
|
char s[256];
|
|
|
|
if (!strncmp(name, "http://", 7) || !strncmp(name, "http:\\\\", 7))
|
|
{
|
|
displayname = name;
|
|
}
|
|
else
|
|
{
|
|
stream = NULL;
|
|
mod = FMUSIC_LoadSong(name);
|
|
if (!mod)
|
|
{
|
|
stream = FSOUND_Stream_Open(name, FSOUND_NORMAL | FSOUND_2D | FSOUND_MPEGACCURATE | FSOUND_NONBLOCKING, 0, 0);
|
|
}
|
|
|
|
if (!mod && !stream)
|
|
{
|
|
MessageBox(0, FMOD_ErrorString(FSOUND_GetError()), "Loading a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
return TRUE;
|
|
}
|
|
|
|
if (mod)
|
|
{
|
|
if (FMUSIC_GetType(mod) != FMUSIC_TYPE_IT) /* IT has its own master volume setting */
|
|
{
|
|
FMUSIC_SetMasterVolume(mod, 192);
|
|
}
|
|
if (FMUSIC_GetType(mod) == FMUSIC_TYPE_MOD || FMUSIC_GetType(mod) == FMUSIC_TYPE_S3M)
|
|
{
|
|
FMUSIC_SetPanSeperation(mod, 0.85f); /* 15% crossover */
|
|
}
|
|
}
|
|
}
|
|
|
|
currsong = (int)SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0);
|
|
if (currsong >= MAXSONGS)
|
|
{
|
|
MessageBox(0, "Error. Unable to fit any more songs in.. please restart app", "Loading a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
return FALSE;
|
|
}
|
|
|
|
if (mod)
|
|
{
|
|
song[currsong].mod = mod;
|
|
song[currsong].stream = NULL;
|
|
song[currsong].url = NULL;
|
|
}
|
|
else if (stream)
|
|
{
|
|
song[currsong].stream = stream;
|
|
song[currsong].mod = NULL;
|
|
song[currsong].url = NULL;
|
|
}
|
|
else
|
|
{
|
|
song[currsong].stream = NULL;
|
|
song[currsong].mod = NULL;
|
|
song[currsong].url = strdup(name);
|
|
}
|
|
|
|
strcpy(s, displayname);
|
|
song[currsong].listname = strdup(displayname);
|
|
|
|
SendMessage(songlist_hwnd, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR)s);
|
|
UpdateWindow(songlist_hwnd);
|
|
SendMessage(songlist_hwnd, LB_SETCURSEL, currsong, 0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
void LoadSong()
|
|
{
|
|
OPENFILENAME ofn; /* common dialog box structure */
|
|
char szDirName[MAX_PATH]; /* directory string */
|
|
char szFile[20481]; /* filename string */
|
|
char szFileTitle[4096]; /* filename string */
|
|
|
|
/*
|
|
Obtain the system directory name and store it in szDirName.
|
|
*/
|
|
GetSystemDirectory(szDirName, sizeof(szDirName));
|
|
|
|
/*
|
|
Place the terminating null character in the szFile.
|
|
*/
|
|
szFile[0] = '\0';
|
|
szFileTitle[0] = '\0';
|
|
|
|
/*
|
|
Set the members of the OPENFILENAME structure.
|
|
*/
|
|
memset(&ofn, 0, sizeof(ofn));
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.hwndOwner = mainhwnd;
|
|
ofn.lpstrTitle = "Open\0";
|
|
ofn.lpstrFilter = "All song Types\0*.MOD;*.S3M;*.XM;*.IT;*.MID;*.RMI;*.SGT;*.WAV;*.MP2;*.MP3;*.OGG;*.WMA;*.ASF;*.AIFF;*.PLS;*.FSB;*.OXM\0Microsoft WAV (*.WAV)\0*.WAV\0MP2/MP3 (*.MP3 *.MP2)\0*.MP2;*.MP3\0Ogg Vorbis (*.OGG)\0*.OGG\0Windows Media Format (*.WMA *.ASF)\0*.WMA;*.ASF\0Audio Interchange File Format (*.AIFF)\0*.AIFF\0MIDI / DirectMusic Files (*.MID,*.RMI,*.SGT)\0*.MID;*.RMI;*.SGT\0Impulse Tracker (*.IT)\0*.IT\0FastTracker2 (*.XM)\0*.XM\0ScreamTracker 3 (*.S3M)\0*.S3M\0Protracker/FastTracker (*.MOD)\0*.MOD\0Playlist (*.PLS)\0*.PLS\0FMOD Sample Bank (*.FSB)\0*.FSB\0Ogg commpress XM (*.OXM)\0*.OXM\0All files (*.*)\0*.*\0\0";
|
|
ofn.lpstrCustomFilter = NULL;
|
|
ofn.nFilterIndex = 1;
|
|
ofn.lpstrFile = szFile;
|
|
ofn.nMaxFile = 20480; /* Huge value allows many files to be multi-selected */
|
|
ofn.lpstrFileTitle = szFileTitle;
|
|
ofn.nMaxFileTitle = 2048;
|
|
ofn.lpstrInitialDir = ".\0";
|
|
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT;
|
|
|
|
/*
|
|
Display the Open dialog box.
|
|
*/
|
|
if (GetOpenFileName(&ofn))
|
|
{
|
|
char *path = ofn.lpstrFile;
|
|
char *fname = ofn.lpstrFile;
|
|
char name[256];
|
|
|
|
/*
|
|
Single file
|
|
*/
|
|
if (ofn.nFileOffset)
|
|
{
|
|
/*
|
|
Skip to the first filename
|
|
*/
|
|
fname +=ofn.nFileOffset;
|
|
*(fname-1) = 0; /* clear the backslash before the filename so the loop below handles it */
|
|
}
|
|
/*
|
|
Multiple files
|
|
*/
|
|
else
|
|
{
|
|
while (*fname++); /* search to the first filename */
|
|
}
|
|
|
|
do
|
|
{
|
|
Playlist *p;
|
|
int i;
|
|
|
|
/*
|
|
Put path in name
|
|
*/
|
|
strcpy(name, path);
|
|
strcat(name, "\\");
|
|
strcat(name, fname);
|
|
|
|
/*
|
|
Open the file.
|
|
*/
|
|
p = ParsePlaylist(name);
|
|
if (p)
|
|
{
|
|
for (i=0;i < p->count;i++)
|
|
{
|
|
AddFileToSongList(p->name[i], p->displayname[i]);
|
|
}
|
|
|
|
FreePlaylist(p);
|
|
}
|
|
else
|
|
{
|
|
AddFileToSongList(name, fname);
|
|
}
|
|
|
|
while (*fname++);
|
|
|
|
Sleep(1);
|
|
|
|
} while (*fname);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
void LoadURL()
|
|
{
|
|
if (DialogBox(g_hinst, MAKEINTRESOURCE(IDD_LOADURLDLG), mainhwnd, FMOD_LoadURLDlgProc))
|
|
{
|
|
if (strlen(url_to_load))
|
|
{
|
|
int songid = (int)SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0);
|
|
if (songid >= MAXSONGS)
|
|
{
|
|
MessageBox(0, "Error. Unable to fit any more songs in.. please restart app", "Loading a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
return;
|
|
}
|
|
|
|
song[songid].mod = 0;
|
|
song[songid].stream = 0;
|
|
song[songid].url = strdup(url_to_load);
|
|
song[songid].listname = strdup(url_to_load);
|
|
|
|
SendMessage(songlist_hwnd, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR)song[songid].url);
|
|
UpdateWindow(songlist_hwnd);
|
|
SendMessage(songlist_hwnd, LB_SETCURSEL, songid, 0);
|
|
|
|
UpdateNetStreamInfo(songid, TRUE, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
void LoadCD()
|
|
{
|
|
int numsongs, songid, i;
|
|
char tmp[256];
|
|
|
|
/*
|
|
Bomb out if there's a cdda_stream already loading
|
|
*/
|
|
if (cdda_stream)
|
|
{
|
|
if (FSOUND_Stream_GetOpenState(cdda_stream) == -2)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
DeleteAllCDTracks();
|
|
|
|
if (cdda_stream)
|
|
{
|
|
FSOUND_Stream_Close(cdda_stream);
|
|
cdda_stream = 0;
|
|
cdda_channel = -1;
|
|
}
|
|
|
|
if (setting_cdda)
|
|
{
|
|
/*
|
|
Use the "!" qualifier to specify "quick open" mode so we can populate the playlist and get
|
|
the track lengths quickly
|
|
*/
|
|
sprintf(tmp, "%s*!j", setting_cdletter);
|
|
cdda_stream = FSOUND_Stream_Open(tmp, FSOUND_NORMAL, 0, 0);
|
|
if (!cdda_stream)
|
|
{
|
|
MessageBox(mainhwnd, "Couldn't open cdda stream", "Error", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
}
|
|
|
|
numsongs = FSOUND_Stream_GetNumSubStreams(cdda_stream);
|
|
for (i=0;i < numsongs;i++)
|
|
{
|
|
songid = (int)SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0);
|
|
if (songid >= MAXSONGS)
|
|
{
|
|
MessageBox(0, "Error. Unable to fit any more songs in.. please restart app", "Loading a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
break;
|
|
}
|
|
|
|
memset(&song[songid], 0, sizeof(song[songid]));
|
|
|
|
sprintf(tmp, "Track %02d", i + 1);
|
|
song[songid].listname = strdup(tmp);
|
|
song[songid].channel = -1;
|
|
song[songid].cdtrack = i + 1;
|
|
|
|
SendMessage(songlist_hwnd, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR)tmp);
|
|
UpdateWindow(songlist_hwnd);
|
|
}
|
|
|
|
SendMessage(songlist_hwnd, LB_SETCURSEL, 0, 0);
|
|
|
|
numsongs = (int)SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0);
|
|
for (i=0;i < numsongs;i++)
|
|
{
|
|
if (song[i].cdtrack)
|
|
{
|
|
FSOUND_Stream_SetSubStream(cdda_stream, song[i].cdtrack - 1);
|
|
song[i].cdtrack_length = FSOUND_Stream_GetLengthMs(cdda_stream);
|
|
}
|
|
}
|
|
|
|
FSOUND_Stream_Close(cdda_stream);
|
|
|
|
/*
|
|
Now do a normal non-blocking open to setup the stream properly for playing
|
|
*/
|
|
strcpy(tmp, setting_cdletter);
|
|
strcat(tmp, "*");
|
|
if (!setting_jitter)
|
|
{
|
|
strcat(tmp, "j");
|
|
}
|
|
if (setting_forceaspi)
|
|
{
|
|
strcat(tmp, "a");
|
|
}
|
|
cdda_stream = FSOUND_Stream_Open(tmp, FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0);
|
|
if (!cdda_stream)
|
|
{
|
|
MessageBox(mainhwnd, "Couldn't open cdda stream", "Error", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
}
|
|
|
|
cdda_stream_state = -2;
|
|
}
|
|
else
|
|
{
|
|
numsongs = FSOUND_CD_GetNumTracks(cddevice);
|
|
if (numsongs)
|
|
{
|
|
for (i=0;i < numsongs;i++)
|
|
{
|
|
songid = (int)SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0);
|
|
if (songid >= MAXSONGS)
|
|
{
|
|
MessageBox(0, "Error. Unable to fit any more songs in.. please restart app", "Loading a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
break;
|
|
}
|
|
|
|
memset(&song[songid], 0, sizeof(song[songid]));
|
|
|
|
sprintf(tmp, "Track %02d", i + 1);
|
|
song[songid].listname = strdup(tmp);
|
|
song[songid].channel = -1;
|
|
song[songid].cdtrack = i + 1;
|
|
song[songid].cdtrack_length = 0;
|
|
|
|
SendMessage(songlist_hwnd, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR)tmp);
|
|
UpdateWindow(songlist_hwnd);
|
|
SendMessage(songlist_hwnd, LB_SETCURSEL, songid, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
void DeleteAllCDTracks()
|
|
{
|
|
int numsongs, i;
|
|
|
|
StopCDTrack();
|
|
|
|
numsongs = (int)SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0);
|
|
for (i=0;i < numsongs;i++)
|
|
{
|
|
if (song[i].cdtrack)
|
|
{
|
|
DeleteSong(i);
|
|
i = -1; /* Force it to start at the start */
|
|
numsongs--;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
signed char StopCDTrack()
|
|
{
|
|
int songid;
|
|
int numsongs = (int)SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0);
|
|
|
|
if (setting_cdda)
|
|
{
|
|
for (songid=0;songid < numsongs;songid++)
|
|
{
|
|
if (song[songid].cdtrack && (song[songid].channel != -1))
|
|
{
|
|
FSOUND_Stream_Stop(cdda_stream);
|
|
song[songid].channel = -1;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FSOUND_CD_Stop(cddevice);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
signed char PlayCDTrack(int songid, int looped)
|
|
{
|
|
unsigned int mode;
|
|
|
|
if (setting_cdda)
|
|
{
|
|
if (cdda_stream)
|
|
{
|
|
if ((song[songid].channel != -1) && FSOUND_IsPlaying(song[songid].channel))
|
|
{
|
|
int off = FSOUND_Stream_GetTime(cdda_stream);
|
|
int len = FSOUND_Stream_GetLengthMs(cdda_stream);
|
|
if ((off < len) && (off > 0))
|
|
{
|
|
/*
|
|
It's already playing
|
|
*/
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (FSOUND_Stream_GetOpenState(cdda_stream) == 0)
|
|
{
|
|
StopCDTrack();
|
|
|
|
FSOUND_Stream_SetSubStream(cdda_stream, song[songid].cdtrack - 1);
|
|
/*
|
|
It's non-blocking - wait for it to finish seeking
|
|
*/
|
|
while (FSOUND_Stream_GetOpenState(cdda_stream) != 0)
|
|
{
|
|
Sleep(100);
|
|
}
|
|
|
|
mode = FSOUND_Stream_GetMode(cdda_stream);
|
|
mode &= ~(FSOUND_LOOP_OFF | FSOUND_LOOP_NORMAL | FSOUND_LOOP_BIDI);
|
|
if (looped == FSOUND_CD_PLAYONCE)
|
|
{
|
|
mode |= FSOUND_LOOP_OFF;
|
|
}
|
|
else if (looped == FSOUND_CD_PLAYLOOPED)
|
|
{
|
|
mode |= FSOUND_LOOP_NORMAL;
|
|
}
|
|
else
|
|
{
|
|
mode |= FSOUND_LOOP_OFF;
|
|
}
|
|
FSOUND_Stream_SetMode(cdda_stream, mode);
|
|
|
|
song[songid].channel = FSOUND_Stream_Play(FSOUND_FREE, cdda_stream);
|
|
if (song[songid].channel < 0)
|
|
{
|
|
MessageBox(mainhwnd, "Error. Cannot start song", "Playing a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (FSOUND_CD_GetPaused(cddevice))
|
|
{
|
|
return FSOUND_CD_SetPaused(cddevice, FALSE);
|
|
}
|
|
else
|
|
{
|
|
FSOUND_CD_SetPlayMode(cddevice, looped);
|
|
return FSOUND_CD_Play(cddevice, song[songid].cdtrack);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
void DeleteSong(int songid)
|
|
{
|
|
int count;
|
|
|
|
if (song[songid].mod)
|
|
{
|
|
FMUSIC_FreeSong(song[songid].mod);
|
|
song[songid].mod = NULL;
|
|
}
|
|
else if (song[songid].stream)
|
|
{
|
|
FSOUND_Stream_Close(song[songid].stream);
|
|
song[songid].stream = NULL;
|
|
|
|
if (song[songid].url)
|
|
{
|
|
free(song[songid].url);
|
|
song[songid].url = 0;
|
|
}
|
|
}
|
|
else if (song[songid].cdtrack)
|
|
{
|
|
if (setting_cdda)
|
|
{
|
|
if (song[songid].channel && cdda_stream)
|
|
{
|
|
FSOUND_Stream_Stop(cdda_stream);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (FSOUND_CD_GetTrack(cddevice) == song[songid].cdtrack)
|
|
{
|
|
FSOUND_CD_Stop(cddevice);
|
|
}
|
|
}
|
|
}
|
|
|
|
song[songid].channel = -1;
|
|
|
|
if (song[songid].listname)
|
|
{
|
|
free(song[songid].listname);
|
|
song[songid].listname = 0;
|
|
}
|
|
|
|
if (song[songid].server_status)
|
|
{
|
|
free(song[songid].server_status);
|
|
song[songid].server_status = 0;
|
|
}
|
|
|
|
if (song[songid].title)
|
|
{
|
|
free(song[songid].title);
|
|
song[songid].title = 0;
|
|
}
|
|
|
|
if (song[songid].artist)
|
|
{
|
|
free(song[songid].artist);
|
|
song[songid].artist = 0;
|
|
}
|
|
|
|
song[songid].protocol = NULL;
|
|
song[songid].format = NULL;
|
|
song[songid].streamname = NULL;
|
|
song[songid].last_status = -1;
|
|
|
|
SendMessage(songlist_hwnd, LB_DELETESTRING, songid, 0);
|
|
|
|
/*
|
|
Shuffle down tunes
|
|
*/
|
|
for (count=songid+1; count<MAXSONGS; count++)
|
|
{
|
|
song[count-1] = song[count];
|
|
}
|
|
|
|
if (songid >= SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0))
|
|
{
|
|
songid = (int)SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0) - 1;
|
|
if (songid < 0)
|
|
{
|
|
songid = 0;
|
|
}
|
|
}
|
|
|
|
SendMessage(songlist_hwnd, LB_SETCURSEL, songid, 0);
|
|
|
|
UpdateStreamInfo(songid, TRUE);
|
|
UpdateNetStreamInfo(songid, TRUE, FALSE);
|
|
UpdateModInfo(songid, TRUE);
|
|
UpdateCDInfo(songid, TRUE);
|
|
SelectInfoWindow();
|
|
|
|
playlistsong = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
BOOL PlaySong(int index)
|
|
{
|
|
if (song[index].mod)
|
|
{
|
|
FMUSIC_SetLooping(song[index].mod, Button_GetCheck(GetDlgItem(mainhwnd, IDC_PLAYLOOPED)));
|
|
FMUSIC_PlaySong(song[index].mod);
|
|
}
|
|
else if (song[index].stream && !song[index].url)
|
|
{
|
|
FSOUND_Stream_SetMode(song[index].stream, Button_GetCheck(GetDlgItem(mainhwnd, IDC_PLAYLOOPED)) ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF);
|
|
song[index].channel = FSOUND_Stream_Play(FSOUND_FREE, song[index].stream);
|
|
}
|
|
else if (!song[index].stream && song[index].url)
|
|
{
|
|
song[index].stream = FSOUND_Stream_Open(song[index].url, FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0);
|
|
if (!song[index].stream)
|
|
{
|
|
MessageBox(mainhwnd, "ERROR: Couldn't open stream", "Playing a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if (song[index].cdtrack)
|
|
{
|
|
PlayCDTrack(index, Button_GetCheck(GetDlgItem(mainhwnd, IDC_PLAYLOOPED)) ? FSOUND_CD_PLAYLOOPED : FSOUND_CD_PLAYONCE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
signed char PlayNextSong()
|
|
{
|
|
playlistsong++;
|
|
|
|
if (playlistsong >= SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0))
|
|
{
|
|
playlistsong = 0;
|
|
}
|
|
|
|
PlaySong(playlistsong);
|
|
|
|
SendMessage(songlist_hwnd, LB_SETCURSEL, playlistsong, 0);
|
|
SelectInfoWindow();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
Create DSP units and reverb buffers etc
|
|
|
|
[PARAMETERS]
|
|
void
|
|
|
|
[RETURN_VALUE]
|
|
void
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
CloseDSP
|
|
]
|
|
*/
|
|
void InitDSP()
|
|
{
|
|
int bytesperoutputsample;
|
|
int mixertype = FSOUND_GetMixer();
|
|
|
|
DSP_Ready = FALSE;
|
|
|
|
if (mixertype == FSOUND_MIXER_MMXP5 || mixertype == FSOUND_MIXER_MMXP6 || mixertype == FSOUND_MIXER_QUALITY_MMXP5 || mixertype == FSOUND_MIXER_QUALITY_MMXP6)
|
|
{
|
|
bytesperoutputsample = 4; // 16bit stereo
|
|
}
|
|
else
|
|
{
|
|
bytesperoutputsample = 8; // 32bit stereo
|
|
}
|
|
|
|
/*
|
|
Initalize and create lowpass buffer and DSP unit
|
|
*/
|
|
LowPass_Init();
|
|
LowPassBuffer = calloc(FSOUND_DSP_GetBufferLength()+256, bytesperoutputsample);
|
|
LowPass_Update(LowPassResonance, LowPassCutoffFrequency, outputfreq);
|
|
LowPassUnit = FSOUND_DSP_Create(&LowPassCallback, FSOUND_DSP_DEFAULTPRIORITY_USER+1, LowPassBuffer);
|
|
|
|
/*
|
|
Create buffer and dsp unit for echo effect
|
|
*/
|
|
EchoLen = MAXECHOLEN; /* 500ms */
|
|
EchoBuffer = calloc(EchoLen, 4); /* The echo buff is always 16bit stereo int regardless of the mixer format, so * 4 */
|
|
EchoOffset = 0;
|
|
EchoUnit = FSOUND_DSP_Create(&EchoCallback, FSOUND_DSP_DEFAULTPRIORITY_USER+2, EchoBuffer);
|
|
|
|
/*
|
|
Create buffer and dsp unit for oscilliscope.
|
|
*/
|
|
OscUnit = FSOUND_DSP_Create(&OscCallback, FSOUND_DSP_DEFAULTPRIORITY_USER+3, 0);
|
|
OscBuffer = calloc(FSOUND_DSP_GetBufferLengthTotal() + 16, 2); /* *2 for mono 16bit buffer */
|
|
|
|
/*
|
|
Initialize reverb stuff
|
|
*/
|
|
Reverb_Init();
|
|
|
|
/*
|
|
Create a bitmap to draw the Spectrum into
|
|
*/
|
|
|
|
// make the header
|
|
ZeroMemory( &GraphicWindowBitmap, sizeof( BITMAPINFO ) );
|
|
GraphicWindowBitmap.bmiHeader.biSize = sizeof( GraphicWindowBitmap.bmiHeader );
|
|
GraphicWindowBitmap.bmiHeader.biWidth = GRAPHICWINDOW_WIDTH;
|
|
GraphicWindowBitmap.bmiHeader.biHeight = GRAPHICWINDOW_HEIGHT;
|
|
GraphicWindowBitmap.bmiHeader.biPlanes = 1;
|
|
GraphicWindowBitmap.bmiHeader.biBitCount = 32;
|
|
GraphicWindowBitmap.bmiHeader.biCompression = BI_RGB;
|
|
GraphicWindowBitmap.bmiHeader.biSizeImage = 0;
|
|
GraphicWindowBitmap.bmiHeader.biXPelsPerMeter = 0;
|
|
GraphicWindowBitmap.bmiHeader.biYPelsPerMeter = 0;
|
|
GraphicWindowBitmap.bmiHeader.biClrUsed = 0;
|
|
GraphicWindowBitmap.bmiHeader.biClrImportant = 0;
|
|
|
|
|
|
DSP_Ready = TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
Remove all DSP units and reverb buffers etc.
|
|
|
|
[PARAMETERS]
|
|
void
|
|
|
|
[RETURN_VALUE]
|
|
void
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
InitDSP
|
|
]
|
|
*/
|
|
void CloseDSP()
|
|
{
|
|
DSP_Ready = FALSE;
|
|
|
|
if (LowPassUnit)
|
|
{
|
|
FSOUND_DSP_Free(LowPassUnit);
|
|
}
|
|
LowPassUnit = NULL;
|
|
|
|
if (EchoUnit)
|
|
{
|
|
FSOUND_DSP_Free(EchoUnit);
|
|
}
|
|
EchoUnit = NULL;
|
|
|
|
if (OscUnit)
|
|
{
|
|
FSOUND_DSP_Free(OscUnit);
|
|
}
|
|
OscUnit = NULL;
|
|
|
|
/*
|
|
Free buffers
|
|
*/
|
|
if (LowPassBuffer)
|
|
{
|
|
free(LowPassBuffer);
|
|
}
|
|
LowPassBuffer = NULL;
|
|
|
|
if (EchoBuffer)
|
|
{
|
|
free(EchoBuffer);
|
|
}
|
|
EchoBuffer = NULL;
|
|
|
|
if (OscBuffer)
|
|
{
|
|
free(OscBuffer);
|
|
}
|
|
OscBuffer = NULL;
|
|
|
|
Reverb_Close();
|
|
LowPass_Close();
|
|
}
|
|
|
|
|
|
/*
|
|
** TextWindowProc
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* DESCRIPTION: Sends back messages to the parent window if this window got focus
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
long FAR PASCAL ProgressWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_LBUTTONDOWN:
|
|
case WM_MOUSEMOVE:
|
|
{
|
|
int songid = (int)SendMessage(songlist_hwnd, LB_GETCURSEL, 0, 0);
|
|
|
|
if (message == WM_MOUSEMOVE && wParam != MK_LBUTTON)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (songid != LB_ERR)
|
|
{
|
|
FMUSIC_MODULE *mod = song[songid].mod;
|
|
FSOUND_STREAM *stream = song[songid].stream;
|
|
char *url = song[songid].url;
|
|
RECT r;
|
|
int width;
|
|
int xPos = LOWORD(lParam); // horizontal position of cursor
|
|
|
|
GetWindowRect(hwnd, &r);
|
|
|
|
width = r.right - r.left;
|
|
|
|
if (mod)
|
|
{
|
|
int count;
|
|
|
|
for (count=0; count < FMUSIC_GetNumChannels(mod); count++)
|
|
{
|
|
FSOUND_StopSound(FMUSIC_GetRealChannel(mod, count));
|
|
}
|
|
FMUSIC_SetOrder(mod, (int)((float)FMUSIC_GetNumOrders(mod) / (float)width * (float)xPos));
|
|
}
|
|
else if (stream && !url)
|
|
{
|
|
FSOUND_Stream_SetTime(stream, (int)((float)FSOUND_Stream_GetLengthMs(stream) / (float)width * (float)xPos));
|
|
}
|
|
else if (song[songid].cdtrack)
|
|
{
|
|
if (setting_cdda)
|
|
{
|
|
if ((song[songid].channel != -1) && cdda_stream)
|
|
{
|
|
FSOUND_Stream_SetTime(cdda_stream, (int)((float)FSOUND_Stream_GetLengthMs(cdda_stream) / (float)width * (float)xPos));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (song[songid].cdtrack == FSOUND_CD_GetTrack(cddevice))
|
|
{
|
|
FSOUND_CD_SetTrackTime(cddevice, (int)((float)FSOUND_CD_GetTrackLength(cddevice, FSOUND_CD_GetTrack(cddevice)) / (float)width * (float)xPos));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
|
|
return (long)CallWindowProc(oldprogressproc, hwnd, message, wParam, lParam);
|
|
}
|
|
|
|
|
|
/*
|
|
** TextWindowProc
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
* DESCRIPTION: Sends back messages to the parent window if this window got focus
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
long FAR PASCAL CDTimeWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_LBUTTONDOWN:
|
|
{
|
|
DraggingCDSlider = TRUE;
|
|
break;
|
|
}
|
|
case WM_LBUTTONUP:
|
|
{
|
|
int pos = (int)SendMessage(hwnd, TBM_GETPOS, 0, 0);
|
|
|
|
if (setting_cdda)
|
|
{
|
|
if (cdda_stream)
|
|
{
|
|
FSOUND_Stream_SetTime(cdda_stream, (int)((float)pos * (float)FSOUND_Stream_GetLengthMs(cdda_stream) / 1000.0f));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FSOUND_CD_SetTrackTime(cddevice, (int)((float)pos * (float)FSOUND_CD_GetTrackLength(cddevice, FSOUND_CD_GetTrack(cddevice)) / 1000.0f));
|
|
}
|
|
DraggingCDSlider = FALSE;
|
|
break;
|
|
}
|
|
};
|
|
|
|
return (long)CallWindowProc(oldcdtimeproc, hwnd, message, wParam, lParam);
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
#ifdef _WIN64
|
|
INT_PTR CALLBACK FMOD_DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
#else
|
|
BOOL CALLBACK FMOD_DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
#endif
|
|
{
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
int count;
|
|
RECT r;
|
|
|
|
SetFocus(hwnd);
|
|
|
|
/*
|
|
CALL DRIVER DIALOG BOX
|
|
*/
|
|
#if 0
|
|
if (!SoundDriver_Init(&outputfreq))
|
|
{
|
|
SendMessage(hwnd, WM_CLOSE, 0, 0);
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
CONFIGURE STABILITY OF SOUND OUTPUT UNDER WINDOWS
|
|
*/
|
|
|
|
FSOUND_SetBufferSize(FSOUND_BUFFERSIZE);
|
|
|
|
/*
|
|
INITIALIZE FSOUND
|
|
*/
|
|
FSOUND_SetOutput(setting_output);
|
|
FSOUND_SetDriver(setting_driver);
|
|
FSOUND_SetMixer(setting_mixer);
|
|
FSOUND_SetHWND(hwnd);
|
|
|
|
outputfreq = setting_outputrate;
|
|
if (!FSOUND_Init(outputfreq, NUMCHANNELS, FSOUND_INIT_GLOBALFOCUS))
|
|
{
|
|
MessageBox(hwnd, FMOD_ErrorString(FSOUND_GetError()), "FSOUND", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
SendMessage(hwnd, WM_CLOSE, 0, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
FSOUND_Stream_Net_SetProxy(setting_http_proxy);
|
|
FSOUND_Stream_SetBufferSize(1000);
|
|
|
|
/*
|
|
SET UP A PAINT TIMER FOR INTERFACE
|
|
*/
|
|
timerid = SetTimer(hwnd, 0, 5, (TIMERPROC)0);
|
|
if (!timerid)
|
|
{
|
|
MessageBox( NULL, "Too many timers in use", "Error", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
INITIALIZE SONG LIST TO NULL
|
|
*/
|
|
for (count=0; count<MAXSONGS+1; count++)
|
|
{
|
|
song[count].mod = NULL;
|
|
song[count].stream = NULL;
|
|
song[count].url = NULL;
|
|
song[count].channel = -1;
|
|
song[count].last_status = -2;
|
|
song[count].last_netstatus = FSOUND_STREAM_NET_NOTCONNECTED;
|
|
song[count].server_status = NULL;
|
|
song[count].title = NULL;
|
|
song[count].artist = NULL;
|
|
song[count].protocol = NULL;
|
|
song[count].format = NULL;
|
|
song[count].streamname = NULL;
|
|
song[count].metadata = 0;
|
|
song[count].cdtrack = 0;
|
|
song[count].cdtrack_length = 0;
|
|
}
|
|
|
|
/*
|
|
SET UP DSP UNITS
|
|
*/
|
|
InitDSP();
|
|
|
|
GetWindowRect(GetDlgItem(hwnd, IDC_STATIC_INFO), &r);
|
|
graphic_window_x = r.left + (((r.right - r.left) - GRAPHICWINDOW_WIDTH) / 2) - 2;
|
|
graphic_window_y = r.top;
|
|
|
|
songlist_hwnd = GetDlgItem(hwnd, IDC_SONGLIST);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_CLOSE:
|
|
{
|
|
CloseDSP();
|
|
|
|
KillTimer(hwnd, timerid);
|
|
|
|
/*
|
|
The timer doesnt die immediately, sleep for a bit to let it die so we dont free streams then the timer tries to access them
|
|
*/
|
|
Sleep(200);
|
|
|
|
CloseDown();
|
|
EndDialog(hwnd,0);
|
|
PostQuitMessage(0);
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_HSCROLL:
|
|
{
|
|
if ((HWND)lParam == GetDlgItem(hwnd, IDC_SLIDER1))
|
|
{
|
|
int songid = (int)SendMessage(songlist_hwnd, LB_GETCURSEL, 0, 0);
|
|
if (songid != LB_ERR)
|
|
{
|
|
FMUSIC_MODULE *mod = song[songid].mod;
|
|
FSOUND_STREAM *stream = song[songid].stream;
|
|
|
|
if (mod)
|
|
{
|
|
FMUSIC_SetMasterVolume(mod, (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0));
|
|
}
|
|
else if (stream)
|
|
{
|
|
FSOUND_SetVolume(song[songid].channel, (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0));
|
|
}
|
|
else if (song[songid].cdtrack)
|
|
{
|
|
if (setting_cdda)
|
|
{
|
|
if ((song[songid].channel != -1) && cdda_stream)
|
|
{
|
|
FSOUND_SetVolume(song[songid].channel, (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (song[songid].cdtrack == FSOUND_CD_GetTrack(cddevice))
|
|
{
|
|
FSOUND_CD_SetVolume(cddevice, (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_VSCROLL :
|
|
{
|
|
if ((HWND)lParam == GetDlgItem(hwnd,IDC_ECHOSLIDER))
|
|
{
|
|
EchoLen = (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0) * outputfreq / 1000;
|
|
if (EchoLen < FSOUND_DSP_GetBufferLength())
|
|
{
|
|
EchoLen = FSOUND_DSP_GetBufferLength();
|
|
}
|
|
|
|
EchoOffset = 0;
|
|
memset(EchoBuffer, 0, MAXECHOLEN); /* echolen is in samples. */
|
|
break;
|
|
}
|
|
else if ((HWND)lParam == GetDlgItem(hwnd,IDC_CUTOFFSLIDER))
|
|
{
|
|
LowPassCutoffFrequency = 520 - (float)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0);
|
|
LowPassCutoffFrequency *= 10; /* 200 to 5000 */
|
|
LowPass_Update(LowPassResonance, LowPassCutoffFrequency, FSOUND_GetOutputRate());
|
|
break;
|
|
}
|
|
else if ((HWND)lParam == GetDlgItem(hwnd,IDC_RESOSLIDER))
|
|
{
|
|
LowPassResonance = 520 - (float)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0);
|
|
LowPassResonance /= 50; /* .2 to 10 */
|
|
LowPass_Update(LowPassResonance, LowPassCutoffFrequency, FSOUND_GetOutputRate());
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
case WM_COMMAND :
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDCANCEL:
|
|
{
|
|
CloseDown();
|
|
EndDialog(hwnd, 0);
|
|
PostQuitMessage(0);
|
|
return TRUE;
|
|
}
|
|
|
|
case IDC_LOAD: /* LOAD MOD */
|
|
{
|
|
LoadSong();
|
|
SelectInfoWindow();
|
|
break;
|
|
}
|
|
|
|
case IDC_LOADURL : /* LOAD URL */
|
|
{
|
|
LoadURL();
|
|
SelectInfoWindow();
|
|
break;
|
|
}
|
|
|
|
case IDC_LOADCD :
|
|
{
|
|
LoadCD();
|
|
SelectInfoWindow();
|
|
break;
|
|
}
|
|
|
|
case IDC_DELETE :
|
|
{
|
|
int songid = (int)SendMessage(songlist_hwnd, LB_GETCURSEL, 0, 0);
|
|
if (songid == LB_ERR)
|
|
{
|
|
MessageBox(hwnd, "Error. Please SELECT a song to delete", "Deleting a mod", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
}
|
|
else
|
|
{
|
|
DeleteSong(songid);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case IDC_PLAY :
|
|
{
|
|
if (play_button_play)
|
|
{
|
|
int songid = (int)SendMessage(songlist_hwnd, LB_GETCURSEL, 0, 0);
|
|
if (songid != LB_ERR)
|
|
{
|
|
if (Button_GetCheck(GetDlgItem(hwnd,IDC_PLAYLIST)))
|
|
{
|
|
playlistsong = songid;
|
|
}
|
|
|
|
if (song[songid].mod)
|
|
{
|
|
FMUSIC_SetLooping(song[songid].mod, Button_GetCheck(GetDlgItem(hwnd,IDC_PLAYLOOPED)));
|
|
if (!FMUSIC_PlaySong(song[songid].mod))
|
|
{
|
|
FMUSIC_SetLooping(song[songid].mod, Button_GetCheck(GetDlgItem(hwnd,IDC_PLAYLOOPED)));
|
|
MessageBox(hwnd, "Error. Cannot start song", "Playing a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
}
|
|
}
|
|
else if (song[songid].url)
|
|
{
|
|
if (song[songid].stream)
|
|
{
|
|
switch (FSOUND_Stream_GetOpenState(song[songid].stream))
|
|
{
|
|
case -1 :
|
|
case -3 :
|
|
{
|
|
FSOUND_Stream_Close(song[songid].stream);
|
|
song[songid].stream = FSOUND_Stream_Open(song[songid].url, FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0);
|
|
if (!song[songid].stream)
|
|
{
|
|
MessageBox(hwnd, "ERROR: Couldn't open stream", "Playing a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case 0 :
|
|
{
|
|
int off, len, status;
|
|
|
|
off = FSOUND_Stream_GetTime(song[songid].stream);
|
|
len = FSOUND_Stream_GetLengthMs(song[songid].stream);
|
|
|
|
FSOUND_Stream_Net_GetStatus(song[songid].stream, &status, 0, 0, 0);
|
|
|
|
if ((status == FSOUND_STREAM_NET_ERROR) || (off >= len))
|
|
{
|
|
FSOUND_Stream_Close(song[songid].stream);
|
|
song[songid].stream = FSOUND_Stream_Open(song[songid].url, FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0);
|
|
if (!song[songid].stream)
|
|
{
|
|
MessageBox(hwnd, "ERROR: Couldn't open stream", "Playing a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
song[songid].stream = FSOUND_Stream_Open(song[songid].url, FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0);
|
|
if (!song[songid].stream)
|
|
{
|
|
MessageBox(hwnd, "ERROR: Couldn't open stream", "Playing a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
}
|
|
}
|
|
}
|
|
else if (song[songid].stream)
|
|
{
|
|
/*
|
|
It's non-blocking - wait for it to finish opening first
|
|
*/
|
|
if (FSOUND_Stream_GetOpenState(song[songid].stream) != 0)
|
|
{
|
|
HWND pwhwnd = CreateDialog(g_hinst, MAKEINTRESOURCE(IDD_DIALOGWAIT), mainhwnd, 0);
|
|
while (FSOUND_Stream_GetOpenState(song[songid].stream) == -2)
|
|
{
|
|
Sleep(100);
|
|
}
|
|
EndDialog(pwhwnd, 0);
|
|
}
|
|
|
|
FSOUND_Stream_SetMode(song[songid].stream, Button_GetCheck(GetDlgItem(hwnd,IDC_PLAYLOOPED)) ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF);
|
|
song[songid].channel = FSOUND_Stream_Play(FSOUND_FREE, song[songid].stream);
|
|
if (song[songid].channel < 0)
|
|
{
|
|
MessageBox(hwnd, "Error. Cannot start song", "Playing a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
}
|
|
}
|
|
else if (song[songid].cdtrack)
|
|
{
|
|
if (!PlayCDTrack(songid, Button_GetCheck(GetDlgItem(hwnd,IDC_PLAYLOOPED)) ? FSOUND_CD_PLAYLOOPED : FSOUND_CD_PLAYONCE))
|
|
{
|
|
MessageBox(hwnd, "Error. Cannot start song", "Playing a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox(hwnd, "Error. Please select a song to play first", "Playing a song", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int songid = (int)SendMessage(songlist_hwnd, LB_GETCURSEL, 0, 0);
|
|
if (songid != LB_ERR)
|
|
{
|
|
if (song[songid].mod)
|
|
{
|
|
FMUSIC_StopSong(song[songid].mod);
|
|
}
|
|
else if (song[songid].stream)
|
|
{
|
|
if (song[songid].url)
|
|
{
|
|
FSOUND_Stream_Close(song[songid].stream);
|
|
song[songid].stream = NULL;
|
|
}
|
|
else
|
|
{
|
|
FSOUND_Stream_Stop(song[songid].stream);
|
|
}
|
|
}
|
|
else if (song[songid].cdtrack)
|
|
{
|
|
if (setting_cdda)
|
|
{
|
|
if ((song[songid].channel != -1) && cdda_stream)
|
|
{
|
|
StopCDTrack();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (song[songid].cdtrack == FSOUND_CD_GetTrack(cddevice))
|
|
{
|
|
StopCDTrack();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (song[songid].title)
|
|
{
|
|
free(song[songid].title);
|
|
song[songid].title = 0;
|
|
}
|
|
|
|
if (song[songid].artist)
|
|
{
|
|
free(song[songid].artist);
|
|
song[songid].artist = 0;
|
|
}
|
|
|
|
song[songid].channel = -1;
|
|
song[songid].protocol = NULL;
|
|
song[songid].format = NULL;
|
|
song[songid].streamname = NULL;
|
|
}
|
|
else
|
|
{
|
|
MessageBox(hwnd, "Error. Please select a song to play first", "Playing a mod", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case IDC_SPECTRUM: /* GRAPHIC SPECTRUM / INFO BUTTON */
|
|
{
|
|
int x, y;
|
|
RECT rect;
|
|
|
|
if (GraphicWindowCurrent == GRAPHICWINDOW_MODINFO)
|
|
{
|
|
ShowWindow(modinfo_hwnd, SW_HIDE);
|
|
ShowWindow(streaminfo_hwnd, SW_HIDE);
|
|
ShowWindow(netstreaminfo_hwnd, SW_HIDE);
|
|
ShowWindow(cdinfo_hwnd, SW_HIDE);
|
|
}
|
|
else if (GraphicWindowCurrent == GRAPHICWINDOW_EQUALISER)
|
|
{
|
|
FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit(), FALSE);
|
|
}
|
|
else if (GraphicWindowCurrent == GRAPHICWINDOW_WAVE)
|
|
{
|
|
FSOUND_DSP_SetActive(OscUnit, FALSE);
|
|
}
|
|
|
|
GraphicWindowCurrent++;
|
|
if (GraphicWindowCurrent >= GRAPHICWINDOW_MAX)
|
|
{
|
|
GraphicWindowCurrent = GRAPHICWINDOW_MODINFO;
|
|
}
|
|
|
|
if (GraphicWindowCurrent == GRAPHICWINDOW_MODINFO)
|
|
{
|
|
SelectInfoWindow();
|
|
SendMessage(GetDlgItem(hwnd, IDC_SPECTRUM), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)"Spectrum");
|
|
}
|
|
else if (GraphicWindowCurrent == GRAPHICWINDOW_EQUALISER)
|
|
{
|
|
FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit(), TRUE);
|
|
SendMessage(GetDlgItem(hwnd, IDC_STATIC_INFO), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)"Spectrum");
|
|
SendMessage(GetDlgItem(hwnd, IDC_SPECTRUM), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)"Wave");
|
|
}
|
|
else if (GraphicWindowCurrent == GRAPHICWINDOW_WAVE)
|
|
{
|
|
FSOUND_DSP_SetActive(OscUnit, TRUE);
|
|
SendMessage(GetDlgItem(hwnd, IDC_STATIC_INFO), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)"Oscilliscope");
|
|
SendMessage(GetDlgItem(hwnd, IDC_SPECTRUM), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)"Info");
|
|
}
|
|
|
|
x = graphic_window_x;
|
|
y = graphic_window_y;
|
|
rect.left = x;
|
|
rect.top = y;
|
|
rect.right = x + GRAPHICWINDOW_WIDTH;
|
|
rect.bottom = y + GRAPHICWINDOW_HEIGHT;
|
|
InvalidateRect(hwnd, &rect, TRUE);
|
|
|
|
break;
|
|
}
|
|
|
|
case IDC_SONGLIST :
|
|
{
|
|
if (HIWORD(wParam) == LBN_SELCHANGE)
|
|
{
|
|
SelectInfoWindow();
|
|
}
|
|
break;
|
|
}
|
|
|
|
case IDC_CONFIG :
|
|
{
|
|
int i, numsongs, currsong;
|
|
|
|
CloseDSP();
|
|
|
|
/*
|
|
Close all open internet streams because all network stuff gets shutdown in FSOUND_Close
|
|
*/
|
|
numsongs = (int)SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0);
|
|
currsong = (int)SendMessage(songlist_hwnd, LB_GETCURSEL, 0, 0);
|
|
for (i=0;i < numsongs;i++)
|
|
{
|
|
if (song[i].url && song[i].stream)
|
|
{
|
|
FSOUND_Stream_Close(song[i].stream);
|
|
song[i].stream = 0;
|
|
song[i].channel = -1;
|
|
song[i].last_status = -1;
|
|
|
|
if (i == currsong)
|
|
{
|
|
UpdateNetStreamInfo(i, TRUE, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cdda_stream)
|
|
{
|
|
FSOUND_Stream_Close(cdda_stream);
|
|
cdda_stream = 0;
|
|
cdda_channel = -1;
|
|
}
|
|
|
|
DeleteAllCDTracks();
|
|
|
|
/*
|
|
Remember .. FSOUND_Close cleans up all DSP units, so if you still have pointers to them,
|
|
it could cause problems (crashes) because they are pointing to freed data.
|
|
This is why there is a call to CloseDSP above.
|
|
*/
|
|
FSOUND_Close();
|
|
|
|
/*
|
|
Call up dialog box to select sound options
|
|
*/
|
|
SoundDriver_Init(&outputfreq);
|
|
|
|
FSOUND_SetBufferSize(FSOUND_BUFFERSIZE);
|
|
|
|
/*
|
|
Initialize FSOUND
|
|
*/
|
|
|
|
if (!FSOUND_Init(outputfreq,NUMCHANNELS, FSOUND_INIT_GLOBALFOCUS))
|
|
{
|
|
MessageBox(hwnd, FMOD_ErrorString(FSOUND_GetError()), "FSOUND", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
return FALSE;
|
|
}
|
|
|
|
FSOUND_Stream_Net_SetProxy(setting_http_proxy);
|
|
FSOUND_Stream_SetBufferSize(1000);
|
|
|
|
InitDSP();
|
|
|
|
if (GraphicWindowCurrent == GRAPHICWINDOW_EQUALISER)
|
|
{
|
|
FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit(), TRUE);
|
|
}
|
|
else if (GraphicWindowCurrent == GRAPHICWINDOW_WAVE)
|
|
{
|
|
FSOUND_DSP_SetActive(OscUnit, TRUE);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
InvalidateRect(songlist_hwnd, NULL, FALSE);
|
|
|
|
break;
|
|
}
|
|
|
|
case WM_DROPFILES :
|
|
{
|
|
HDROP hDrop = (HDROP)wParam;
|
|
int numfiles, count;
|
|
char name[1024];
|
|
Playlist *p;
|
|
int i;
|
|
struct _stat buf;
|
|
|
|
numfiles = DragQueryFile(hDrop, 0xFFFFFFFF, &name[0], 1024);
|
|
if (!numfiles)
|
|
break;
|
|
|
|
for (count=0; count<numfiles; count++)
|
|
{
|
|
DragQueryFile(hDrop, count, &name[0], 1024);
|
|
|
|
if (_stat(name, &buf))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!(buf.st_mode & _S_IFREG))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
p = ParsePlaylist(name);
|
|
if (p)
|
|
{
|
|
for (i=0;i < p->count;i++)
|
|
{
|
|
AddFileToSongList(p->name[i], p->displayname[i]);
|
|
}
|
|
|
|
FreePlaylist(p);
|
|
}
|
|
else
|
|
{
|
|
AddFileToSongList(name, name);
|
|
}
|
|
}
|
|
|
|
DragFinish(hDrop);
|
|
SelectInfoWindow();
|
|
|
|
break;
|
|
}
|
|
case WM_COPYDATA :
|
|
{
|
|
Playlist *p;
|
|
char *name;
|
|
int i;
|
|
COPYDATASTRUCT *data;
|
|
|
|
data = (COPYDATASTRUCT *)lParam;
|
|
if (data->cbData)
|
|
{
|
|
char tmp[2048];
|
|
|
|
strcpy(tmp, (char *)data->lpData);
|
|
name = tmp;
|
|
|
|
if (*name == '"')
|
|
{
|
|
name++;
|
|
}
|
|
|
|
if (name[strlen(name) - 1] == '"')
|
|
{
|
|
name[strlen(name) - 1] = 0;
|
|
}
|
|
|
|
p = ParsePlaylist(name);
|
|
if (p)
|
|
{
|
|
for (i=0;i < p->count;i++)
|
|
{
|
|
AddFileToSongList(p->name[i], p->displayname[i]);
|
|
}
|
|
|
|
FreePlaylist(p);
|
|
}
|
|
else
|
|
{
|
|
AddFileToSongList(name, name);
|
|
}
|
|
}
|
|
|
|
SelectInfoWindow();
|
|
break;
|
|
}
|
|
|
|
case WM_TIMER :
|
|
{
|
|
char s[256];
|
|
HDC hdc = GetDC(hwnd);
|
|
HFONT myfont;
|
|
FMUSIC_MODULE *mod;
|
|
FSOUND_STREAM *stream;
|
|
int songid;
|
|
int greyoutfilters;
|
|
|
|
greyoutfilters = FALSE;
|
|
|
|
myfont = GetStockObject(DEFAULT_GUI_FONT);
|
|
SelectObject(hdc, myfont);
|
|
|
|
SetBkColor(hdc, GetSysColor(COLOR_3DFACE));
|
|
SetTextColor(hdc, RGB(0, 0, 255));
|
|
|
|
sprintf(s, "%03d", FSOUND_GetChannelsPlaying());
|
|
TextOut(hdc, (int)(TEXT_CHANNELSPLAYING_X * scalex), (int)(TEXT_CHANNELSPLAYING_Y * scaley), s, (int)strlen(s));
|
|
|
|
sprintf(s, "%5.02f%% ", FSOUND_GetCPUUsage());
|
|
TextOut(hdc, (int)(TEXT_CPUUSAGE_X * scalex), (int)(TEXT_CPUUSAGE_Y * scaley), s, (int)strlen(s));
|
|
|
|
/*
|
|
DSP BUTTONS
|
|
*/
|
|
if (DSP_Ready)
|
|
{
|
|
int count;
|
|
|
|
/*
|
|
If the unit is inactive and the checkbox is checked, then clear preverb buffer
|
|
this stops any old preverb dregs hanging around.
|
|
*/
|
|
if (!FSOUND_DSP_GetActive(PreverbTap[0].Unit) && (char)Button_GetCheck(GetDlgItem(hwnd,IDC_PREVERB)))
|
|
{
|
|
for (count=0; count < PREVERB_NUMTAPS; count++)
|
|
{
|
|
memset(PreverbTap[count].historybuff, 0, PreverbTap[count].historylen<<2); /* preverblen is in samples. */
|
|
}
|
|
}
|
|
for (count=0; count < PREVERB_NUMTAPS; count++)
|
|
{
|
|
FSOUND_DSP_SetActive(PreverbTap[count].Unit, (char)Button_GetCheck(GetDlgItem(hwnd,IDC_PREVERB)));
|
|
}
|
|
|
|
/*
|
|
If the unit is inactive and the checkbox is checked, then clear reverb buffer
|
|
this stops any old reverb dregs hanging around.
|
|
*/
|
|
if (!FSOUND_DSP_GetActive(ReverbTap[0].Unit) && (char)Button_GetCheck(GetDlgItem(hwnd,IDC_REVERB)))
|
|
{
|
|
for (count=0; count < REVERB_NUMTAPS; count++)
|
|
{
|
|
memset(ReverbTap[count].historybuff, 0, ReverbTap[count].historylen<<2); /* preverblen is in samples. */
|
|
}
|
|
}
|
|
for (count=0; count < REVERB_NUMTAPS; count++)
|
|
{
|
|
FSOUND_DSP_SetActive(ReverbTap[count].Unit, (char)Button_GetCheck(GetDlgItem(hwnd,IDC_REVERB)));
|
|
}
|
|
|
|
|
|
/*
|
|
MIDI reverb uses the reverb button as well
|
|
*/
|
|
FMUSIC_SetReverb((char)Button_GetCheck(GetDlgItem(hwnd,IDC_REVERB)));
|
|
|
|
|
|
/*
|
|
If the unit is inactive and the checkbox is checked, then clear echo buffer
|
|
this stops any old echo dregs hanging around.
|
|
*/
|
|
if (!FSOUND_DSP_GetActive(EchoUnit) && (char)Button_GetCheck(GetDlgItem(hwnd,IDC_ECHO)))
|
|
{
|
|
/*
|
|
Set status
|
|
*/
|
|
ShowWindow(GetDlgItem(mainhwnd,IDC_ECHOSLIDER), SW_SHOW);
|
|
memset(EchoBuffer, 0, MAXECHOLEN); /* echolen is in samples. */
|
|
|
|
SendMessage(GetDlgItem(mainhwnd,IDC_ECHOSLIDER), TBM_SETPOS, TRUE, EchoLen * 1000 / outputfreq);
|
|
}
|
|
if (FSOUND_DSP_GetActive(EchoUnit) && !(char)Button_GetCheck(GetDlgItem(hwnd,IDC_ECHO)))
|
|
{
|
|
ShowWindow(GetDlgItem(mainhwnd,IDC_ECHOSLIDER), SW_HIDE);
|
|
}
|
|
|
|
FSOUND_DSP_SetActive(EchoUnit, (char)Button_GetCheck(GetDlgItem(hwnd,IDC_ECHO)));
|
|
|
|
|
|
|
|
if (!FSOUND_DSP_GetActive(LowPassUnit) && (char)Button_GetCheck(GetDlgItem(hwnd,IDC_LOWPASS)))
|
|
{
|
|
/*
|
|
Set status
|
|
*/
|
|
ShowWindow(GetDlgItem(mainhwnd,IDC_CUTOFFSLIDER), SW_SHOW);
|
|
ShowWindow(GetDlgItem(mainhwnd,IDC_RESOSLIDER), SW_SHOW);
|
|
|
|
SendMessage(GetDlgItem(mainhwnd,IDC_CUTOFFSLIDER), TBM_SETPOS, TRUE, 520 - (int)(LowPassCutoffFrequency / 10.0f));
|
|
SendMessage(GetDlgItem(mainhwnd,IDC_RESOSLIDER), TBM_SETPOS, TRUE, 520 - (int)(LowPassResonance * 50.0f));
|
|
}
|
|
if (FSOUND_DSP_GetActive(LowPassUnit) && !(char)Button_GetCheck(GetDlgItem(hwnd,IDC_LOWPASS)))
|
|
{
|
|
ShowWindow(GetDlgItem(mainhwnd,IDC_CUTOFFSLIDER), SW_HIDE);
|
|
ShowWindow(GetDlgItem(mainhwnd,IDC_RESOSLIDER), SW_HIDE);
|
|
}
|
|
|
|
FSOUND_DSP_SetActive(LowPassUnit, (char)Button_GetCheck(GetDlgItem(hwnd,IDC_LOWPASS)));
|
|
}
|
|
|
|
/*
|
|
Check PLAYLIST checkbox
|
|
*/
|
|
if (Button_GetCheck(GetDlgItem(hwnd,IDC_PLAYLIST)))
|
|
{
|
|
mod = song[playlistsong].mod;
|
|
if (mod)
|
|
{
|
|
if (FMUSIC_IsFinished(mod))
|
|
{
|
|
FMUSIC_StopSong(mod);
|
|
PlayNextSong();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
stream = song[playlistsong].stream;
|
|
if (stream)
|
|
{
|
|
int off = FSOUND_Stream_GetTime(stream);
|
|
int len = FSOUND_Stream_GetLengthMs(stream);
|
|
|
|
if ((!song[playlistsong].url) || (song[playlistsong].url && (FSOUND_Stream_GetOpenState(song[playlistsong].stream) == 0)))
|
|
{
|
|
if (off >= len)
|
|
{
|
|
if (song[playlistsong].url)
|
|
{
|
|
FSOUND_Stream_Close(stream);
|
|
song[playlistsong].stream = 0;
|
|
}
|
|
else
|
|
{
|
|
FSOUND_Stream_Stop(stream);
|
|
}
|
|
|
|
song[playlistsong].channel = -1;
|
|
|
|
PlayNextSong();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (song[playlistsong].cdtrack)
|
|
{
|
|
if (setting_cdda)
|
|
{
|
|
if ((song[playlistsong].channel != -1) && cdda_stream && (FSOUND_Stream_GetOpenState(cdda_stream) == 0))
|
|
{
|
|
int off = FSOUND_Stream_GetTime(cdda_stream);
|
|
int len = FSOUND_Stream_GetLengthMs(cdda_stream);
|
|
|
|
if (off >= len)
|
|
{
|
|
StopCDTrack();
|
|
PlayNextSong();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int off = FSOUND_CD_GetTrackTime(cddevice);
|
|
int len = FSOUND_CD_GetTrackLength(cddevice, FSOUND_CD_GetTrack(cddevice));
|
|
if (off >= len)
|
|
{
|
|
StopCDTrack();
|
|
PlayNextSong();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
songid = (int)SendMessage(songlist_hwnd, LB_GETCURSEL, 0, 0);
|
|
if (songid >= 0)
|
|
{
|
|
unsigned int lengthms, currtime;
|
|
signed char playing = FALSE;
|
|
|
|
if (song[songid].mod)
|
|
{
|
|
mod = song[songid].mod;
|
|
UpdateModInfo(songid, FALSE);
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETRANGE, 0, MAKELPARAM(0, FMUSIC_GetNumOrders(mod)-1));
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETPOS, FMUSIC_GetOrder(mod), 0);
|
|
|
|
/*
|
|
Grey out fx buttons for midi
|
|
*/
|
|
if (FMUSIC_GetType(mod) == FMUSIC_TYPE_MIDI)
|
|
{
|
|
greyoutfilters = TRUE;
|
|
}
|
|
|
|
playing = FMUSIC_IsPlaying(mod);
|
|
}
|
|
else if (song[songid].url)
|
|
{
|
|
UpdateNetStreamInfo(songid, FALSE, FALSE);
|
|
|
|
if (song[songid].stream && (song[songid].channel != -1))
|
|
{
|
|
playing = FSOUND_IsPlaying(song[songid].channel);
|
|
}
|
|
}
|
|
else if (song[songid].stream)
|
|
{
|
|
UpdateStreamInfo(songid, FALSE);
|
|
|
|
currtime = FSOUND_Stream_GetTime(song[songid].stream);
|
|
lengthms = FSOUND_Stream_GetLengthMs(song[songid].stream);
|
|
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETRANGE, 0, MAKELPARAM(0, 1000) );
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETPOS, (WPARAM)((float)currtime / (float)lengthms * 1000.0f), 0);
|
|
|
|
if (song[songid].channel != -1)
|
|
{
|
|
playing = FSOUND_IsPlaying(song[songid].channel);
|
|
if (currtime >= lengthms)
|
|
{
|
|
playing = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else if (song[songid].cdtrack)
|
|
{
|
|
UpdateCDInfo(songid, TRUE);
|
|
|
|
if (setting_cdda)
|
|
{
|
|
if ((song[songid].channel != -1) && cdda_stream)
|
|
{
|
|
currtime = FSOUND_Stream_GetTime(cdda_stream);
|
|
lengthms = FSOUND_Stream_GetLengthMs(cdda_stream);
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETRANGE, 0, MAKELPARAM(0, 1000) );
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETPOS, (WPARAM)((float)currtime / (float)lengthms * 1000.0f), 0);
|
|
|
|
playing = FSOUND_IsPlaying(song[songid].channel);
|
|
}
|
|
else
|
|
{
|
|
currtime = 0;
|
|
lengthms = 1;
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETRANGE, 0, MAKELPARAM(0, 1000) );
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETPOS, (WPARAM)((float)currtime / (float)lengthms * 1000.0f), 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (song[songid].cdtrack == FSOUND_CD_GetTrack(cddevice))
|
|
{
|
|
currtime = FSOUND_CD_GetTrackTime(cddevice);
|
|
lengthms = FSOUND_CD_GetTrackLength(cddevice, FSOUND_CD_GetTrack(cddevice));
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETRANGE, 0, MAKELPARAM(0, 1000) );
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETPOS, (WPARAM)((float)currtime / (float)lengthms * 1000.0f), 0);
|
|
|
|
if (FSOUND_CD_GetTrack(cddevice))
|
|
{
|
|
playing = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
currtime = 0;
|
|
lengthms = 1;
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETRANGE, 0, MAKELPARAM(0, 1000) );
|
|
SendMessage(GetDlgItem(hwnd,IDC_PROGRESS1), PBM_SETPOS, (WPARAM)((float)currtime / (float)lengthms * 1000.0f), 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!playing)
|
|
{
|
|
if (!play_button_play)
|
|
{
|
|
SetWindowText(GetDlgItem(hwnd, IDC_PLAY), "Play");
|
|
play_button_play = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (play_button_play)
|
|
{
|
|
SetWindowText(GetDlgItem(hwnd, IDC_PLAY), "Stop");
|
|
play_button_play = FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Set position of the master volume slider
|
|
*/
|
|
if (song[songid].mod)
|
|
{
|
|
SendMessage(GetDlgItem(hwnd,IDC_SLIDER1), TBM_SETPOS, TRUE, FMUSIC_GetMasterVolume(mod));
|
|
}
|
|
else if (song[songid].cdtrack && !setting_cdda)
|
|
{
|
|
SendMessage(GetDlgItem(hwnd,IDC_SLIDER1), TBM_SETPOS, TRUE, FSOUND_CD_GetVolume(cddevice));
|
|
}
|
|
else
|
|
{
|
|
SendMessage(GetDlgItem(hwnd,IDC_SLIDER1), TBM_SETPOS, TRUE, FSOUND_GetVolume(song[songid].channel));
|
|
}
|
|
}
|
|
|
|
/*
|
|
Update song listbox entries if the open state has changed
|
|
*/
|
|
{
|
|
int numsongs = (int)SendMessage(songlist_hwnd, LB_GETCOUNT, 0, 0);
|
|
int count;
|
|
|
|
for (count = 0; count < numsongs; count++)
|
|
{
|
|
int status = -2;
|
|
|
|
if (song[count].url)
|
|
{
|
|
UpdateNetStreamInfo(count, FALSE, TRUE);
|
|
}
|
|
|
|
if (song[count].stream)
|
|
{
|
|
status = FSOUND_Stream_GetOpenState(song[count].stream);
|
|
}
|
|
else if (song[count].mod)
|
|
{
|
|
status = FMUSIC_GetOpenState(song[count].mod);
|
|
}
|
|
|
|
if (status != song[count].last_status)
|
|
{
|
|
if (song[count].stream && !song[count].url && !status)
|
|
{
|
|
UpdateStreamInfo(count, TRUE);
|
|
}
|
|
|
|
SendMessage(songlist_hwnd, LB_SETITEMDATA, count, 0);
|
|
InvalidateRect(songlist_hwnd, 0, FALSE);
|
|
}
|
|
song[count].last_status = status;
|
|
}
|
|
}
|
|
|
|
if (greyoutfilters)
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd,IDC_LOWPASS), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd,IDC_PREVERB), FALSE);
|
|
EnableWindow(GetDlgItem(hwnd,IDC_ECHO), FALSE);
|
|
}
|
|
else
|
|
{
|
|
EnableWindow(GetDlgItem(hwnd,IDC_LOWPASS), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd,IDC_PREVERB), TRUE);
|
|
EnableWindow(GetDlgItem(hwnd,IDC_ECHO), TRUE);
|
|
}
|
|
|
|
if (GraphicWindowCurrent == GRAPHICWINDOW_EQUALISER)
|
|
{
|
|
PlotSpectrum(hdc);
|
|
}
|
|
else if (GraphicWindowCurrent == GRAPHICWINDOW_WAVE)
|
|
{
|
|
PlotOscilliscope(hdc);
|
|
}
|
|
|
|
if (setting_cdda)
|
|
{
|
|
if (cdda_stream)
|
|
{
|
|
if (FSOUND_Stream_GetOpenState(cdda_stream) == -3)
|
|
{
|
|
FSOUND_Stream_Close(cdda_stream);
|
|
cdda_stream = 0;
|
|
cdda_channel = -1;
|
|
MessageBox(0, "ERROR: Unable to open CDDA stream", "Error", MB_ICONHAND | MB_OK | MB_SYSTEMMODAL);
|
|
}
|
|
else
|
|
{
|
|
if ((cdda_stream_state != 0) && (FSOUND_Stream_GetOpenState(cdda_stream) == 0))
|
|
{
|
|
char *tag;
|
|
|
|
cdda_stream_state = 0;
|
|
|
|
if (FSOUND_Stream_FindTagField(cdda_stream, FSOUND_TAGFIELD_ASF + 1, "CD_ERROR", (void **)&tag, 0))
|
|
{
|
|
MessageBox(mainhwnd, tag, "Error", MB_ICONHAND|MB_OK|MB_SYSTEMMODAL);
|
|
FSOUND_Stream_Close(cdda_stream);
|
|
cdda_stream = 0;
|
|
cdda_channel = -1;
|
|
}
|
|
else
|
|
{
|
|
FSOUND_Stream_SetSubStream(cdda_stream, 0);
|
|
while (FSOUND_Stream_GetOpenState(cdda_stream) != 0)
|
|
{
|
|
Sleep(100);
|
|
}
|
|
|
|
InvalidateRect(songlist_hwnd, 0, FALSE);
|
|
}
|
|
}
|
|
if (cdda_stream)
|
|
{
|
|
if (FSOUND_Stream_GetLengthMs(cdda_stream) && !DraggingCDSlider)
|
|
{
|
|
SendMessage(GetDlgItem(hwnd,IDC_CDTIME), TBM_SETPOS, TRUE, (int)((float)FSOUND_Stream_GetTime(cdda_stream) * 1000.0f / (float)FSOUND_Stream_GetLengthMs(cdda_stream)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (FSOUND_CD_GetTrack(cddevice))
|
|
{
|
|
if (FSOUND_CD_GetTrackLength(cddevice, FSOUND_CD_GetTrack(cddevice)) && !DraggingCDSlider)
|
|
{
|
|
SendMessage(GetDlgItem(hwnd,IDC_CDTIME), TBM_SETPOS, TRUE, (int)((float)FSOUND_CD_GetTrackTime(cddevice) * 1000.0f / (float)FSOUND_CD_GetTrackLength(cddevice, FSOUND_CD_GetTrack(cddevice))));
|
|
}
|
|
}
|
|
}
|
|
|
|
DeleteObject(myfont);
|
|
ReleaseDC(hwnd, hdc);
|
|
break;
|
|
}
|
|
|
|
case WM_MEASUREITEM:
|
|
{
|
|
LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam;
|
|
TEXTMETRIC m;
|
|
HDC hdc;
|
|
|
|
hdc = GetDC(hwnd);
|
|
|
|
GetTextMetrics(hdc, &m);
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
lpmis->itemHeight = m.tmAscent;
|
|
return TRUE;
|
|
}
|
|
case WM_DRAWITEM:
|
|
{
|
|
DRAWITEMSTRUCT FAR *pDIS;
|
|
DWORD crBack;
|
|
DWORD crText;
|
|
HBRUSH hbrBack;
|
|
char szBuf[MAX_PATH];
|
|
int state;
|
|
|
|
#define PHDC (pDIS->hDC)
|
|
#define PRC (pDIS->rcItem)
|
|
|
|
pDIS = (DRAWITEMSTRUCT FAR *)lParam;
|
|
|
|
if (pDIS->itemID < 0)
|
|
{
|
|
break;
|
|
|
|
}
|
|
memset(szBuf, 0, MAX_PATH);
|
|
|
|
/* Draw the focus rectangle for an empty list box or an
|
|
empty combo box to indicate that the control has the
|
|
focus
|
|
*/
|
|
if ((int)(pDIS->itemID) < 0)
|
|
{
|
|
switch(pDIS->CtlType)
|
|
{
|
|
case ODT_LISTBOX:
|
|
{
|
|
if ((pDIS->itemAction) & (ODA_FOCUS))
|
|
{
|
|
DrawFocusRect (PHDC, &PRC);
|
|
}
|
|
break;
|
|
}
|
|
case ODT_COMBOBOX:
|
|
{
|
|
if ((pDIS->itemState) & (ODS_FOCUS))
|
|
{
|
|
DrawFocusRect (PHDC, &PRC);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* Get the string */
|
|
switch(pDIS->CtlType)
|
|
{
|
|
case ODT_LISTBOX:
|
|
{
|
|
SendMessage ( pDIS->hwndItem, LB_GETTEXT, pDIS->itemID, (LPARAM)(LPSTR)szBuf);
|
|
break;
|
|
}
|
|
case ODT_COMBOBOX:
|
|
{
|
|
SendMessage ( pDIS->hwndItem, CB_GETLBTEXT, pDIS->itemID, (LPARAM)(LPSTR)szBuf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if ((pDIS->itemState) & (ODS_SELECTED))
|
|
{
|
|
/* Set background and text colors for selected item */
|
|
crBack = GetSysColor (COLOR_HIGHLIGHT);
|
|
}
|
|
else
|
|
{
|
|
/* Set background and text colors for unselected item */
|
|
crBack = GetSysColor (COLOR_WINDOW);
|
|
}
|
|
|
|
if (song[pDIS->itemID].mod)
|
|
{
|
|
state = FMUSIC_GetOpenState(song[pDIS->itemID].mod);
|
|
}
|
|
if (song[pDIS->itemID].stream)
|
|
{
|
|
state = FSOUND_Stream_GetOpenState(song[pDIS->itemID].stream);
|
|
}
|
|
if (song[pDIS->itemID].cdtrack)
|
|
{
|
|
if (setting_cdda && cdda_stream)
|
|
{
|
|
state = FSOUND_Stream_GetOpenState(cdda_stream);
|
|
}
|
|
else
|
|
{
|
|
state = 0;
|
|
}
|
|
}
|
|
|
|
switch (state)
|
|
{
|
|
case 0: crText = (pDIS->itemState & ODS_SELECTED) ? GetSysColor(COLOR_HIGHLIGHTTEXT) : GetSysColor(COLOR_WINDOWTEXT) ; break;
|
|
case -1: crText = (pDIS->itemState & ODS_SELECTED) ? GetSysColor(COLOR_HIGHLIGHTTEXT) : RGB(255, 0, 0) ; break;
|
|
case -2: crText = (pDIS->itemState & ODS_SELECTED) ? GetSysColor(COLOR_HIGHLIGHTTEXT) : RGB(192, 192, 192) ; break;
|
|
case -3: crText = (pDIS->itemState & ODS_SELECTED) ? GetSysColor(COLOR_HIGHLIGHTTEXT) : RGB(255, 0, 0) ; break;
|
|
case -4: crText = (pDIS->itemState & ODS_SELECTED) ? GetSysColor(COLOR_HIGHLIGHTTEXT) : RGB(0, 0, 255) ; break;
|
|
case -5: crText = (pDIS->itemState & ODS_SELECTED) ? GetSysColor(COLOR_HIGHLIGHTTEXT) : RGB(0, 0, 255) ; break;
|
|
}
|
|
|
|
// Fill item rectangle with background color
|
|
hbrBack = CreateSolidBrush (crBack);
|
|
FillRect (PHDC, &PRC, hbrBack);
|
|
DeleteObject (hbrBack);
|
|
|
|
// Set current background and text colors
|
|
SetBkColor (PHDC, crBack);
|
|
SetTextColor (PHDC, crText);
|
|
|
|
// TextOut uses current background and text colors
|
|
TextOut ( PHDC, PRC.left, PRC.top, szBuf, lstrlen(szBuf));
|
|
|
|
/* If enabled item has the input focus, call DrawFocusRect to set or clear the focus rectangle */
|
|
if ((pDIS->itemState) & (ODS_FOCUS))
|
|
{
|
|
DrawFocusRect (PHDC, &PRC);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
#ifdef _WIN64
|
|
INT_PTR CALLBACK FMOD_StreamDetailsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
#else
|
|
BOOL CALLBACK FMOD_StreamDetailsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
#endif
|
|
{
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG :
|
|
{
|
|
RECT r;
|
|
char str[8192];
|
|
char tmp[4096];
|
|
int songid, numinfo, i, bitrate;
|
|
signed char twotabs = FALSE;
|
|
|
|
songid = (int)SendMessage(songlist_hwnd, LB_GETCURSEL, 0, 0);
|
|
str[0] = 0;
|
|
|
|
FSOUND_Stream_GetNumTagFields(song[songid].stream, &numinfo);
|
|
|
|
for (i=0;i < numinfo;i++)
|
|
{
|
|
char *name, *value;
|
|
int type, length;
|
|
char *str_streaminfotype[6] =
|
|
{
|
|
"VORBIS",
|
|
"ID3V1",
|
|
"ID3V2",
|
|
"SHOUTcast",
|
|
"Icecast",
|
|
"ASF"
|
|
};
|
|
|
|
if (FSOUND_Stream_GetTagField(song[songid].stream, i, &type, &name, &value, &length))
|
|
{
|
|
if (type == FSOUND_TAGFIELD_SHOUTCAST)
|
|
{
|
|
twotabs = TRUE;
|
|
}
|
|
|
|
if (type == FSOUND_TAGFIELD_ID3V2 && ((name[0] == 'T' && value[0] == 0) || !strncmp(name, "COMM", 4)))
|
|
{
|
|
char tmp2[2048];
|
|
int offset = 0;
|
|
|
|
if (name[0] == 'T' && value[0] == 0)
|
|
{
|
|
offset = 1;
|
|
}
|
|
else if (!strncmp(name, "COMM", 4) && length > 8)
|
|
{
|
|
offset = 8; /* a quick hack to skip the COMM tag stuff at the start (language etc), check id3.org for more */
|
|
}
|
|
|
|
strncpy(tmp2, value + offset, length - offset);
|
|
|
|
tmp2[length - 1] = 0;
|
|
|
|
sprintf(tmp, "%s\t%s = %s (%d bytes)\r\n", str_streaminfotype[type], name, tmp2, length);
|
|
}
|
|
else
|
|
{
|
|
if (type != FSOUND_TAGFIELD_SHOUTCAST)
|
|
{
|
|
sprintf(tmp, "%s%s%s = %s (%d bytes)\r\n", str_streaminfotype[type], twotabs ? "\t\t" : "\t", name, value, length);
|
|
}
|
|
else
|
|
{
|
|
sprintf(tmp, "%s\t%s = %s (%d bytes)\r\n", str_streaminfotype[type], name, value, length);
|
|
}
|
|
}
|
|
|
|
strcat(str, tmp);
|
|
}
|
|
}
|
|
|
|
if (FSOUND_Stream_Net_GetStatus(song[songid].stream, 0, 0, &bitrate, 0))
|
|
{
|
|
sprintf(tmp, "Current bitrate : %d\r\n", bitrate);
|
|
strcat(str, tmp);
|
|
}
|
|
|
|
SetWindowText(GetDlgItem(hwnd, IDC_STREAMDETAILSEDIT), str);
|
|
PostMessage(GetDlgItem(hwnd, IDC_STREAMDETAILSEDIT), EM_SETSEL, 0, 0);
|
|
GetClientRect(hwnd, &r);
|
|
MoveWindow(GetDlgItem(hwnd, IDC_STREAMDETAILSEDIT), 0, 0, r.right, r.bottom, TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_COMMAND :
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK :
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_SIZE :
|
|
MoveWindow(GetDlgItem(hwnd, IDC_STREAMDETAILSEDIT), 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
|
|
return 0;
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hwnd, 0);
|
|
return TRUE;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
#ifdef _WIN64
|
|
INT_PTR CALLBACK FMOD_InfoDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
#else
|
|
BOOL CALLBACK FMOD_InfoDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
#endif
|
|
{
|
|
switch (msg)
|
|
{
|
|
case WM_COMMAND :
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_NETSTREAMINFO_DETAILS :
|
|
{
|
|
int songid = (int)SendMessage(songlist_hwnd, LB_GETCURSEL, 0, 0);
|
|
if ((songid >= 0) && song[songid].stream)
|
|
{
|
|
DialogBox(g_hinst, MAKEINTRESOURCE(IDD_STREAMDETAILSDLG), mainhwnd, FMOD_StreamDetailsDlgProc);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_CLOSE:
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
#ifdef _WIN64
|
|
INT_PTR CALLBACK FMOD_LoadURLDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
#else
|
|
BOOL CALLBACK FMOD_LoadURLDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
#endif
|
|
{
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG :
|
|
{
|
|
int i;
|
|
HWND h = GetDlgItem(hwnd, IDC_URLCOMBO);
|
|
|
|
ComboBox_ResetContent(h);
|
|
|
|
for (i=0;i < MRU_MAX;i++)
|
|
{
|
|
if (!mru[i])
|
|
{
|
|
break;
|
|
}
|
|
|
|
ComboBox_AddString(h, mru[i]);
|
|
}
|
|
|
|
url_to_load[0] = 0;
|
|
SetFocus(hwnd);
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK :
|
|
{
|
|
ComboBox_GetText(GetDlgItem(hwnd, IDC_URLCOMBO), url_to_load, 4095);
|
|
if (strlen(url_to_load))
|
|
{
|
|
AddToMRU(url_to_load);
|
|
}
|
|
EndDialog(hwnd, 1);
|
|
return TRUE;
|
|
}
|
|
|
|
case IDCANCEL :
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_CLOSE :
|
|
{
|
|
EndDialog(hwnd, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
BOOL AddToMRU(char *url)
|
|
{
|
|
int i, j;
|
|
|
|
for (i=0;i < MRU_MAX;i++)
|
|
{
|
|
if (!mru[i])
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (!strcmp(mru[i], url))
|
|
{
|
|
if (i)
|
|
{
|
|
char *tmp = mru[i];
|
|
for (j=i;j > 0;j--)
|
|
{
|
|
mru[j] = mru[j - 1];
|
|
}
|
|
mru[0] = tmp;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i=MRU_MAX - 1;i > 0;i--)
|
|
{
|
|
mru[i] = mru[i - 1];
|
|
}
|
|
|
|
mru[0] = strdup(url);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
BOOL UpdateStreamInfo(int songid, BOOL forceupdate)
|
|
{
|
|
char s[256];
|
|
static int last_songid = -1;
|
|
static unsigned int last_pos = -1;
|
|
static int last_time = -1;
|
|
BOOL update = forceupdate;
|
|
FSOUND_STREAM *stream;
|
|
|
|
if (!song[songid].stream)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
stream = song[songid].stream;
|
|
|
|
if (songid != last_songid)
|
|
{
|
|
update = TRUE;
|
|
}
|
|
|
|
if (update)
|
|
{
|
|
sprintf(s, "Name\t%s", FSOUND_Sample_GetName(FSOUND_Stream_GetSample(stream)));
|
|
SetWindowText(GetDlgItem(streaminfo_hwnd, IDC_STREAMINFO_NAME), s);
|
|
}
|
|
|
|
if ((last_pos != FSOUND_Stream_GetPosition(stream)) || update)
|
|
{
|
|
sprintf(s, "Pos\t%d/%d", FSOUND_Stream_GetPosition(stream), FSOUND_Stream_GetLength(stream));
|
|
SetWindowText(GetDlgItem(streaminfo_hwnd, IDC_STREAMINFO_POSITION), s);
|
|
}
|
|
|
|
if ((last_time != FSOUND_Stream_GetTime(stream)) || update)
|
|
{
|
|
sprintf(s, "Pos\t%d/%d", FSOUND_Stream_GetPosition(stream), FSOUND_Stream_GetLength(stream));
|
|
SetWindowText(GetDlgItem(streaminfo_hwnd, IDC_STREAMINFO_POSITION), s);
|
|
sprintf(s, "Time\t%02d:%02d/%02d:%02d", FSOUND_Stream_GetTime(stream) / 1000 / 60,
|
|
FSOUND_Stream_GetTime(stream) / 1000 % 60,
|
|
FSOUND_Stream_GetLengthMs(stream) / 1000 / 60,
|
|
FSOUND_Stream_GetLengthMs(stream) / 1000 % 60);
|
|
SetWindowText(GetDlgItem(streaminfo_hwnd, IDC_STREAMINFO_TIME), s);
|
|
}
|
|
|
|
last_time = FSOUND_Stream_GetTime(stream);
|
|
last_pos = FSOUND_Stream_GetPosition(stream);
|
|
last_songid = songid;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
BOOL UpdateCDInfo(int songid, BOOL forceupdate)
|
|
{
|
|
char s[256];
|
|
static int last_songid = -1;
|
|
static unsigned int last_time = -1;
|
|
BOOL update = forceupdate;
|
|
unsigned int pos, length;
|
|
|
|
if (!song[songid].cdtrack)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (setting_cdda && !cdda_stream)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (songid != last_songid)
|
|
{
|
|
update = TRUE;
|
|
}
|
|
|
|
if (update)
|
|
{
|
|
sprintf(s, "Name\tTrack %02d", song[songid].cdtrack);
|
|
SetWindowText(GetDlgItem(cdinfo_hwnd, IDC_CDINFO_NAME), s);
|
|
}
|
|
|
|
if ((setting_cdda && (song[songid].channel != -1)) || (!setting_cdda && (FSOUND_CD_GetTrack(cddevice) == song[songid].cdtrack)))
|
|
{
|
|
pos = setting_cdda ? FSOUND_Stream_GetTime(cdda_stream) : FSOUND_CD_GetTrackTime(cddevice);
|
|
length = setting_cdda ? FSOUND_Stream_GetLengthMs(cdda_stream) : FSOUND_CD_GetTrackLength(cddevice, FSOUND_CD_GetTrack(cddevice));
|
|
|
|
if ((last_time != pos) || update)
|
|
{
|
|
sprintf(s, "Time\t%02d:%02d/%02d:%02d", pos / 1000 / 60,
|
|
pos / 1000 % 60,
|
|
length / 1000 / 60,
|
|
length / 1000 % 60);
|
|
SetWindowText(GetDlgItem(cdinfo_hwnd, IDC_CDINFO_TIME), s);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (setting_cdda && (song[songid].channel == -1))
|
|
{
|
|
sprintf(s, "Time\t%02d:%02d/%02d:%02d", 0 / 1000 / 60,
|
|
0 / 1000 % 60,
|
|
song[songid].cdtrack_length / 1000 / 60,
|
|
song[songid].cdtrack_length / 1000 % 60);
|
|
SetWindowText(GetDlgItem(cdinfo_hwnd, IDC_CDINFO_TIME), s);
|
|
}
|
|
else
|
|
{
|
|
sprintf(s, "Time\t%02d:%02d/%02d:%02d", 0 / 1000 / 60,
|
|
0 / 1000 % 60,
|
|
0 / 1000 / 60,
|
|
0 / 1000 % 60);
|
|
SetWindowText(GetDlgItem(cdinfo_hwnd, IDC_CDINFO_TIME), s);
|
|
}
|
|
}
|
|
|
|
last_time = pos;
|
|
last_songid = songid;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
BOOL UpdateNetStreamInfo(int songid, BOOL forceupdate, BOOL forceqiuet)
|
|
{
|
|
static int last_songid = -1;
|
|
static int last_read_percent = -1;
|
|
signed char update = forceupdate;
|
|
int status, off, len, flags;
|
|
char str[4096];
|
|
char *tmp;
|
|
|
|
if (!song[songid].url)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (song[songid].stream)
|
|
{
|
|
int ret = FSOUND_Stream_GetOpenState(song[songid].stream);
|
|
if ((ret == -3) || (ret == -1))
|
|
{
|
|
status = FSOUND_STREAM_NET_ERROR;
|
|
if (song[songid].last_netstatus != status)
|
|
{
|
|
char *s;
|
|
|
|
if (song[songid].server_status)
|
|
{
|
|
free(song[songid].server_status);
|
|
song[songid].server_status = 0;
|
|
}
|
|
|
|
s = FSOUND_Stream_Net_GetLastServerStatus();
|
|
if (s)
|
|
{
|
|
song[songid].server_status = strdup(s);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FSOUND_Stream_Net_GetStatus(song[songid].stream, &status, 0, 0, 0);
|
|
|
|
if ((status == FSOUND_STREAM_NET_READY) && (song[songid].channel == -1))
|
|
{
|
|
song[songid].channel = FSOUND_Stream_Play(FSOUND_FREE, song[songid].stream);
|
|
if (song[songid].channel != -1)
|
|
{
|
|
FSOUND_Stream_Net_SetMetadataCallback(song[songid].stream, MetadataCallback, (void *)songid);
|
|
update = TRUE;
|
|
}
|
|
}
|
|
|
|
if (FSOUND_Stream_GetOpenState(song[songid].stream) == 0)
|
|
{
|
|
off = FSOUND_Stream_GetTime(song[songid].stream);
|
|
len = FSOUND_Stream_GetLengthMs(song[songid].stream);
|
|
|
|
if (off >= len)
|
|
{
|
|
FSOUND_Stream_Close(song[songid].stream);
|
|
song[songid].stream = 0;
|
|
song[songid].channel = -1;
|
|
song[songid].last_status = -2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
status = FSOUND_STREAM_NET_NOTCONNECTED;
|
|
}
|
|
|
|
if ((songid != last_songid) || (status != song[songid].last_netstatus))
|
|
{
|
|
update = TRUE;
|
|
}
|
|
|
|
if (song[songid].metadata)
|
|
{
|
|
song[songid].metadata = 0;
|
|
update = TRUE;
|
|
}
|
|
|
|
last_songid = songid;
|
|
song[songid].last_netstatus = status;
|
|
|
|
if (!forceqiuet)
|
|
{
|
|
if (update)
|
|
{
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_STREAM), "Stream");
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_TRACK), "Track");
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_PROTOCOL), "Proto");
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_FORMAT), "Format");
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_STATUS), "Status");
|
|
|
|
if (!song[songid].url)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
switch (status)
|
|
{
|
|
case FSOUND_STREAM_NET_NOTCONNECTED :
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_STATUS), "Status\tNot playing");
|
|
break;
|
|
|
|
case FSOUND_STREAM_NET_CONNECTING :
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_STATUS), "Status\tConnecting...");
|
|
break;
|
|
|
|
case FSOUND_STREAM_NET_BUFFERING :
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_STATUS), "Status\tBuffering...");
|
|
break;
|
|
|
|
case FSOUND_STREAM_NET_ERROR :
|
|
{
|
|
if (song[songid].server_status)
|
|
{
|
|
char tmp[1024];
|
|
sprintf(tmp, "Status\t%s", song[songid].server_status);
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_STATUS), tmp);
|
|
}
|
|
else
|
|
{
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_STATUS), "Status\tError");
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FSOUND_STREAM_NET_READY :
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_STATUS), "Status\tPlaying");
|
|
break;
|
|
|
|
default :
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_STATUS), "Status\tUnknown");
|
|
break;
|
|
}
|
|
|
|
if (status != FSOUND_STREAM_NET_NOTCONNECTED)
|
|
{
|
|
sprintf(str, "Track\t%s%s%s", song[songid].artist ? song[songid].artist : "", song[songid].title ? " - " : "", song[songid].title ? song[songid].title : "");
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_TRACK), str);
|
|
|
|
if (song[songid].protocol)
|
|
{
|
|
sprintf(str, "Proto\t%s", song[songid].protocol);
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_PROTOCOL), str);
|
|
}
|
|
|
|
if (song[songid].format)
|
|
{
|
|
sprintf(str, "Format\t%s", song[songid].format);
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_FORMAT), str);
|
|
}
|
|
|
|
if (song[songid].streamname)
|
|
{
|
|
sprintf(str, "Stream\t%s", song[songid].streamname);
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_STREAM), str);
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
int read_percent;
|
|
|
|
FSOUND_Stream_Net_GetStatus(song[songid].stream, 0, &read_percent, 0, 0);
|
|
if (read_percent != last_read_percent)
|
|
{
|
|
SendMessage(GetDlgItem(mainhwnd, IDC_PROGRESS1), PBM_SETRANGE, 0, MAKELPARAM(0, 100) );
|
|
SendMessage(GetDlgItem(mainhwnd, IDC_PROGRESS1), PBM_SETPOS, (WPARAM)read_percent, 0);
|
|
}
|
|
}
|
|
|
|
if (FSOUND_Stream_Net_GetStatus(song[songid].stream, 0, 0, 0, &flags))
|
|
{
|
|
if (!song[songid].protocol)
|
|
{
|
|
char *str_protocol[3] =
|
|
{
|
|
"SHOUTcast",
|
|
"Icecast",
|
|
"HTTP"
|
|
};
|
|
|
|
if (flags & FSOUND_PROTOCOL_SHOUTCAST)
|
|
{
|
|
tmp = str_protocol[0];
|
|
}
|
|
else if (flags & FSOUND_PROTOCOL_ICECAST)
|
|
{
|
|
tmp = str_protocol[1];
|
|
}
|
|
else if (flags & FSOUND_PROTOCOL_HTTP)
|
|
{
|
|
tmp = str_protocol[2];
|
|
}
|
|
else
|
|
{
|
|
tmp = 0;
|
|
}
|
|
|
|
if (tmp)
|
|
{
|
|
song[songid].protocol = tmp;
|
|
sprintf(str, "Proto\t%s", tmp);
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_PROTOCOL), str);
|
|
}
|
|
}
|
|
|
|
if (!song[songid].format)
|
|
{
|
|
char *str_format[2] =
|
|
{
|
|
"MPEG Layer 3",
|
|
"Ogg Vorbis"
|
|
};
|
|
|
|
if (flags & FSOUND_FORMAT_MPEG)
|
|
{
|
|
tmp = str_format[0];
|
|
}
|
|
else if (flags & FSOUND_FORMAT_OGGVORBIS)
|
|
{
|
|
tmp = str_format[1];
|
|
}
|
|
else
|
|
{
|
|
tmp = 0;
|
|
}
|
|
|
|
if (tmp)
|
|
{
|
|
song[songid].format = tmp;
|
|
sprintf(str, "Format\t%s", tmp);
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_FORMAT), str);
|
|
}
|
|
}
|
|
|
|
if (!song[songid].streamname)
|
|
{
|
|
if (flags & FSOUND_PROTOCOL_SHOUTCAST)
|
|
{
|
|
FSOUND_Stream_FindTagField(song[songid].stream, FSOUND_TAGFIELD_SHOUTCAST, "icy-name", &tmp, 0);
|
|
}
|
|
else if (flags & FSOUND_PROTOCOL_ICECAST)
|
|
{
|
|
FSOUND_Stream_FindTagField(song[songid].stream, FSOUND_TAGFIELD_ICECAST, "ice-name", &tmp, 0);
|
|
}
|
|
else if (flags & FSOUND_PROTOCOL_HTTP)
|
|
{
|
|
tmp = song[songid].url;
|
|
}
|
|
else
|
|
{
|
|
tmp = 0;
|
|
}
|
|
|
|
if (tmp)
|
|
{
|
|
song[songid].streamname = tmp;
|
|
sprintf(str, "Stream\t%s", tmp);
|
|
SetWindowText(GetDlgItem(netstreaminfo_hwnd, IDC_NETSTREAMINFO_STREAM), str);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
BOOL UpdateModInfo(int songid, BOOL forceupdate)
|
|
{
|
|
char s[256];
|
|
static int last_songid = -1;
|
|
static int last_speed = -1;
|
|
static int last_bpm = -1;
|
|
static int last_order = -1;
|
|
static int last_pattern = -1;
|
|
static int last_row = -1;
|
|
char *type[] =
|
|
{
|
|
"Unknown ",
|
|
"Protracker / FastTracker ",
|
|
"ScreamTracker 3 ",
|
|
"FastTracker 2 ",
|
|
"Impulse Tracker ",
|
|
"MIDI ",
|
|
"FMOD Sample Bank "
|
|
};
|
|
FMUSIC_MODULE *mod = song[songid].mod;
|
|
BOOL update = forceupdate;
|
|
|
|
if (!song[songid].mod)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (songid != last_songid)
|
|
{
|
|
update = TRUE;
|
|
}
|
|
|
|
if (update)
|
|
{
|
|
sprintf(s, "Name\t%s", FMUSIC_GetName(mod));
|
|
SetWindowText(GetDlgItem(modinfo_hwnd, IDC_MODINFO_NAME), s);
|
|
|
|
sprintf(s, "Type\t%s", type[FMUSIC_GetType(mod)]);
|
|
SetWindowText(GetDlgItem(modinfo_hwnd, IDC_MODINFO_TYPE), s);
|
|
}
|
|
|
|
if ((last_speed != FMUSIC_GetSpeed(mod)) || update)
|
|
{
|
|
sprintf(s, "Speed\t%02d", FMUSIC_GetSpeed(mod));
|
|
SetWindowText(GetDlgItem(modinfo_hwnd, IDC_MODINFO_SPEED), s);
|
|
}
|
|
|
|
if ((last_bpm != FMUSIC_GetBPM(mod)) || update)
|
|
{
|
|
sprintf(s, "BPM\t%03d", FMUSIC_GetBPM(mod));
|
|
SetWindowText(GetDlgItem(modinfo_hwnd, IDC_MODINFO_BPM), s);
|
|
}
|
|
|
|
if ((last_order != FMUSIC_GetOrder(mod)) || update)
|
|
{
|
|
sprintf(s, "Order\t%03d / %03d", FMUSIC_GetOrder(mod), FMUSIC_GetNumOrders(mod));
|
|
SetWindowText(GetDlgItem(modinfo_hwnd, IDC_MODINFO_ORDER), s);
|
|
}
|
|
|
|
if ((last_pattern != FMUSIC_GetPattern(mod)) || update)
|
|
{
|
|
sprintf(s, "Pattern\t%03d / %03d", FMUSIC_GetPattern(mod), FMUSIC_GetNumPatterns(mod));
|
|
SetWindowText(GetDlgItem(modinfo_hwnd, IDC_MODINFO_PATTERN), s);
|
|
}
|
|
|
|
if ((last_row != FMUSIC_GetRow(mod)) || (last_order != FMUSIC_GetOrder(mod)) || update)
|
|
{
|
|
sprintf(s, "Row\t%03d / %03d", FMUSIC_GetRow(mod), FMUSIC_GetPatternLength(mod, FMUSIC_GetOrder(mod)));
|
|
SetWindowText(GetDlgItem(modinfo_hwnd, IDC_MODINFO_ROW), s);
|
|
}
|
|
|
|
last_speed = FMUSIC_GetSpeed(mod);
|
|
last_bpm = FMUSIC_GetBPM(mod);
|
|
last_order = FMUSIC_GetOrder(mod);
|
|
last_pattern = FMUSIC_GetPattern(mod);
|
|
last_row = FMUSIC_GetRow(mod);
|
|
last_songid = songid;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
void SelectInfoWindow()
|
|
{
|
|
int songid;
|
|
int songtype = SONGTYPE_NONE;
|
|
|
|
ShowWindow(modinfo_hwnd, SW_HIDE);
|
|
ShowWindow(streaminfo_hwnd, SW_HIDE);
|
|
ShowWindow(netstreaminfo_hwnd, SW_HIDE);
|
|
ShowWindow(cdinfo_hwnd, SW_HIDE);
|
|
|
|
if (GraphicWindowCurrent == GRAPHICWINDOW_MODINFO)
|
|
{
|
|
songid = (int)SendMessage(songlist_hwnd, LB_GETCURSEL, 0, 0);
|
|
if (songid != LB_ERR)
|
|
{
|
|
songtype = song[songid].mod ? SONGTYPE_MOD : song[songid].url ? SONGTYPE_NETSTREAM : song[songid].stream ? SONGTYPE_STREAM : song[songid].cdtrack ? SONGTYPE_CD : SONGTYPE_NONE;
|
|
}
|
|
|
|
switch (songtype)
|
|
{
|
|
case SONGTYPE_MOD :
|
|
SendMessage(GetDlgItem(mainhwnd, IDC_STATIC_INFO), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)"Module Info");
|
|
ShowWindow(modinfo_hwnd, SW_SHOW);
|
|
break;
|
|
|
|
case SONGTYPE_STREAM :
|
|
SendMessage(GetDlgItem(mainhwnd, IDC_STATIC_INFO), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)"Stream Info");
|
|
ShowWindow(streaminfo_hwnd, SW_SHOW);
|
|
break;
|
|
|
|
case SONGTYPE_NETSTREAM :
|
|
SendMessage(GetDlgItem(mainhwnd, IDC_STATIC_INFO), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)"Net Stream Info");
|
|
ShowWindow(netstreaminfo_hwnd, SW_SHOW);
|
|
break;
|
|
|
|
case SONGTYPE_CD :
|
|
SendMessage(GetDlgItem(mainhwnd, IDC_STATIC_INFO), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)"CD Track Info");
|
|
ShowWindow(cdinfo_hwnd, SW_SHOW);
|
|
break;
|
|
|
|
case SONGTYPE_NONE :
|
|
SendMessage(GetDlgItem(mainhwnd, IDC_STATIC_INFO), WM_SETTEXT, 0, (LPARAM)(LPCTSTR)"No file loaded");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
[API]
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
char SetupInterface(HINSTANCE hinst, LPSTR lpCmdLine)
|
|
{
|
|
char name[2048];
|
|
RECT r;
|
|
int desktop_height,desktop_width;
|
|
int window_height,window_width;
|
|
int i;
|
|
|
|
for (i=0;i < MRU_MAX;i++)
|
|
{
|
|
mru[i] = 0;
|
|
}
|
|
|
|
LoadSettings();
|
|
|
|
GetWindowRect(GetDesktopWindow(), &r);
|
|
desktop_width = r.right - r.left;
|
|
desktop_height = r.bottom - r.top;
|
|
|
|
/*
|
|
Fix up screwed up xy positions
|
|
*/
|
|
if (setting_xpos > desktop_width || setting_xpos < 0)
|
|
{
|
|
setting_xpos = (desktop_width / 2)-320;
|
|
}
|
|
if (setting_ypos > desktop_height || setting_ypos < 0)
|
|
{
|
|
setting_ypos = (desktop_height / 2)-140;
|
|
}
|
|
|
|
mainhwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_INTERFACE), GetDesktopWindow(), FMOD_DlgProc);
|
|
|
|
ShowWindow(mainhwnd, SW_HIDE);
|
|
|
|
sprintf(name, "FMOD %.2f", FMOD_VERSION);
|
|
SetWindowText(mainhwnd, name);
|
|
|
|
|
|
/*
|
|
Set the icon
|
|
*/
|
|
#ifdef _WIN64
|
|
SetClassLong(mainhwnd, GCLP_HICON, (LONG) LoadIcon(hinst, MAKEINTRESOURCE(IDI_ICON1)));
|
|
#else
|
|
SetClassLong(mainhwnd, GCL_HICON, (LONG) LoadIcon(hinst, MAKEINTRESOURCE(IDI_ICON1)));
|
|
#endif
|
|
|
|
GetWindowRect(mainhwnd, &r);
|
|
MoveWindow(mainhwnd, setting_xpos, setting_ypos, r.right, r.bottom, TRUE);
|
|
|
|
window_width = r.right - r.left;
|
|
window_height = r.bottom - r.top;
|
|
scalex = (float)window_width / WINDOW_WIDTH;
|
|
scaley = (float)window_height / WINDOW_HEIGHT;
|
|
|
|
ShowWindow(mainhwnd, SW_SHOW);
|
|
|
|
InitCommonControls();
|
|
|
|
/*
|
|
Set the range of the master volume slider
|
|
*/
|
|
SendMessage(GetDlgItem(mainhwnd,IDC_SLIDER1), TBM_SETRANGE, TRUE, MAKELPARAM(0, 256));
|
|
|
|
/*
|
|
Set position of the master volume slider
|
|
*/
|
|
SendMessage(GetDlgItem(mainhwnd,IDC_SLIDER1), TBM_SETPOS, TRUE, 256);
|
|
|
|
/*
|
|
set the range of the echo slider
|
|
set position of the echo slider
|
|
set status
|
|
*/
|
|
SendMessage(GetDlgItem(mainhwnd,IDC_ECHOSLIDER), TBM_SETRANGE, TRUE, MAKELPARAM(20, 500));
|
|
SendMessage(GetDlgItem(mainhwnd,IDC_ECHOSLIDER), TBM_SETPOS, TRUE, 500);
|
|
ShowWindow(GetDlgItem(mainhwnd,IDC_ECHOSLIDER), SW_HIDE);
|
|
|
|
/*
|
|
set the range of the cutoff freq slider
|
|
set position of the cutoff freq slider
|
|
set status
|
|
*/
|
|
SendMessage(GetDlgItem(mainhwnd,IDC_CUTOFFSLIDER), TBM_SETRANGE, TRUE, MAKELPARAM(20, 500));
|
|
SendMessage(GetDlgItem(mainhwnd,IDC_CUTOFFSLIDER), TBM_SETPOS, TRUE, 20);
|
|
ShowWindow(GetDlgItem(mainhwnd,IDC_CUTOFFSLIDER), SW_HIDE);
|
|
|
|
/*
|
|
set the range of the resonance slider
|
|
set position of the resonance slider
|
|
set status
|
|
*/
|
|
SendMessage(GetDlgItem(mainhwnd,IDC_RESOSLIDER), TBM_SETRANGE, TRUE, MAKELPARAM(20, 500));
|
|
SendMessage(GetDlgItem(mainhwnd,IDC_RESOSLIDER), TBM_SETPOS, TRUE, 500);
|
|
ShowWindow(GetDlgItem(mainhwnd,IDC_RESOSLIDER), SW_HIDE);
|
|
|
|
/*
|
|
COMMAND LINE
|
|
*/
|
|
if (strlen(lpCmdLine))
|
|
{
|
|
Playlist *p;
|
|
int i;
|
|
char *filename = name;
|
|
|
|
strcpy(filename, lpCmdLine);
|
|
|
|
if (*filename == '"')
|
|
{
|
|
filename++;
|
|
}
|
|
|
|
if (filename[strlen(filename) - 1] == '"')
|
|
{
|
|
filename[strlen(filename) - 1] = 0;
|
|
}
|
|
|
|
/*
|
|
Open the file.
|
|
*/
|
|
p = ParsePlaylist(filename);
|
|
if (p)
|
|
{
|
|
for (i=0;i < p->count;i++)
|
|
{
|
|
AddFileToSongList(p->name[i], p->displayname[i]);
|
|
}
|
|
|
|
FreePlaylist(p);
|
|
}
|
|
else
|
|
{
|
|
AddFileToSongList(filename, filename);
|
|
}
|
|
}
|
|
|
|
srand(clock());
|
|
Button_SetCheck(GetDlgItem(mainhwnd,IDC_RADIOCONTINUOUS), TRUE);
|
|
|
|
/*
|
|
Subclass the position slider so we can get the mouse messages and process them there
|
|
*/
|
|
#ifdef _WIN64
|
|
oldprogressproc = (WNDPROC)GetWindowLong(GetDlgItem(mainhwnd, IDC_PROGRESS1), GWLP_WNDPROC);
|
|
oldcdtimeproc = (WNDPROC)GetWindowLong(GetDlgItem(mainhwnd, IDC_CDTIME), GWLP_WNDPROC);
|
|
|
|
SetWindowLong(GetDlgItem(mainhwnd, IDC_PROGRESS1), GWLP_WNDPROC, (LONG)&ProgressWindowProc);
|
|
SetWindowLong(GetDlgItem(mainhwnd, IDC_CDTIME), GWLP_WNDPROC, (LONG)&CDTimeWindowProc);
|
|
#else
|
|
oldprogressproc = (WNDPROC)GetWindowLong(GetDlgItem(mainhwnd, IDC_PROGRESS1), GWL_WNDPROC);
|
|
oldcdtimeproc = (WNDPROC)GetWindowLong(GetDlgItem(mainhwnd, IDC_CDTIME), GWL_WNDPROC);
|
|
|
|
SetWindowLong(GetDlgItem(mainhwnd, IDC_PROGRESS1), GWL_WNDPROC, (LONG)&ProgressWindowProc);
|
|
SetWindowLong(GetDlgItem(mainhwnd, IDC_CDTIME), GWL_WNDPROC, (LONG)&CDTimeWindowProc);
|
|
#endif
|
|
|
|
SetWindowText(GetDlgItem(mainhwnd, IDC_STATIC_INFO), "No file loaded");
|
|
SetWindowText(GetDlgItem(mainhwnd, IDC_INFOWINDOW), "");
|
|
|
|
streaminfo_hwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_STREAMINFODLG), GetDlgItem(mainhwnd, IDC_INFOWINDOW), FMOD_InfoDlgProc);
|
|
ShowWindow(streaminfo_hwnd, SW_HIDE);
|
|
|
|
netstreaminfo_hwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_NETSTREAMINFODLG), GetDlgItem(mainhwnd, IDC_INFOWINDOW), FMOD_InfoDlgProc);
|
|
ShowWindow(netstreaminfo_hwnd, SW_HIDE);
|
|
|
|
cdinfo_hwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_CDINFODLG), GetDlgItem(mainhwnd, IDC_INFOWINDOW), FMOD_InfoDlgProc);
|
|
ShowWindow(cdinfo_hwnd, SW_HIDE);
|
|
|
|
modinfo_hwnd = CreateDialog(hinst, MAKEINTRESOURCE(IDD_MODINFODLG), GetDlgItem(mainhwnd, IDC_INFOWINDOW), FMOD_InfoDlgProc);
|
|
ShowWindow(modinfo_hwnd, SW_HIDE);
|
|
|
|
url_to_load[0] = 0;
|
|
|
|
if (strlen(lpCmdLine))
|
|
{
|
|
int songid = (int)SendMessage(songlist_hwnd, LB_GETCURSEL, 0, 0);
|
|
UpdateStreamInfo(songid, TRUE);
|
|
UpdateNetStreamInfo(songid, TRUE, FALSE);
|
|
UpdateModInfo(songid, TRUE);
|
|
UpdateCDInfo(songid, TRUE);
|
|
SelectInfoWindow();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
void CloseDown()
|
|
{
|
|
int count, i;
|
|
RECT r;
|
|
int desktop_height, desktop_width;
|
|
|
|
GetWindowRect(mainhwnd, &r);
|
|
setting_xpos = r.left;
|
|
setting_ypos = r.top;
|
|
|
|
GetWindowRect(GetDesktopWindow(), &r);
|
|
desktop_width = r.right - r.left;
|
|
desktop_height = r.bottom - r.top;
|
|
if (setting_xpos > desktop_width || setting_xpos < 0)
|
|
{
|
|
setting_xpos = (desktop_width / 2)-320;
|
|
}
|
|
if (setting_ypos > desktop_height || setting_ypos < 0)
|
|
{
|
|
setting_ypos = (desktop_height / 2)-140;
|
|
}
|
|
|
|
SaveSettings();
|
|
|
|
for (i=0;i < MRU_MAX;i++)
|
|
{
|
|
if (mru[i])
|
|
{
|
|
free(mru[i]);
|
|
mru[i] = 0;
|
|
}
|
|
}
|
|
|
|
for (count=0; count<MAXSONGS; count++)
|
|
{
|
|
if (song[count].stream)
|
|
{
|
|
FSOUND_Stream_Close(song[count].stream);
|
|
song[count].stream = NULL;
|
|
}
|
|
|
|
if (song[count].mod)
|
|
{
|
|
FMUSIC_FreeSong(song[count].mod);
|
|
song[count].mod = NULL;
|
|
}
|
|
|
|
if (song[count].url)
|
|
{
|
|
free(song[count].url);
|
|
song[count].url = NULL;
|
|
}
|
|
|
|
if (song[count].listname)
|
|
{
|
|
free(song[count].listname);
|
|
song[count].listname = NULL;
|
|
}
|
|
|
|
if (song[count].server_status)
|
|
{
|
|
free(song[count].server_status);
|
|
song[count].server_status = NULL;
|
|
}
|
|
|
|
if (song[count].title)
|
|
{
|
|
free(song[count].title);
|
|
song[count].title = 0;
|
|
}
|
|
|
|
if (song[count].artist)
|
|
{
|
|
free(song[count].artist);
|
|
song[count].artist = 0;
|
|
}
|
|
}
|
|
|
|
if (cdda_stream)
|
|
{
|
|
FSOUND_Stream_Close(cdda_stream);
|
|
cdda_stream = 0;
|
|
}
|
|
|
|
FSOUND_Close();
|
|
}
|
|
|
|
|
|
/*
|
|
[NAME]
|
|
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
*/
|
|
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
|
{
|
|
MSG msg;
|
|
char name[1024];
|
|
HWND hwnd;
|
|
COPYDATASTRUCT data;
|
|
|
|
g_hinst = hInstance;
|
|
|
|
sprintf(name, "FMOD %.2f", FMOD_VERSION);
|
|
hwnd = FindWindow(0, name);
|
|
if (hwnd)
|
|
{
|
|
if (IsIconic(hwnd))
|
|
{
|
|
ShowWindow(hwnd, SW_RESTORE);
|
|
}
|
|
else
|
|
{
|
|
SetActiveWindow(hwnd);
|
|
}
|
|
|
|
if (strlen(lpCmdLine))
|
|
{
|
|
data.dwData = 0;
|
|
data.cbData = (int)strlen(lpCmdLine) + 1;
|
|
data.lpData = lpCmdLine;
|
|
SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&data);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
if (FSOUND_GetVersion() < FMOD_VERSION)
|
|
{
|
|
MessageBox(GetForegroundWindow(), "INCORRECT DLL VERSION!!", "FMOD ERROR", MB_OK);
|
|
}
|
|
|
|
/*
|
|
Initialize
|
|
*/
|
|
if (!SetupInterface(hInstance, lpCmdLine)) return FALSE;
|
|
|
|
while (GetMessage( &msg, 0, 0, 0 ))
|
|
{
|
|
TranslateMessage( &msg );
|
|
DispatchMessage( &msg );
|
|
}
|
|
|
|
return (int)msg.wParam;
|
|
}
|