diff --git a/configure.ac b/configure.ac index eb8940f0e..1ad918a2d 100644 --- a/configure.ac +++ b/configure.ac @@ -1107,7 +1107,7 @@ dnl Checks for CD-ROM dnl ================================================================== CD_CFLAGS="" -CD_PLUGIN_TARGETS="" +CD_PLUGIN_TARGETS="cd_file.la" unset CDTYPE AC_MSG_CHECKING(for CD audio support) diff --git a/doc/tracklist.cfg b/doc/tracklist.cfg new file mode 100644 index 000000000..9f143f0c1 --- /dev/null +++ b/doc/tracklist.cfg @@ -0,0 +1,14 @@ +// sample track list +{ + 2 = "music/02.ogg"; + 3 = "music/03.ogg"; + 4 = "music/04.ogg"; + 5 = "music/05.ogg"; + 6 = "music/06.ogg"; + 7 = "music/07.ogg"; + 8 = "music/08.ogg"; + 9 = "music/09.ogg"; + 10 = "music/10.ogg"; + 11 = "music/11.ogg"; +} + diff --git a/libs/audio/cd/Makefile.am b/libs/audio/cd/Makefile.am index fccad2b04..3f76932b7 100644 --- a/libs/audio/cd/Makefile.am +++ b/libs/audio/cd/Makefile.am @@ -11,16 +11,14 @@ EXEEXT= plugin_PROGRAMS= @CD_PLUGIN_TARGETS@ noinst_PROGRAMS= @CD_PLUGIN_STATIC@ -EXTRA_PROGRAMS= cd_linux.la cd_sdl.la cd_sgi.la cd_win.la cd_xmms.la +EXTRA_PROGRAMS= cd_file.la cd_linux.la cd_sdl.la cd_sgi.la cd_win.la cd_xmms.la + +cd_file_la_LDFLAGS= $(plugin_ldflags) +cd_file_la_SOURCES= cd_file.c cd_linux_la_LDFLAGS= $(plugin_ldflags) cd_linux_la_SOURCES= cd_linux.c -cd_xmms_la_LDFLAGS= $(plugin_ldflags) -cd_xmms_la_LDADD= $(XMMS_LIBS) -cd_xmms_la_CFLAGS= $(XMMS_CFLAGS) -cd_xmms_la_SOURCES= cd_xmms.c - cd_sdl_la_LDFLAGS= $(plugin_ldflags) cd_sdl_la_LDADD= $(SDL_LIBS) $(plugin_libadd) cd_sdl_la_CFLAGS= $(SDL_CFLAGS) @@ -33,3 +31,8 @@ cd_sgi_la_SOURCES= cd_sgi.c cd_win_la_LDFLAGS= $(plugin_ldflags) cd_win_la_LDADD= $(plugin_libadd) cd_win_la_SOURCES= cd_win.c + +cd_xmms_la_LDFLAGS= $(plugin_ldflags) +cd_xmms_la_LDADD= $(XMMS_LIBS) +cd_xmms_la_CFLAGS= $(XMMS_CFLAGS) +cd_xmms_la_SOURCES= cd_xmms.c diff --git a/libs/audio/cd/cd_file.c b/libs/audio/cd/cd_file.c new file mode 100644 index 000000000..70dc85eea --- /dev/null +++ b/libs/audio/cd/cd_file.c @@ -0,0 +1,473 @@ +/* + cd_ogg.c + + ogg music support + + Copyright (C) 1996-1997 Id Software, Inc. + Modified Andrew Pilley, 2004 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static __attribute__ ((unused)) const char rcsid[] = + "$Id$"; + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif + +#include +#include +#include +#include + +#include "QF/cdaudio.h" +#include "QF/cmd.h" +#include "QF/cvar.h" +#include "QF/plugin.h" +#include "QF/qargs.h" +#include "QF/sound.h" +#include "QF/sys.h" +#include "QF/quakefs.h" +#include "QF/quakeio.h" +#include "QF/dstring.h" +#include "QF/qfplist.h" +#include "QF/sound.h" +#include "snd_render.h" + +#include "compat.h" + +static plugin_t plugin_info; +static plugin_data_t plugin_info_data; +static plugin_funcs_t plugin_info_funcs; +static general_data_t plugin_info_general_data; +static general_funcs_t plugin_info_general_funcs; + +//static cd_data_t plugin_info_cd_data; +static cd_funcs_t plugin_info_cd_funcs; + + /* static qboolean cdValid = false; *//* removed, not using a cd. */ +static qboolean playing = false; +static qboolean wasPlaying = false; +static qboolean mus_enabled = false; + +static cvar_t *bgmvolume; + + +/* added by Andrew, for cd_ogg */ +static cvar_t *mus_ogglist; /* contain the filename of the ogglist. + */ +static QFile *oggfile = NULL; /* filedescriptor with track map */ +static qboolean ogglistvalid = false; /* true if a valid ogg list has been + loaded */ +static plitem_t *tracklist = NULL; /* the parsed tracklist */ + +/* end of added variables. */ + +/* does nothing */ +static void +I_OGGMus_CloseDoor (void) +{ + Sys_Printf ("Entering I_OGGMus_CloseDoor\n"); + return; +} + +/* does nothing. */ +static void +I_OGGMus_Eject (void) +{ + Sys_Printf ("Entering I_OGGMus_Eject\n"); + return; +} + +/* we've opened the trackmap file from the quake resources + * go through it, and make ourselves a tracklist map */ +static int +I_OGGMus_GetAudioDiskInfo (void) +{ + Sys_Printf ("Entering I_OGGMus_GetAudioDiskInfo\n"); + /* read the track list, parse it a bit, map it into a list */ + int size = -1; + char *buffile = NULL; + + ogglistvalid = false; + + if (oggfile == NULL) { + return -1; + } + + /* rewind the stream */ + Qseek (oggfile, 0, SEEK_SET); + size = Qfilesize (oggfile); + buffile = calloc (size + 10, sizeof (char)); + Qread (oggfile, buffile, size); + tracklist = PL_GetPropertyList (buffile); + if (!tracklist || tracklist->type != QFDictionary) { + Sys_Printf ("Malformed or empty tracklist file. check mus_ogglist\n"); + return -1; + } + free (buffile); + + ogglistvalid = true; + + return 0; +} + +/* pause playback of music? */ +static void +I_OGGMus_Pause (void) +{ + Sys_Printf ("Entering I_OGGMus_Pause\n"); + /* pause the ogg playback. */ + /* just kinda cheat and stop it for the time being */ + if (tracklist == NULL || !mus_enabled) + return; + + if (!playing) + return; + + wasPlaying = playing; + playing = false; +} + +/* stop playback of music. */ +static void +I_OGGMus_Stop (void) +{ + Sys_Printf ("Entering I_OGGMus_Stop\n"); + /* okay, stop playing oggs. */ + if (tracklist == NULL || !mus_enabled) + return; + + if (!playing) + return; + + wasPlaying = false; + playing = false; +} + +/* start playing, if we've got a trackmap. + * cry if we can't find a file to play */ +static void +I_OGGMus_Play (int track, qboolean looping) +{ + plitem_t *trackmap = NULL; + dstring_t *trackstring = dstring_new (); + + Sys_Printf ("Entering I_OGGMus_Play\n"); + /* alrighty. grab the list, map track to filename. grab filename from data + resources, attach sound to play, loop. */ + if (tracklist == NULL || !mus_enabled) { + free (trackstring); + return; + } + + dsprintf (trackstring, "%i", track); + trackmap = PL_ObjectForKey (tracklist, trackstring->str); + if (trackmap == NULL || trackmap->type != QFString) { + Sys_Printf ("No Track for track number %s.\n", trackstring->str); + free (trackstring); + return; + } + + Sys_Printf ("Playing: %s.\n", (char *) trackmap->data); + S_LocalSound ((char *) trackmap->data); + free (trackstring); + playing = true; +} + +/* unpause. might just cheat and restart playing */ +static void +I_OGGMus_Resume (void) +{ + Sys_Printf ("Entering I_OGGMus_Resume\n"); + + if (tracklist == NULL || !mus_enabled) + return; + + if (!wasPlaying) + return; + playing = true; +} + +static void +I_OGGMus_Shutdown (void) +{ + Sys_Printf ("Entering I_OGGMus_Shutdown\n"); + /* clean up a bit, destroy the ogg if i have to */ + + if (tracklist != NULL) { + I_OGGMus_Stop (); + PL_Free (tracklist); + tracklist = NULL; + } + if (oggfile != NULL) { + Qclose (oggfile); + oggfile = NULL; + } + mus_enabled = false; +} + +/* print out the current track map. */ +static void +I_OGGMus_Info (void) +{ + plitem_t *keylist = NULL; + plitem_t *currentmap = NULL; + plitem_t *currenttrack = NULL; + int iter = 0; + + Sys_Printf ("Entering I_OGGMus_Info\n"); + if (tracklist != NULL) { + + keylist = PL_D_AllKeys (tracklist); + if (keylist == NULL) { + Sys_DPrintf + ("OGGMus: Didn't get valid plist_t array yet have valid tracklist?\n"); + return; + } + Sys_DPrintf ("OGGMus: number of entries %i.\n", + ((plarray_t *) (keylist->data))->numvals); + Sys_Printf ("\n" "Tracklist loaded from file:\n%s\n" + "---------------------------\n", mus_ogglist->string); + + /* loop through the list with PL_ObjectAtIndex() */ + + for (iter = 0; iter < ((plarray_t *) (keylist->data))->numvals; iter++) { + currentmap = PL_ObjectAtIndex (keylist, iter); + if (currentmap == NULL) { + Sys_DPrintf ("OGGMus: No track for track number %i.\n", iter); + continue; + } + if (currentmap->type != QFString) { + Sys_DPrintf ("OGGMus: Track fetched isn't a QFString for: %i\n", + iter); + continue; + } + currenttrack = + PL_ObjectForKey (tracklist, (char *) currentmap->data); + Sys_Printf (" %s - %s\n", (char *) currentmap->data, + (char *) currenttrack->data); + + } + + PL_Free (keylist); + } else { + Sys_Printf ("\n" "No Tracklist\n" "------------\n"); + } + + +} + + + +static void +I_OGG_f (void) +{ + Sys_Printf ("Entering I_OGG_f\n"); + const char *command; + + if (Cmd_Argc () < 2) + return; + + command = Cmd_Argv (1); + + if (strequal (command, "on")) { + mus_enabled = true; + return; + } + + if (strequal (command, "off")) { + if (playing) + I_OGGMus_Stop (); + mus_enabled = false; + return; + } + + if (strequal (command, "reset")) { + mus_enabled = true; + if (playing) + I_OGGMus_Stop (); + I_OGGMus_GetAudioDiskInfo (); + return; + } + + if (strequal (command, "remap")) { + Sys_Printf ("OGGMus: remap does nothing.\n"); + return; + } + + if (strequal (command, "close")) { + I_OGGMus_CloseDoor (); + return; + } + + if (!tracklist) { + I_OGGMus_GetAudioDiskInfo (); + if (!tracklist) { + Sys_Printf ("Can't initialize tracklist.\n"); + return; + } + } + + if (strequal (command, "play")) { + CDAudio_Play (atoi (Cmd_Argv (2)), false); + return; + } + + if (strequal (command, "loop")) { + CDAudio_Play (atoi (Cmd_Argv (2)), true); + return; + } + + if (strequal (command, "stop")) { + I_OGGMus_Stop (); + return; + } + + if (strequal (command, "pause")) { + CDAudio_Pause (); + return; + } + + if (strequal (command, "resume")) { + CDAudio_Resume (); + return; + } + + if (strequal (command, "eject")) { + if (playing) + I_OGGMus_Stop (); + I_OGGMus_Eject (); + return; + } + + if (strequal (command, "info")) { + I_OGGMus_Info (); + return; + } +} + +/* stubb out, since we don't need */ +static void +I_OGGMus_Update (void) +{ + +} + +/* called when the mus_ogglist cvar is changed */ +static void +Mus_OggChange (cvar_t *mus_ogglist) +{ + int size; + + Sys_Printf ("Entering Mus_OggChange\n"); + + /* make sure we're not playing anything right now, and we've cleaned up */ + CDAudio_Shutdown (); + + + if (strequal (mus_ogglist->string, "none")) { + /* bail if we don't have one */ + return; + } + + + size = QFS_FOpenFile (mus_ogglist->string, &oggfile); + if (size == -1) { + Sys_Printf ("Mus_OGGInit: open of file \"%s\" failed\n", + mus_ogglist->string); + mus_enabled = false; + return; + } + + if (I_OGGMus_GetAudioDiskInfo () == -1) { + /* check the info, read it in. done */ + Sys_Printf ("Mus_OGGInit: invalid track map.\n"); + ogglistvalid = false; + mus_enabled = false; + return; + } + mus_enabled = true; +} + +/* change volume on sound object */ +static void +Mus_VolChange (cvar_t *bgmvolume) +{ + Sys_Printf ("Entering Mus_VolChange\n"); + +} + +static void +I_OGGMus_Init (void) +{ + Sys_Printf ("Entering I_OGGMus_Init\n"); + /* check list file cvar, open list file, create map, close file. */ + + mus_ogglist = Cvar_Get ("mus_ogglist", "tracklist.cfg", CVAR_NONE, + Mus_OggChange, + "filename of track to music file map"); + bgmvolume = Cvar_Get ("bgmvolume", "1", CVAR_ARCHIVE, Mus_VolChange, + "Volume of CD music"); +} + +PLUGIN_INFO (cd, file) +{ + plugin_info.type = qfp_cd; /* enum, leave */ + plugin_info.api_version = QFPLUGIN_VERSION; /* version symbol. leave */ + plugin_info.plugin_version = "0.1"; /* plugin version, increment */ + plugin_info.description = "OGG Music output\n" + "Copyright (C) 2001 contributors of the QuakeForge project\n" + "Please see the file \"AUTHORS\" for a list of contributors\n"; + plugin_info.functions = &plugin_info_funcs; + plugin_info.data = &plugin_info_data; + + plugin_info_data.general = &plugin_info_general_data; +// plugin_info_data.cd = &plugin_info_cd_data; + plugin_info_data.input = NULL; + + plugin_info_funcs.general = &plugin_info_general_funcs; + plugin_info_funcs.cd = &plugin_info_cd_funcs; + plugin_info_funcs.input = NULL; + + plugin_info_general_funcs.p_Init = I_OGGMus_Init; + plugin_info_general_funcs.p_Shutdown = I_OGGMus_Shutdown; + + plugin_info_cd_funcs.pCDAudio_Pause = I_OGGMus_Pause; + plugin_info_cd_funcs.pCDAudio_Play = I_OGGMus_Play; + plugin_info_cd_funcs.pCDAudio_Resume = I_OGGMus_Resume; + plugin_info_cd_funcs.pCDAudio_Update = I_OGGMus_Update; + plugin_info_cd_funcs.pCD_f = I_OGG_f; + + return &plugin_info; +}