mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-12-23 19:20:56 +00:00
465 lines
9.7 KiB
C
465 lines
9.7 KiB
C
|
// SRB2MP.cpp : Defines the entry point for the application.
|
||
|
//
|
||
|
|
||
|
#include "StdAfx.h"
|
||
|
#include "lump.h"
|
||
|
|
||
|
#define APPTITLE "SRB2 Music Player"
|
||
|
#define APPVERSION "v0.1"
|
||
|
#define APPAUTHOR "SSNTails"
|
||
|
#define APPCOMPANY "Sonic Team Junior"
|
||
|
|
||
|
static FSOUND_STREAM *fmus = NULL;
|
||
|
static int fsoundchannel = -1;
|
||
|
static FMUSIC_MODULE *mod = NULL;
|
||
|
static struct wadfile* wfptr = NULL;
|
||
|
|
||
|
static inline VOID M_SetVolume(int volume)
|
||
|
{
|
||
|
if (mod && FMUSIC_GetType(mod) != FMUSIC_TYPE_NONE)
|
||
|
FMUSIC_SetMasterVolume(mod, volume);
|
||
|
if (fsoundchannel != -1)
|
||
|
FSOUND_SetVolume(fsoundchannel, volume);
|
||
|
}
|
||
|
|
||
|
static inline BOOL M_InitMusic(VOID)
|
||
|
{
|
||
|
if (FSOUND_GetVersion() < FMOD_VERSION)
|
||
|
{
|
||
|
printf("Error : You are using the wrong DLL version!\nYou should be using FMOD %.02f\n", FMOD_VERSION);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
FSOUND_SetOutput(FSOUND_OUTPUT_WINMM);
|
||
|
#endif
|
||
|
|
||
|
if (!FSOUND_Init(44100, 1, FSOUND_INIT_GLOBALFOCUS))
|
||
|
{
|
||
|
printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static inline VOID M_FreeMusic(VOID)
|
||
|
{
|
||
|
if (mod)
|
||
|
{
|
||
|
FMUSIC_StopSong(mod);
|
||
|
FMUSIC_FreeSong(mod);
|
||
|
mod = NULL;
|
||
|
}
|
||
|
if (fmus)
|
||
|
{
|
||
|
FSOUND_Stream_Stop(fmus);
|
||
|
FSOUND_Stream_Close(fmus);
|
||
|
fmus = NULL;
|
||
|
fsoundchannel = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static inline VOID M_ShutdownMusic(VOID)
|
||
|
{
|
||
|
M_FreeMusic();
|
||
|
FSOUND_Close();
|
||
|
//remove(musicfile); // Delete the temp file
|
||
|
}
|
||
|
|
||
|
static inline VOID M_PauseMusic(VOID)
|
||
|
{
|
||
|
if (mod && !FMUSIC_GetPaused(mod))
|
||
|
FMUSIC_SetPaused(mod, TRUE);
|
||
|
if (fsoundchannel != -1 && FSOUND_IsPlaying(fsoundchannel))
|
||
|
FSOUND_SetPaused(fsoundchannel, TRUE);
|
||
|
}
|
||
|
|
||
|
static inline VOID M_ResumeMusic(VOID)
|
||
|
{
|
||
|
if (mod && FMUSIC_GetPaused(mod))
|
||
|
FMUSIC_SetPaused(mod, FALSE);
|
||
|
if (fsoundchannel != -1 && FSOUND_GetPaused(fsoundchannel))
|
||
|
FSOUND_SetPaused(fsoundchannel, FALSE);
|
||
|
}
|
||
|
|
||
|
static inline VOID M_StopMusic(VOID)
|
||
|
{
|
||
|
if (mod)
|
||
|
FMUSIC_StopSong(mod);
|
||
|
if (fsoundchannel != -1 && fmus && FSOUND_IsPlaying(fsoundchannel))
|
||
|
FSOUND_Stream_Stop(fmus);
|
||
|
}
|
||
|
|
||
|
static inline VOID M_StartFMODSong(LPVOID data, int len, int looping, HWND hDlg)
|
||
|
{
|
||
|
const int loops = FSOUND_LOOP_NORMAL|FSOUND_LOADMEMORY;
|
||
|
const int nloop = FSOUND_LOADMEMORY;
|
||
|
M_FreeMusic();
|
||
|
|
||
|
if (looping)
|
||
|
mod = FMUSIC_LoadSongEx(data, 0, len, loops, NULL, 0);
|
||
|
else
|
||
|
mod = FMUSIC_LoadSongEx(data, 0, len, nloop, NULL, 0);
|
||
|
|
||
|
if (mod)
|
||
|
{
|
||
|
FMUSIC_SetLooping(mod, (signed char)looping);
|
||
|
FMUSIC_SetPanSeperation(mod, 0.0f);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (looping)
|
||
|
fmus = FSOUND_Stream_Open(data, loops, 0, len);
|
||
|
else
|
||
|
fmus = FSOUND_Stream_Open(data, nloop, 0, len);
|
||
|
}
|
||
|
|
||
|
if (!fmus && !mod)
|
||
|
{
|
||
|
MessageBoxA(hDlg, FMOD_ErrorString(FSOUND_GetError()), "Error", MB_OK|MB_APPLMODAL);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Scan the OGG for the COMMENT= field for a custom loop point
|
||
|
if (looping && fmus)
|
||
|
{
|
||
|
const BYTE *origpos, *dataum = data;
|
||
|
size_t scan, size = len;
|
||
|
|
||
|
CHAR buffer[512];
|
||
|
BOOL titlefound = FALSE, artistfound = FALSE;
|
||
|
|
||
|
unsigned int loopstart = 0;
|
||
|
|
||
|
origpos = dataum;
|
||
|
|
||
|
for(scan = 0; scan < size; scan++)
|
||
|
{
|
||
|
if (!titlefound)
|
||
|
{
|
||
|
if (*dataum++ == 'T')
|
||
|
if (*dataum++ == 'I')
|
||
|
if (*dataum++ == 'T')
|
||
|
if (*dataum++ == 'L')
|
||
|
if (*dataum++ == 'E')
|
||
|
if (*dataum++ == '=')
|
||
|
{
|
||
|
size_t titlecount = 0;
|
||
|
CHAR title[256];
|
||
|
BYTE length = *(dataum-10) - 6;
|
||
|
|
||
|
while(titlecount < length)
|
||
|
title[titlecount++] = *dataum++;
|
||
|
|
||
|
title[titlecount] = '\0';
|
||
|
|
||
|
sprintf(buffer, "Title: %s", title);
|
||
|
|
||
|
SendMessage(GetDlgItem(hDlg, IDC_TITLE), WM_SETTEXT, 0, (LPARAM)(LPCSTR)buffer);
|
||
|
|
||
|
titlefound = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dataum = origpos;
|
||
|
|
||
|
for(scan = 0; scan < size; scan++)
|
||
|
{
|
||
|
if (!artistfound)
|
||
|
{
|
||
|
if (*dataum++ == 'A')
|
||
|
if (*dataum++ == 'R')
|
||
|
if (*dataum++ == 'T')
|
||
|
if (*dataum++ == 'I')
|
||
|
if (*dataum++ == 'S')
|
||
|
if (*dataum++ == 'T')
|
||
|
if (*dataum++ == '=')
|
||
|
{
|
||
|
size_t artistcount = 0;
|
||
|
CHAR artist[256];
|
||
|
BYTE length = *(dataum-11) - 7;
|
||
|
|
||
|
while(artistcount < length)
|
||
|
artist[artistcount++] = *dataum++;
|
||
|
|
||
|
artist[artistcount] = '\0';
|
||
|
|
||
|
sprintf(buffer, "By: %s", artist);
|
||
|
|
||
|
SendMessage(GetDlgItem(hDlg, IDC_ARTIST), WM_SETTEXT, 0, (LPARAM)(LPCSTR)buffer);
|
||
|
|
||
|
artistfound = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dataum = origpos;
|
||
|
|
||
|
for(scan = 0; scan < size; scan++)
|
||
|
{
|
||
|
if (*dataum++ == 'C'){
|
||
|
if (*dataum++ == 'O'){
|
||
|
if (*dataum++ == 'M'){
|
||
|
if (*dataum++ == 'M'){
|
||
|
if (*dataum++ == 'E'){
|
||
|
if (*dataum++ == 'N'){
|
||
|
if (*dataum++ == 'T'){
|
||
|
if (*dataum++ == '='){
|
||
|
if (*dataum++ == 'L'){
|
||
|
if (*dataum++ == 'O'){
|
||
|
if (*dataum++ == 'O'){
|
||
|
if (*dataum++ == 'P'){
|
||
|
if (*dataum++ == 'P'){
|
||
|
if (*dataum++ == 'O'){
|
||
|
if (*dataum++ == 'I'){
|
||
|
if (*dataum++ == 'N'){
|
||
|
if (*dataum++ == 'T'){
|
||
|
if (*dataum++ == '=')
|
||
|
{
|
||
|
size_t newcount = 0;
|
||
|
CHAR looplength[64];
|
||
|
while (*dataum != 1 && newcount < 63)
|
||
|
{
|
||
|
looplength[newcount++] = *dataum++;
|
||
|
}
|
||
|
|
||
|
looplength[newcount] = '\n';
|
||
|
|
||
|
loopstart = atoi(looplength);
|
||
|
}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
else
|
||
|
dataum--;}
|
||
|
}
|
||
|
|
||
|
if (loopstart > 0)
|
||
|
{
|
||
|
const int length = FSOUND_Stream_GetLengthMs(fmus);
|
||
|
const int freq = 44100;
|
||
|
const unsigned int loopend = (unsigned int)((freq/1000.0f)*length-(freq/1000.0f));
|
||
|
if (!FSOUND_Stream_SetLoopPoints(fmus, loopstart, loopend))
|
||
|
{
|
||
|
printf("FMOD(Start,FSOUND_Stream_SetLoopPoints): %s\n",
|
||
|
FMOD_ErrorString(FSOUND_GetError()));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (mod)
|
||
|
FMUSIC_PlaySong(mod);
|
||
|
if (fmus)
|
||
|
fsoundchannel = FSOUND_Stream_PlayEx(FSOUND_FREE, fmus, NULL, FALSE);
|
||
|
|
||
|
M_SetVolume(128);
|
||
|
}
|
||
|
|
||
|
static inline VOID FreeWADLumps(VOID)
|
||
|
{
|
||
|
M_FreeMusic();
|
||
|
if (wfptr) free_wadfile(wfptr);
|
||
|
wfptr = NULL;
|
||
|
}
|
||
|
|
||
|
static inline VOID ReadWADLumps(LPCSTR WADfilename, HWND hDlg)
|
||
|
{
|
||
|
HWND listbox = GetDlgItem(hDlg, IDC_PLAYLIST);
|
||
|
FILE* f;
|
||
|
struct lumplist *curlump;
|
||
|
|
||
|
SendMessage(listbox, LB_RESETCONTENT, 0, 0);
|
||
|
FreeWADLumps();
|
||
|
f = fopen(WADfilename, "rb");
|
||
|
wfptr = read_wadfile(f);
|
||
|
fclose(f);
|
||
|
|
||
|
/* start of C_LIST */
|
||
|
/* Loop through the lump list, printing lump info */
|
||
|
for(curlump = wfptr->head->next; curlump; curlump = curlump->next)
|
||
|
{
|
||
|
LPCSTR lumpname = get_lump_name(curlump->cl);
|
||
|
if (!strncmp(lumpname, "O_", 2) || !strncmp(lumpname, "D_", 2))
|
||
|
SendMessage(listbox, LB_ADDSTRING, 0, (LPARAM)(LPCSTR)get_lump_name(curlump->cl));
|
||
|
}
|
||
|
/* end of C_LIST */
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// OpenWadfile
|
||
|
//
|
||
|
// Provides a common dialog box
|
||
|
// for selecting the desired wad file.
|
||
|
//
|
||
|
static inline VOID OpenWadfile(HWND hDlg)
|
||
|
{
|
||
|
OPENFILENAMEA ofn;
|
||
|
CHAR FileBuffer[256] = "";
|
||
|
|
||
|
ZeroMemory(&ofn, sizeof(ofn));
|
||
|
ofn.hwndOwner = hDlg;
|
||
|
ofn.lpstrFilter = "WAD Files\0*.wad\0All Files\0*.*\0\0";
|
||
|
ofn.lpstrInitialDir = NULL;
|
||
|
ofn.lpstrFile = FileBuffer;
|
||
|
ofn.lStructSize = sizeof(ofn);
|
||
|
ofn.nMaxFile = sizeof(FileBuffer);
|
||
|
ofn.nFilterIndex = 1;
|
||
|
ofn.lpstrFileTitle = NULL;
|
||
|
ofn.nMaxFileTitle = 0;
|
||
|
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||
|
|
||
|
if (GetOpenFileNameA(&ofn))
|
||
|
ReadWADLumps(FileBuffer, hDlg);
|
||
|
}
|
||
|
|
||
|
static inline VOID PlayLump(HWND hDlg)
|
||
|
{
|
||
|
HWND listbox = GetDlgItem(hDlg, IDC_PLAYLIST);
|
||
|
LRESULT cursel = SendMessage(listbox, LB_GETCURSEL, 0, 0);
|
||
|
|
||
|
/* Start of C_EXTRACT */
|
||
|
CHAR argv[9];
|
||
|
|
||
|
SendMessage(listbox, LB_GETTEXT, cursel, (LPARAM)(LPCSTR)argv);
|
||
|
|
||
|
/* Extract LUMPNAME FILENAME pairs */
|
||
|
if (wfptr)
|
||
|
{
|
||
|
struct lumplist *extracted;
|
||
|
|
||
|
printf("Extracting lump %s...\n", argv);
|
||
|
/* Find the lump to extract */
|
||
|
extracted = find_previous_lump(wfptr->head, NULL, argv);
|
||
|
if (extracted == NULL || (extracted = extracted->next) == NULL)
|
||
|
return;
|
||
|
|
||
|
/* Extract lump */
|
||
|
M_StartFMODSong(extracted->cl->data, extracted->cl->len, FALSE, hDlg);
|
||
|
|
||
|
/* end of extracting LUMPNAME FILENAME pairs */
|
||
|
|
||
|
} /* end of C_EXTRACT */
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
switch(message)
|
||
|
{
|
||
|
case WM_INITDIALOG:
|
||
|
M_InitMusic();
|
||
|
break;
|
||
|
|
||
|
case WM_CLOSE:
|
||
|
EndDialog(hDlg, message);
|
||
|
break;
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
FreeWADLumps();
|
||
|
M_ShutdownMusic();
|
||
|
break;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
{
|
||
|
switch(LOWORD(wParam))
|
||
|
{
|
||
|
case 2:
|
||
|
EndDialog(hDlg, message);
|
||
|
return TRUE;
|
||
|
case IDC_ABOUT: // The About button.
|
||
|
{
|
||
|
char TempString[256];
|
||
|
sprintf(TempString, "%s %s by %s - %s", APPTITLE, APPVERSION, APPAUTHOR, APPCOMPANY);
|
||
|
MessageBoxA(hDlg, TempString, "About", MB_OK|MB_APPLMODAL);
|
||
|
}
|
||
|
return TRUE;
|
||
|
case IDC_OPEN:
|
||
|
OpenWadfile(hDlg);
|
||
|
return TRUE;
|
||
|
case IDC_PLAY:
|
||
|
PlayLump(hDlg);
|
||
|
return TRUE;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static inline VOID RegisterDialogClass(LPCSTR name, WNDPROC callback, HINSTANCE hInst)
|
||
|
{
|
||
|
WNDCLASSA wnd;
|
||
|
|
||
|
wnd.style = CS_HREDRAW | CS_VREDRAW;
|
||
|
wnd.cbWndExtra = DLGWINDOWEXTRA;
|
||
|
wnd.cbClsExtra = 0;
|
||
|
wnd.hCursor = LoadCursorA(NULL,(LPCSTR)MAKEINTRESOURCE(IDC_ARROW));
|
||
|
wnd.hIcon = LoadIcon(NULL,MAKEINTRESOURCE(IDI_ICON1));
|
||
|
wnd.hInstance = hInst;
|
||
|
wnd.lpfnWndProc = callback;
|
||
|
wnd.lpszClassName = name;
|
||
|
wnd.lpszMenuName = NULL;
|
||
|
wnd.hbrBackground = (HBRUSH)(COLOR_WINDOW);
|
||
|
|
||
|
if (!RegisterClassA(&wnd))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int APIENTRY WinMain(HINSTANCE hInstance,
|
||
|
HINSTANCE hPrevInstance,
|
||
|
LPSTR lpCmdLine,
|
||
|
int nCmdShow)
|
||
|
{
|
||
|
// Prevent multiples instances of this app.
|
||
|
CreateMutexA(NULL, TRUE, APPTITLE);
|
||
|
|
||
|
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||
|
return 0;
|
||
|
|
||
|
RegisterDialogClass("SRB2MP", MainWndproc, hInstance);
|
||
|
|
||
|
DialogBoxA(hInstance, (LPCSTR)IDD_MAIN, NULL, DialogProc);
|
||
|
|
||
|
return 0;
|
||
|
}
|