removed some OS-specific drivers. they weren't used and was here only for

reference.

git-svn-id: http://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@583 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
sezero 2011-12-30 13:59:14 +00:00
parent db10cdba6c
commit 862aa71e52
9 changed files with 0 additions and 5967 deletions

View file

@ -1,512 +0,0 @@
/*
cd_bsd.c
Copyright (C) 1996-1997 Id Software, Inc.
A few BSD bits taken from the darkplaces project for Hexen II:
Hammer of Thyrion (uHexen2)
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
*/
#include "cd_unix.h"
#ifdef __USE_BSD_CDROM__
#include "quakedef.h"
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <sys/cdio.h>
#include <paths.h>
static qboolean cdValid = false;
static qboolean playing = false;
static qboolean wasPlaying = false;
static qboolean initialized = false;
static qboolean enabled = true;
static qboolean playLooping = false;
static byte remap[100];
static byte playTrack;
static byte maxTrack;
static int cdfile = -1;
/* default path to cdrom device. user can always do -cddev */
#if !defined(__FreeBSD__)
static const char default_dev[] = _PATH_DEV "cd0";
#else
static const char default_dev[] = _PATH_DEV "acd0";
#endif
static const char *cd_dev = default_dev;
static float old_cdvolume;
static qboolean hw_vol_works = true;
static struct ioc_vol orig_vol; /* original setting to be restored upon exit */
static struct ioc_vol drv_vol; /* the volume setting we'll be using */
#define IOCTL_FAILURE(__name) do { \
int __err = errno; \
Con_DPrintf("ioctl %s failed (%d: %s)\n", #__name, __err, strerror(__err)); \
} while (0)
static void CDAudio_Eject(void)
{
if (cdfile == -1 || !enabled)
return;
ioctl(cdfile, CDIOCALLOW);
if (ioctl(cdfile, CDIOCEJECT) == -1)
IOCTL_FAILURE(CDIOCEJECT);
}
static void CDAudio_CloseDoor(void)
{
if (cdfile == -1 || !enabled)
return;
ioctl(cdfile, CDIOCALLOW);
if (ioctl(cdfile, CDIOCCLOSE) == -1)
IOCTL_FAILURE(CDIOCCLOSE);
}
static int CDAudio_GetAudioDiskInfo(void)
{
struct ioc_toc_header tochdr;
if (cdfile == -1)
return -1;
cdValid = false;
if (ioctl(cdfile, CDIOREADTOCHEADER, &tochdr) == -1)
{
IOCTL_FAILURE(CDIOREADTOCHEADER);
return -1;
}
if (tochdr.starting_track < 1)
{
Con_DPrintf("CDAudio: no music tracks\n");
return -1;
}
cdValid = true;
maxTrack = tochdr.ending_track;
return 0;
}
int CDAudio_Play(byte track, qboolean looping)
{
struct ioc_read_toc_entry entry;
struct cd_toc_entry toc_buffer;
struct ioc_play_track ti;
if (cdfile == -1 || !enabled)
return -1;
if (!cdValid)
{
CDAudio_GetAudioDiskInfo();
if (!cdValid)
return -1;
}
track = remap[track];
if (track < 1 || track > maxTrack)
{
Con_DPrintf("CDAudio: Bad track number %u.\n", track);
return -1;
}
/* don't try to play a non-audio track */
# define CDROM_DATA_TRACK 4
memset((char *)&toc_buffer, 0, sizeof(toc_buffer));
entry.data_len = sizeof(toc_buffer);
entry.data = &toc_buffer;
entry.starting_track = track;
entry.address_format = CD_MSF_FORMAT;
if (ioctl(cdfile, CDIOREADTOCENTRYS, &entry) == -1)
{
IOCTL_FAILURE(CDIOREADTOCENTRYS);
return -1;
}
if (toc_buffer.control & CDROM_DATA_TRACK)
{
Con_Printf("CDAudio: track %i is not audio\n", track);
return -1;
}
if (playing)
{
if (playTrack == track)
return 0;
CDAudio_Stop();
}
ti.start_track = track;
ti.end_track = track;
ti.start_index = 1;
ti.end_index = 99;
if (ioctl(cdfile, CDIOCPLAYTRACKS, &ti) == -1)
{
IOCTL_FAILURE(CDIOCPLAYTRACKS);
return -1;
}
if (ioctl(cdfile, CDIOCRESUME) == -1)
{
IOCTL_FAILURE(CDIOCRESUME);
return -1;
}
playLooping = looping;
playTrack = track;
playing = true;
if (bgmvolume.value == 0) /* don't bother advancing */
CDAudio_Pause ();
return 0;
}
void CDAudio_Stop(void)
{
if (cdfile == -1 || !enabled)
return;
if (!playing)
return;
if (ioctl(cdfile, CDIOCSTOP) == -1)
{
IOCTL_FAILURE(CDIOCSTOP);
return;
}
ioctl(cdfile, CDIOCALLOW);
wasPlaying = false;
playing = false;
}
void CDAudio_Pause(void)
{
if (cdfile == -1 || !enabled)
return;
if (!playing)
return;
if (ioctl(cdfile, CDIOCPAUSE) == -1)
IOCTL_FAILURE(CDIOCPAUSE);
wasPlaying = playing;
playing = false;
}
void CDAudio_Resume(void)
{
if (cdfile == -1 || !enabled)
return;
if (!cdValid)
return;
if (!wasPlaying)
return;
if (ioctl(cdfile, CDIOCRESUME) == -1)
IOCTL_FAILURE(CDIOCRESUME);
playing = true;
}
static void CD_f (void)
{
const char *command;
int ret, n;
if (Cmd_Argc() < 2)
{
Con_Printf("commands:");
Con_Printf("on, off, reset, remap, \n");
Con_Printf("play, stop, loop, pause, resume\n");
Con_Printf("eject, close, info\n");
return;
}
command = Cmd_Argv (1);
if (Q_strcasecmp(command, "on") == 0)
{
enabled = true;
return;
}
if (Q_strcasecmp(command, "off") == 0)
{
if (playing)
CDAudio_Stop();
enabled = false;
return;
}
if (Q_strcasecmp(command, "reset") == 0)
{
enabled = true;
if (playing)
CDAudio_Stop();
for (n = 0; n < 100; n++)
remap[n] = n;
CDAudio_GetAudioDiskInfo();
return;
}
if (Q_strcasecmp(command, "remap") == 0)
{
ret = Cmd_Argc() - 2;
if (ret <= 0)
{
for (n = 1; n < 100; n++)
if (remap[n] != n)
Con_Printf(" %u -> %u\n", n, remap[n]);
return;
}
for (n = 1; n <= ret; n++)
remap[n] = atoi(Cmd_Argv (n+1));
return;
}
if (Q_strcasecmp(command, "close") == 0)
{
CDAudio_CloseDoor();
return;
}
if (!cdValid)
{
CDAudio_GetAudioDiskInfo();
if (!cdValid)
{
Con_Printf("No CD in player.\n");
return;
}
}
if (Q_strcasecmp(command, "play") == 0)
{
CDAudio_Play((byte)atoi(Cmd_Argv (2)), false);
return;
}
if (Q_strcasecmp(command, "loop") == 0)
{
CDAudio_Play((byte)atoi(Cmd_Argv (2)), true);
return;
}
if (Q_strcasecmp(command, "stop") == 0)
{
CDAudio_Stop();
return;
}
if (Q_strcasecmp(command, "pause") == 0)
{
CDAudio_Pause();
return;
}
if (Q_strcasecmp(command, "resume") == 0)
{
CDAudio_Resume();
return;
}
if (Q_strcasecmp(command, "eject") == 0)
{
if (playing)
CDAudio_Stop();
CDAudio_Eject();
cdValid = false;
return;
}
if (Q_strcasecmp(command, "info") == 0)
{
Con_Printf("%u tracks\n", maxTrack);
if (playing)
Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
else if (wasPlaying)
Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
Con_Printf("Volume is %f\n", bgmvolume.value);
return;
}
}
static qboolean CD_GetVolume (struct ioc_vol *vol)
{
if (ioctl(cdfile, CDIOCGETVOL, vol) == -1)
{
IOCTL_FAILURE(CDIOCGETVOL);
return false;
}
return true;
}
static qboolean CD_SetVolume (struct ioc_vol *vol)
{
if (ioctl(cdfile, CDIOCSETVOL, vol) == -1)
{
IOCTL_FAILURE(CDIOCSETVOL);
return false;
}
return true;
}
static qboolean CDAudio_SetVolume (float value)
{
if (cdfile == -1 || !enabled)
return false;
old_cdvolume = value;
if (value == 0.0f)
CDAudio_Pause ();
else
CDAudio_Resume();
if (!hw_vol_works)
{
return false;
}
else
{
drv_vol.vol[0] = drv_vol.vol[2] =
drv_vol.vol[1] = drv_vol.vol[3] = value * 255.0f;
return CD_SetVolume (&drv_vol);
}
}
void CDAudio_Update(void)
{
struct ioc_read_subchannel subchnl;
struct cd_sub_channel_info data;
static time_t lastchk;
if (cdfile == -1 || !enabled)
return;
if (old_cdvolume != bgmvolume.value)
CDAudio_SetVolume (bgmvolume.value);
if (playing && lastchk < time(NULL))
{
lastchk = time(NULL) + 2; /* two seconds between chks */
memset (&subchnl, 0, sizeof(subchnl));
subchnl.data = &data;
subchnl.data_len = sizeof(data);
subchnl.address_format = CD_MSF_FORMAT;
subchnl.data_format = CD_CURRENT_POSITION;
subchnl.track = playTrack;
if (ioctl(cdfile, CDIOCREADSUBCHANNEL, &subchnl) == -1)
{
IOCTL_FAILURE(CDIOCREADSUBCHANNEL);
playing = false;
return;
}
if (data.header.audio_status != CD_AS_PLAY_IN_PROGRESS &&
data.header.audio_status != CD_AS_PLAY_PAUSED)
{
playing = false;
if (playLooping)
CDAudio_Play(playTrack, true);
}
else
{
playTrack = data.what.position.track_number;
}
}
}
int CDAudio_Init(void)
{
int i;
if (safemode || COM_CheckParm("-nocdaudio"))
return -1;
if ((i = COM_CheckParm("-cddev")) != 0 && i < com_argc - 1)
cd_dev = com_argv[i + 1];
if ((cdfile = open(cd_dev, O_RDONLY | O_NONBLOCK)) == -1)
{
i = errno;
Con_Printf("CDAudio_Init: open of \"%s\" failed (%d: %s)\n",
cd_dev, i, strerror(i));
cdfile = -1;
return -1;
}
for (i = 0; i < 100; i++)
remap[i] = i;
initialized = true;
enabled = true;
old_cdvolume = bgmvolume.value;
Con_Printf("CDAudio initialized (using BSD ioctls)\n");
if (CDAudio_GetAudioDiskInfo())
{
Con_Printf("CDAudio_Init: No CD in drive\n");
cdValid = false;
}
Cmd_AddCommand ("cd", CD_f);
hw_vol_works = CD_GetVolume (&orig_vol);
if (hw_vol_works)
hw_vol_works = CDAudio_SetVolume (bgmvolume.value);
return 0;
}
void CDAudio_Shutdown(void)
{
if (!initialized)
return;
CDAudio_Stop();
if (hw_vol_works)
CD_SetVolume (&orig_vol);
close(cdfile);
cdfile = -1;
}
#endif /* __USE_BSD_CDROM__ */

View file

@ -1,487 +0,0 @@
/*
cd_linux.c
Copyright (C) 1996-1997 Id Software, Inc.
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
*/
#include "cd_unix.h"
#ifdef __USE_LINUX_CDROM__
#include "quakedef.h"
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <linux/cdrom.h>
#include <paths.h>
static qboolean cdValid = false;
static qboolean playing = false;
static qboolean wasPlaying = false;
static qboolean initialized = false;
static qboolean enabled = true;
static qboolean playLooping = false;
static byte remap[100];
static byte playTrack;
static byte maxTrack;
static int cdfile = -1;
static const char default_dev[] = _PATH_DEV "cdrom"; /* user can always do -cddev */
static const char *cd_dev = default_dev;
static float old_cdvolume;
static qboolean hw_vol_works = true;
static struct cdrom_volctrl orig_vol; /* original setting to be restored upon exit */
static struct cdrom_volctrl drv_vol; /* the volume setting we'll be using */
#define IOCTL_FAILURE(__name) do { \
int __err = errno; \
Con_DPrintf("ioctl %s failed (%d: %s)\n", #__name, __err, strerror(__err)); \
} while (0)
static void CDAudio_Eject(void)
{
if (cdfile == -1 || !enabled)
return;
if (ioctl(cdfile, CDROMEJECT) == -1)
IOCTL_FAILURE(CDROMEJECT);
}
static void CDAudio_CloseDoor(void)
{
if (cdfile == -1 || !enabled)
return;
if (ioctl(cdfile, CDROMCLOSETRAY) == -1)
IOCTL_FAILURE(CDROMCLOSETRAY);
}
static int CDAudio_GetAudioDiskInfo(void)
{
struct cdrom_tochdr tochdr;
if (cdfile == -1)
return -1;
cdValid = false;
if (ioctl(cdfile, CDROMREADTOCHDR, &tochdr) == -1)
{
IOCTL_FAILURE(CDROMREADTOCHDR);
return -1;
}
if (tochdr.cdth_trk0 < 1)
{
Con_DPrintf("CDAudio: no music tracks\n");
return -1;
}
cdValid = true;
maxTrack = tochdr.cdth_trk1;
return 0;
}
int CDAudio_Play(byte track, qboolean looping)
{
struct cdrom_tocentry entry;
struct cdrom_ti ti;
if (cdfile == -1 || !enabled)
return -1;
if (!cdValid)
{
CDAudio_GetAudioDiskInfo();
if (!cdValid)
return -1;
}
track = remap[track];
if (track < 1 || track > maxTrack)
{
Con_DPrintf("CDAudio: Bad track number %u.\n", track);
return -1;
}
/* don't try to play a non-audio track */
entry.cdte_track = track;
entry.cdte_format = CDROM_MSF;
if (ioctl(cdfile, CDROMREADTOCENTRY, &entry) == -1)
{
IOCTL_FAILURE(CDROMREADTOCENTRY);
return -1;
}
if (entry.cdte_ctrl == CDROM_DATA_TRACK)
{
Con_Printf("CDAudio: track %i is not audio\n", track);
return -1;
}
if (playing)
{
if (playTrack == track)
return 0;
CDAudio_Stop();
}
ti.cdti_trk0 = track;
ti.cdti_trk1 = track;
ti.cdti_ind0 = 1;
ti.cdti_ind1 = 99;
if (ioctl(cdfile, CDROMPLAYTRKIND, &ti) == -1)
{
IOCTL_FAILURE(CDROMPLAYTRKIND);
return -1;
}
if (ioctl(cdfile, CDROMRESUME) == -1)
{
IOCTL_FAILURE(CDROMRESUME);
return -1;
}
playLooping = looping;
playTrack = track;
playing = true;
if (bgmvolume.value == 0) /* don't bother advancing */
CDAudio_Pause ();
return 0;
}
void CDAudio_Stop(void)
{
if (cdfile == -1 || !enabled)
return;
if (!playing)
return;
if (ioctl(cdfile, CDROMSTOP) == -1)
IOCTL_FAILURE(CDROMSTOP);
wasPlaying = false;
playing = false;
}
void CDAudio_Pause(void)
{
if (cdfile == -1 || !enabled)
return;
if (!playing)
return;
if (ioctl(cdfile, CDROMPAUSE) == -1)
IOCTL_FAILURE(CDROMPAUSE);
wasPlaying = playing;
playing = false;
}
void CDAudio_Resume(void)
{
if (cdfile == -1 || !enabled)
return;
if (!cdValid)
return;
if (!wasPlaying)
return;
if (ioctl(cdfile, CDROMRESUME) == -1)
IOCTL_FAILURE(CDROMRESUME);
playing = true;
}
static void CD_f (void)
{
const char *command;
int ret, n;
if (Cmd_Argc() < 2)
{
Con_Printf("commands:");
Con_Printf("on, off, reset, remap, \n");
Con_Printf("play, stop, loop, pause, resume\n");
Con_Printf("eject, close, info\n");
return;
}
command = Cmd_Argv (1);
if (Q_strcasecmp(command, "on") == 0)
{
enabled = true;
return;
}
if (Q_strcasecmp(command, "off") == 0)
{
if (playing)
CDAudio_Stop();
enabled = false;
return;
}
if (Q_strcasecmp(command, "reset") == 0)
{
enabled = true;
if (playing)
CDAudio_Stop();
for (n = 0; n < 100; n++)
remap[n] = n;
CDAudio_GetAudioDiskInfo();
return;
}
if (Q_strcasecmp(command, "remap") == 0)
{
ret = Cmd_Argc() - 2;
if (ret <= 0)
{
for (n = 1; n < 100; n++)
if (remap[n] != n)
Con_Printf(" %u -> %u\n", n, remap[n]);
return;
}
for (n = 1; n <= ret; n++)
remap[n] = atoi(Cmd_Argv (n+1));
return;
}
if (Q_strcasecmp(command, "close") == 0)
{
CDAudio_CloseDoor();
return;
}
if (!cdValid)
{
CDAudio_GetAudioDiskInfo();
if (!cdValid)
{
Con_Printf("No CD in player.\n");
return;
}
}
if (Q_strcasecmp(command, "play") == 0)
{
CDAudio_Play((byte)atoi(Cmd_Argv (2)), false);
return;
}
if (Q_strcasecmp(command, "loop") == 0)
{
CDAudio_Play((byte)atoi(Cmd_Argv (2)), true);
return;
}
if (Q_strcasecmp(command, "stop") == 0)
{
CDAudio_Stop();
return;
}
if (Q_strcasecmp(command, "pause") == 0)
{
CDAudio_Pause();
return;
}
if (Q_strcasecmp(command, "resume") == 0)
{
CDAudio_Resume();
return;
}
if (Q_strcasecmp(command, "eject") == 0)
{
if (playing)
CDAudio_Stop();
CDAudio_Eject();
cdValid = false;
return;
}
if (Q_strcasecmp(command, "info") == 0)
{
Con_Printf("%u tracks\n", maxTrack);
if (playing)
Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
else if (wasPlaying)
Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
Con_Printf("Volume is %f\n", bgmvolume.value);
return;
}
}
static qboolean CD_GetVolume (struct cdrom_volctrl *vol)
{
if (ioctl(cdfile, CDROMVOLREAD, vol) == -1)
{
IOCTL_FAILURE(CDROMVOLREAD);
return false;
}
return true;
}
static qboolean CD_SetVolume (struct cdrom_volctrl *vol)
{
if (ioctl(cdfile, CDROMVOLCTRL, vol) == -1)
{
IOCTL_FAILURE(CDROMVOLCTRL);
return false;
}
return true;
}
static qboolean CDAudio_SetVolume (float value)
{
if (cdfile == -1 || !enabled)
return false;
old_cdvolume = value;
if (value == 0.0f)
CDAudio_Pause ();
else
CDAudio_Resume();
if (!hw_vol_works)
{
return false;
}
else
{
drv_vol.channel0 = drv_vol.channel2 =
drv_vol.channel1 = drv_vol.channel3 = value * 255.0f;
return CD_SetVolume (&drv_vol);
}
}
void CDAudio_Update(void)
{
struct cdrom_subchnl subchnl;
static time_t lastchk;
if (cdfile == -1 || !enabled)
return;
if (old_cdvolume != bgmvolume.value)
CDAudio_SetVolume (bgmvolume.value);
if (playing && lastchk < time(NULL))
{
lastchk = time(NULL) + 2; /* two seconds between chks */
subchnl.cdsc_format = CDROM_MSF;
if (ioctl(cdfile, CDROMSUBCHNL, &subchnl) == -1)
{
IOCTL_FAILURE(CDROMSUBCHNL);
playing = false;
return;
}
if (subchnl.cdsc_audiostatus != CDROM_AUDIO_PLAY &&
subchnl.cdsc_audiostatus != CDROM_AUDIO_PAUSED)
{
playing = false;
if (playLooping)
CDAudio_Play(playTrack, true);
}
else
{
playTrack = subchnl.cdsc_trk;
}
}
}
int CDAudio_Init(void)
{
int i;
if (safemode || COM_CheckParm("-nocdaudio"))
return -1;
if ((i = COM_CheckParm("-cddev")) != 0 && i < com_argc - 1)
cd_dev = com_argv[i + 1];
if ((cdfile = open(cd_dev, O_RDONLY | O_NONBLOCK)) == -1)
{
i = errno;
Con_Printf("CDAudio_Init: open of \"%s\" failed (%d: %s)\n",
cd_dev, i, strerror(i));
cdfile = -1;
return -1;
}
for (i = 0; i < 100; i++)
remap[i] = i;
initialized = true;
enabled = true;
old_cdvolume = bgmvolume.value;
Con_Printf("CDAudio initialized (using Linux ioctls)\n");
if (CDAudio_GetAudioDiskInfo())
{
Con_Printf("CDAudio_Init: No CD in drive\n");
cdValid = false;
}
Cmd_AddCommand ("cd", CD_f);
hw_vol_works = CD_GetVolume (&orig_vol);
if (hw_vol_works)
hw_vol_works = CDAudio_SetVolume (bgmvolume.value);
return 0;
}
void CDAudio_Shutdown(void)
{
if (!initialized)
return;
CDAudio_Stop();
if (hw_vol_works)
CD_SetVolume (&orig_vol);
close(cdfile);
cdfile = -1;
}
#endif /* __USE_LINUX_CDROM__ */

View file

@ -1,49 +0,0 @@
/*
cd_unix.h
Unix include file to compile the correct cdaudio code
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
*/
#ifndef __CD_UNIX_H
#define __CD_UNIX_H
#undef __USE_BSD_CDROM__
#undef __USE_LINUX_CDROM__
#undef __USE_SDL_CDROM__
#if defined (WITH_SDLCD)
/* This means that the makefile is edited for USE_SDLCD */
# define __USE_SDL_CDROM__ 1
#elif defined (__linux) || defined (__linux__)
# define __USE_LINUX_CDROM__ 1
#elif defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__)
# define __USE_BSD_CDROM__ 1
#else /* elif defined (SDLQUAKE) */
# define __USE_SDL_CDROM__ 1
/*
#else
# error "no cdaudio module defined. edit cd_unix.h or your makefile.."
*/
#endif
#endif /* __CD_UNIX_H */

View file

@ -1,619 +0,0 @@
/*
cd_win.c
Win32 cdaudio code
Copyright (C) 1996-1997 Id Software, Inc.
Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
rights reserved.
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.
51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA
*/
#include "quakedef.h"
#include "winquake.h"
#include <mmsystem.h>
/*
* You just can't set the volume of CD playback via MCI :
* http://blogs.msdn.com/larryosterman/archive/2005/10/06/477874.aspx
* OTOH, using the aux APIs to control the CD audio volume is broken.
*/
#undef USE_AUX_API
static qboolean cdValid = false;
static qboolean playing = false;
static qboolean wasPlaying = false;
static qboolean initialized = false;
static qboolean enabled = false;
static qboolean playLooping = false;
static byte remap[100];
static byte playTrack;
static byte maxTrack;
static float old_cdvolume;
static UINT wDeviceID;
static DWORD end_pos;
#if defined(USE_AUX_API)
static UINT CD_ID;
static unsigned long CD_OrigVolume;
static void CD_SetVolume(unsigned long Volume);
#endif /* USE_AUX_API */
static void CDAudio_Eject(void)
{
DWORD dwReturn;
dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD_PTR)NULL);
if (dwReturn)
Con_DPrintf("MCI_SET_DOOR_OPEN failed (%u)\n", (unsigned int)dwReturn);
}
static void CDAudio_CloseDoor(void)
{
DWORD dwReturn;
dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD_PTR)NULL);
if (dwReturn)
Con_DPrintf("MCI_SET_DOOR_CLOSED failed (%u)\n", (unsigned int)dwReturn);
}
static int CDAudio_GetAudioDiskInfo(void)
{
DWORD dwReturn;
MCI_STATUS_PARMS mciStatusParms;
cdValid = false;
mciStatusParms.dwItem = MCI_STATUS_READY;
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR) (LPVOID) &mciStatusParms);
if (dwReturn)
{
Con_DPrintf("CDAudio: drive ready test - get status failed\n");
return -1;
}
if (!mciStatusParms.dwReturn)
{
Con_DPrintf("CDAudio: drive not ready\n");
return -1;
}
mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR) (LPVOID) &mciStatusParms);
if (dwReturn)
{
Con_DPrintf("CDAudio: get tracks - status failed\n");
return -1;
}
if (mciStatusParms.dwReturn < 1)
{
Con_DPrintf("CDAudio: no music tracks\n");
return -1;
}
cdValid = true;
maxTrack = mciStatusParms.dwReturn;
return 0;
}
int CDAudio_Play(byte track, qboolean looping)
{
DWORD dwReturn;
MCI_PLAY_PARMS mciPlayParms;
MCI_STATUS_PARMS mciStatusParms;
if (!enabled)
return -1;
if (!cdValid)
{
CDAudio_GetAudioDiskInfo();
if (!cdValid)
return -1;
}
track = remap[track];
if (track < 1 || track > maxTrack)
{
Con_DPrintf("CDAudio: Bad track number %u.\n", track);
return -1;
}
// don't try to play a non-audio track
mciStatusParms.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
mciStatusParms.dwTrack = track;
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD_PTR) (LPVOID) &mciStatusParms);
if (dwReturn)
{
Con_DPrintf("MCI_STATUS failed (%u)\n", (unsigned int)dwReturn);
return -1;
}
if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO)
{
Con_Printf("CDAudio: track %i is not audio\n", track);
return -1;
}
// get the length of the track to be played
mciStatusParms.dwItem = MCI_STATUS_LENGTH;
mciStatusParms.dwTrack = track;
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD_PTR) (LPVOID) &mciStatusParms);
if (dwReturn)
{
Con_DPrintf("MCI_STATUS failed (%u)\n", (unsigned int)dwReturn);
return -1;
}
if (playing)
{
if (playTrack == track)
return 0;
CDAudio_Stop();
}
mciPlayParms.dwFrom = MCI_MAKE_TMSF(track, 0, 0, 0);
mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track;
end_pos = mciPlayParms.dwTo;
mciPlayParms.dwCallback = (DWORD_PTR)mainwindow;
dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD_PTR)(LPVOID) &mciPlayParms);
if (dwReturn)
{
Con_DPrintf("CDAudio: MCI_PLAY failed (%u)\n", (unsigned int)dwReturn);
return -1;
}
playLooping = looping;
playTrack = track;
playing = true;
if (bgmvolume.value == 0) /* don't bother advancing */
CDAudio_Pause ();
return 0;
}
void CDAudio_Stop(void)
{
DWORD dwReturn;
if (!enabled)
return;
if (!playing)
return;
dwReturn = mciSendCommand(wDeviceID, MCI_STOP, 0, (DWORD_PTR)NULL);
if (dwReturn)
Con_DPrintf("MCI_STOP failed (%u)", (unsigned int)dwReturn);
wasPlaying = false;
playing = false;
}
void CDAudio_Pause(void)
{
DWORD dwReturn;
MCI_GENERIC_PARMS mciGenericParms;
if (!enabled)
return;
if (!playing)
return;
mciGenericParms.dwCallback = (DWORD_PTR)mainwindow;
dwReturn = mciSendCommand(wDeviceID, MCI_PAUSE, 0, (DWORD_PTR)(LPVOID) &mciGenericParms);
if (dwReturn)
Con_DPrintf("MCI_PAUSE failed (%u)", (unsigned int)dwReturn);
wasPlaying = playing;
playing = false;
}
void CDAudio_Resume(void)
{
DWORD dwReturn;
MCI_STATUS_PARMS mciStatusParms;
MCI_PLAY_PARMS mciPlayParms;
if (!enabled)
return;
if (!cdValid)
return;
if (!wasPlaying)
return;
#if 0
/* dwReturn = mciSendCommand(wDeviceID, MCI_RESUME, MCI_WAIT, NULL); */
mciPlayParms.dwFrom = MCI_MAKE_TMSF(playTrack, 0, 0, 0);
mciPlayParms.dwTo = MCI_MAKE_TMSF(playTrack + 1, 0, 0, 0);
mciPlayParms.dwCallback = (DWORD_PTR)mainwindow;
dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD_PTR)(LPVOID) &mciPlayParms);
#endif
mciStatusParms.dwItem = MCI_STATUS_POSITION;
dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR) (LPVOID) &mciStatusParms);
if (dwReturn)
{
Con_DPrintf("MCI_STATUS failed (%u)\n", (unsigned int)dwReturn);
return;
}
mciPlayParms.dwFrom = mciStatusParms.dwReturn;
mciPlayParms.dwTo = end_pos; /* set in CDAudio_Play() */
mciPlayParms.dwCallback = (DWORD_PTR)mainwindow;
dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_FROM | MCI_TO | MCI_NOTIFY, (DWORD_PTR)(LPVOID) &mciPlayParms);
if (dwReturn)
{
Con_DPrintf("CDAudio: MCI_PLAY failed (%u)\n", (unsigned int)dwReturn);
return;
}
playing = true;
}
static void CD_f (void)
{
const char *command;
int ret, n;
if (Cmd_Argc() < 2)
{
Con_Printf("commands:");
Con_Printf("on, off, reset, remap, \n");
Con_Printf("play, stop, loop, pause, resume\n");
Con_Printf("eject, close, info\n");
return;
}
command = Cmd_Argv (1);
if (Q_strcasecmp(command, "on") == 0)
{
enabled = true;
return;
}
if (Q_strcasecmp(command, "off") == 0)
{
if (playing)
CDAudio_Stop();
enabled = false;
return;
}
if (Q_strcasecmp(command, "reset") == 0)
{
enabled = true;
if (playing)
CDAudio_Stop();
for (n = 0; n < 100; n++)
remap[n] = n;
CDAudio_GetAudioDiskInfo();
return;
}
if (Q_strcasecmp(command, "remap") == 0)
{
ret = Cmd_Argc() - 2;
if (ret <= 0)
{
for (n = 1; n < 100; n++)
if (remap[n] != n)
Con_Printf(" %u -> %u\n", n, remap[n]);
return;
}
for (n = 1; n <= ret; n++)
remap[n] = atoi(Cmd_Argv (n+1));
return;
}
if (Q_strcasecmp(command, "close") == 0)
{
CDAudio_CloseDoor();
return;
}
if (!cdValid)
{
CDAudio_GetAudioDiskInfo();
if (!cdValid)
{
Con_Printf("No CD in player.\n");
return;
}
}
if (Q_strcasecmp(command, "play") == 0)
{
CDAudio_Play((byte)atoi(Cmd_Argv (2)), false);
return;
}
if (Q_strcasecmp(command, "loop") == 0)
{
CDAudio_Play((byte)atoi(Cmd_Argv (2)), true);
return;
}
if (Q_strcasecmp(command, "stop") == 0)
{
CDAudio_Stop();
return;
}
if (Q_strcasecmp(command, "pause") == 0)
{
CDAudio_Pause();
return;
}
if (Q_strcasecmp(command, "resume") == 0)
{
CDAudio_Resume();
return;
}
if (Q_strcasecmp(command, "eject") == 0)
{
if (playing)
CDAudio_Stop();
CDAudio_Eject();
cdValid = false;
return;
}
if (Q_strcasecmp(command, "info") == 0)
{
Con_Printf("%u tracks\n", maxTrack);
if (playing)
Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
else if (wasPlaying)
Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
Con_Printf("Volume is %f\n", bgmvolume.value);
return;
}
}
LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (lParam != (LONG)wDeviceID)
return 1;
switch (wParam)
{
case MCI_NOTIFY_SUCCESSFUL:
if (playing)
{
playing = false;
if (playLooping)
CDAudio_Play(playTrack, true);
}
break;
case MCI_NOTIFY_ABORTED:
case MCI_NOTIFY_SUPERSEDED:
break;
case MCI_NOTIFY_FAILURE:
Con_DPrintf("MCI_NOTIFY_FAILURE\n");
CDAudio_Stop ();
cdValid = false;
break;
default:
Con_DPrintf("Unexpected MM_MCINOTIFY type (%Iu)\n", wParam);
return 1;
}
return 0;
}
static void CDAudio_SetVolume (float value)
{
old_cdvolume = value;
if (value == 0.0f)
CDAudio_Pause ();
else
CDAudio_Resume();
#if defined(USE_AUX_API)
CD_SetVolume (value * 0xffff);
#endif /* USE_AUX_API */
}
void CDAudio_Update(void)
{
if (!enabled)
return;
if (old_cdvolume != bgmvolume.value)
CDAudio_SetVolume (bgmvolume.value);
}
#if defined(USE_AUX_API)
static void CD_FindCDAux(void)
{
UINT NumDevs, counter;
MMRESULT Result;
AUXCAPS Caps;
CD_ID = -1;
if (!COM_CheckParm("-usecdvolume"))
return;
NumDevs = auxGetNumDevs();
for (counter = 0; counter < NumDevs; counter++)
{
Result = auxGetDevCaps(counter,&Caps,sizeof(Caps));
if (!Result) // valid
{
if (Caps.wTechnology == AUXCAPS_CDAUDIO)
{
CD_ID = counter;
auxGetVolume(CD_ID, &CD_OrigVolume);
return;
}
}
}
}
static void CD_SetVolume(unsigned long Volume)
{
if (CD_ID != -1)
auxSetVolume(CD_ID, (Volume<<16) + Volume);
}
#endif /* USE_AUX_API */
static const char *get_cddev_arg (const char *arg)
{
/* arg should be like "D", "D:" or "D:\", make
* sure it is so. Also check if this is really
* a CDROM drive. */
static char drive[4];
if (!arg || ! *arg)
return NULL;
if (arg[1] != '\0')
{
if (arg[1] != ':')
return NULL;
if (arg[2] != '\0')
{
if (arg[2] != '\\' &&
arg[2] != '/')
return NULL;
if (arg[3] != '\0')
return NULL;
}
}
if (*arg >= 'A' && *arg <= 'Z')
{
drive[0] = *arg;
drive[1] = ':';
drive[2] = '\\';
drive[3] = '\0';
}
else if (*arg >= 'a' && *arg <= 'z')
{
/* make it uppercase */
drive[0] = *arg - ('a' - 'A');
drive[1] = ':';
drive[2] = '\\';
drive[3] = '\0';
}
else
{
return NULL;
}
if (GetDriveType(drive) != DRIVE_CDROM)
{
Con_Printf("%c is not a CDROM drive\n", drive[0]);
return NULL;
}
drive[2] = '\0';
return drive;
}
int CDAudio_Init(void)
{
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_SET_PARMS mciSetParms;
const char *userdev = NULL;
int n;
if (safemode || COM_CheckParm("-nocdaudio"))
return -1;
if ((n = COM_CheckParm("-cddev")) != 0 && n < com_argc - 1)
{
userdev = get_cddev_arg(com_argv[n + 1]);
if (!userdev)
{
Con_Printf("Invalid argument to -cddev\n");
return -1;
}
mciOpenParms.lpstrElementName = userdev;
}
mciOpenParms.lpstrDeviceType = "cdaudio";
dwReturn = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD_PTR) (LPVOID) &mciOpenParms);
if (!userdev)
userdev = "default cdrom";
if (dwReturn)
{
Con_Printf("CDAudio_Init: MCI_OPEN failed for %s (%u)\n",
userdev, (unsigned int)dwReturn);
return -1;
}
wDeviceID = mciOpenParms.wDeviceID;
// Set the time format to track/minute/second/frame (TMSF).
mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)(LPVOID) &mciSetParms);
if (dwReturn)
{
Con_Printf("MCI_SET_TIME_FORMAT failed (%u)\n", (unsigned int)dwReturn);
mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD_PTR)NULL);
return -1;
}
for (n = 0; n < 100; n++)
remap[n] = n;
initialized = true;
enabled = true;
old_cdvolume = bgmvolume.value;
if (CDAudio_GetAudioDiskInfo())
{
Con_Printf("CDAudio_Init: No CD in player.\n");
cdValid = false;
}
Cmd_AddCommand ("cd", CD_f);
#if defined(USE_AUX_API)
CD_FindCDAux();
#endif /* USE_AUX_API */
Con_Printf("CD Audio Initialized\n");
return 0;
}
void CDAudio_Shutdown(void)
{
if (!initialized)
return;
CDAudio_Stop();
if (mciSendCommand(wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD_PTR)NULL))
Con_DPrintf("CDAudio_Shutdown: MCI_CLOSE failed\n");
}

File diff suppressed because it is too large Load diff

View file

@ -1,332 +0,0 @@
/*
snd_alsa.c
ALSA 1.0 sound driver for Linux Hexen II
Copyright (C) 1999,2004 contributors of the QuakeForge project
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
*/
#include "quakedef.h"
#include <alsa/asoundlib.h>
#define NB_PERIODS 4
//static const char alsa_default[] = "hw:0,0";
//static const char alsa_default[] = "plughw:0";
static const char alsa_default[] = "default";
static const char *pcmname = alsa_default;
static snd_pcm_t *pcm = NULL;
static snd_pcm_uframes_t buffer_size;
static const int tryrates[] = { 11025, 22050, 44100, 48000, 16000, 24000, 8000 };
static const int MAX_TRYRATES = sizeof(tryrates)/sizeof(tryrates[0]);
#if defined(__GNUC__) && \
!(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
#define ALSA_CHECK_ERR(check, fmt, args...) \
do { \
if (check < 0) { \
Con_Printf ("ALSA: " fmt, ##args); \
goto error; \
} \
} while (0)
#else
#define ALSA_CHECK_ERR(check, ...) \
do { \
if (check < 0) { \
Con_Printf ("ALSA: " __VA_ARGS__); \
goto error; \
} \
} while (0)
#endif
qboolean SNDDMA_Init (dma_t *dma)
{
int i, err;
unsigned int rate;
int tmp_bits, tmp_chan;
snd_pcm_hw_params_t *hw = NULL;
snd_pcm_sw_params_t *sw = NULL;
snd_pcm_uframes_t frag_size;
i = COM_CheckParm("-alsadev");
if (i != 0 && i < com_argc - 1)
pcmname = com_argv[i + 1];
err = snd_pcm_open (&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if (err < 0)
{
Con_Printf ("ALSA: error opening device \"%s\": %s\n", pcmname, snd_strerror(err));
return false;
}
Con_Printf ("ALSA: Using device: %s\n", pcmname);
err = snd_pcm_hw_params_malloc (&hw);
ALSA_CHECK_ERR(err, "unable to allocate hardware params. %s\n", snd_strerror(err));
err = snd_pcm_hw_params_any (pcm, hw);
ALSA_CHECK_ERR(err, "unable to init hardware params. %s\n", snd_strerror(err));
err = snd_pcm_hw_params_set_access (pcm, hw, SND_PCM_ACCESS_MMAP_INTERLEAVED);
ALSA_CHECK_ERR(err, "unable to set interleaved access. %s\n", snd_strerror(err));
i = (loadas8bit.value) ? 8 : 16;
tmp_bits = (i == 8) ? SND_PCM_FORMAT_U8 : SND_PCM_FORMAT_S16;
err = snd_pcm_hw_params_set_format (pcm, hw, (snd_pcm_format_t) tmp_bits);
if (err < 0)
{
Con_Printf ("Problems setting %d bit format, trying alternatives..\n", i);
tmp_bits = (i == 8) ? SND_PCM_FORMAT_S16 : SND_PCM_FORMAT_U8;
err = snd_pcm_hw_params_set_format (pcm, hw, (snd_pcm_format_t) tmp_bits);
ALSA_CHECK_ERR(err, "Neither 8 nor 16 bit format supported. %s\n", snd_strerror(err));
}
tmp_bits = (tmp_bits == SND_PCM_FORMAT_U8) ? 8 : 16;
i = tmp_chan = (COM_CheckParm("-sndmono") == 0) ? 2 : 1;
err = snd_pcm_hw_params_set_channels (pcm, hw, tmp_chan);
if (err < 0)
{
Con_Printf ("Problems setting channels to %s, retrying for %s\n",
(i == 2) ? "stereo" : "mono",
(i == 2) ? "mono" : "stereo");
tmp_chan = (i == 2) ? 1 : 2;
err = snd_pcm_hw_params_set_channels (pcm, hw, tmp_chan);
ALSA_CHECK_ERR(err, "unable to set desired channels. %s\n", snd_strerror(err));
}
rate = (int)sndspeed.value;
err = snd_pcm_hw_params_set_rate_near (pcm, hw, &rate, 0);
if (err < 0)
{
Con_Printf("Problems setting sample rate, trying alternatives..\n");
for (i = 0; i < MAX_TRYRATES; i++)
{
rate = tryrates[i];
err = snd_pcm_hw_params_set_rate_near (pcm, hw, &rate, 0);
if (err < 0)
{
Con_DPrintf ("Unable to set sample rate %d\n", tryrates[i]);
rate = 0;
}
else
{
if (rate != (unsigned int) tryrates[i])
{
Con_Printf ("Warning: Rate set (%u) didn't match requested rate (%d)!\n", rate, tryrates[i]);
// goto error;
}
break;
}
}
if (rate == 0)
{
Con_Printf ("Unable to set any sample rates.\n");
goto error;
}
}
else
{
if (rate != (unsigned int) sndspeed.value)
{
Con_Printf ("Warning: Rate set (%u) didn't match requested rate (%d)!\n", rate, (int)sndspeed.value);
// goto error;
}
}
/* pick a buffer size that is a power of 2 (by masking off low bits) */
buffer_size = i = (int)(rate * 0.15f);
while (buffer_size & (buffer_size-1))
buffer_size &= (buffer_size-1);
/* then check if it is the nearest power of 2 and bump it up if not */
if (i - buffer_size >= buffer_size >> 1)
buffer_size *= 2;
err = snd_pcm_hw_params_set_buffer_size_near (pcm, hw, &buffer_size);
ALSA_CHECK_ERR(err, "unable to set buffer size near %lu (%s)\n",
(unsigned long)buffer_size, snd_strerror(err));
err = snd_pcm_hw_params_get_buffer_size (hw, &buffer_size);
ALSA_CHECK_ERR(err, "unable to get buffer size. %s\n", snd_strerror(err));
if (buffer_size & (buffer_size-1))
{
Con_Printf ("ALSA: WARNING: non-power of 2 buffer size. sound may be\n");
Con_Printf ("unsatisfactory. Recommend using either the plughw or hw\n");
Con_Printf ("devices or adjusting dmix to have a power of 2 buf size\n");
}
/* pick a period size near the buffer_size we got from ALSA */
frag_size = buffer_size / NB_PERIODS;
err = snd_pcm_hw_params_set_period_size_near (pcm, hw, &frag_size, 0);
ALSA_CHECK_ERR(err, "unable to set period size near %i. %s\n",
(int)frag_size, snd_strerror(err));
err = snd_pcm_hw_params (pcm, hw);
ALSA_CHECK_ERR(err, "unable to install hardware params. %s\n", snd_strerror(err));
err = snd_pcm_sw_params_malloc (&sw);
ALSA_CHECK_ERR(err, "unable to allocate software params. %s\n", snd_strerror(err));
err = snd_pcm_sw_params_current (pcm, sw);
ALSA_CHECK_ERR(err, "unable to determine current software params. %s\n", snd_strerror(err));
err = snd_pcm_sw_params_set_start_threshold (pcm, sw, ~0U);
ALSA_CHECK_ERR(err, "unable to set playback threshold. %s\n", snd_strerror(err));
err = snd_pcm_sw_params_set_stop_threshold (pcm, sw, ~0U);
ALSA_CHECK_ERR(err, "unable to set playback stop threshold. %s\n", snd_strerror(err));
err = snd_pcm_sw_params (pcm, sw);
ALSA_CHECK_ERR(err, "unable to install software params. %s\n", snd_strerror(err));
memset ((void *) dma, 0, sizeof(dma_t));
shm = dma;
shm->channels = tmp_chan;
/*
// don't mix less than this in mono samples:
err = snd_pcm_hw_params_get_period_size (hw,
(snd_pcm_uframes_t *) (char *) (&shm->submission_chunk), 0);
ALSA_CHECK_ERR(err, "unable to get period size. %s\n", snd_strerror(err));
*/
shm->submission_chunk = 1;
shm->samplepos = 0;
shm->samplebits = tmp_bits;
Con_Printf ("ALSA: %lu bytes buffer with mmap interleaved access\n", (unsigned long)buffer_size);
shm->samples = buffer_size * shm->channels; // mono samples in buffer
shm->speed = rate;
SNDDMA_GetDMAPos (); // sets shm->buffer
snd_pcm_hw_params_free(hw);
snd_pcm_sw_params_free(sw);
return true;
error:
// full clean-up
if (hw)
snd_pcm_hw_params_free(hw);
if (sw)
snd_pcm_sw_params_free(sw);
shm = NULL;
snd_pcm_close (pcm);
pcm = NULL;
return false;
}
int SNDDMA_GetDMAPos (void)
{
snd_pcm_uframes_t offset;
snd_pcm_uframes_t nframes;
const snd_pcm_channel_area_t *areas;
if (!shm)
return 0;
nframes = shm->samples/shm->channels;
snd_pcm_avail_update (pcm);
snd_pcm_mmap_begin (pcm, &areas, &offset, &nframes);
// The following commit was absent in QF, causing the
// very first sound to be corrupted
snd_pcm_mmap_commit (pcm, offset, nframes);
offset *= shm->channels;
nframes *= shm->channels;
shm->samplepos = offset;
shm->buffer = (unsigned char *) areas->addr; // FIXME! there's an area per channel
return shm->samplepos;
}
void SNDDMA_Shutdown (void)
{
if (shm)
{
// full clean-up
Con_Printf ("Shutting down ALSA sound\n");
snd_pcm_drop (pcm); // do I need this?
snd_pcm_close (pcm);
pcm = NULL;
shm->buffer = NULL;
shm = NULL;
}
}
/*
==============
SNDDMA_LockBuffer
Makes sure dma buffer is valid
==============
*/
void SNDDMA_LockBuffer (void)
{
/* nothing to do here */
}
/*
==============
SNDDMA_Submit
Unlock the dma buffer /
Send sound to the device
==============
*/
void SNDDMA_Submit (void)
{
snd_pcm_uframes_t offset;
snd_pcm_uframes_t nframes;
const snd_pcm_channel_area_t *areas;
int state;
int count = paintedtime - soundtime;
nframes = count / shm->channels;
snd_pcm_avail_update (pcm);
snd_pcm_mmap_begin (pcm, &areas, &offset, &nframes);
state = snd_pcm_state (pcm);
switch (state)
{
case SND_PCM_STATE_PREPARED:
snd_pcm_mmap_commit (pcm, offset, nframes);
snd_pcm_start (pcm);
break;
case SND_PCM_STATE_RUNNING:
snd_pcm_mmap_commit (pcm, offset, nframes);
break;
default:
break;
}
}
void SNDDMA_BlockSound (void)
{
snd_pcm_pause (pcm, 1);
}
void SNDDMA_UnblockSound (void)
{
snd_pcm_pause (pcm, 0);
}

View file

@ -1,315 +0,0 @@
/*
snd_oss.c
Copyright (C) 1996-1997 Id Software, Inc.
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
*/
#include "quakedef.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/wait.h>
/* FIXME: <sys/soundcard.h> is by the book, but we might
* have to take care of <soundcard.h>, <linux/soundcard.h>
* and <machine/soundcard.h> someday. */
#include <sys/soundcard.h>
#include <errno.h>
static int FORMAT_S16;
static int audio_fd = -1;
static const char oss_default[] = "/dev/dsp";
static const char *ossdev = oss_default;
static unsigned long mmaplen;
static const int tryrates[] = { 11025, 22050, 44100, 48000, 16000, 24000, 8000 };
static const int MAX_TRYRATES = sizeof(tryrates)/sizeof(tryrates[0]);
qboolean SNDDMA_Init (dma_t *dma)
{
int i, caps, tmp;
unsigned long sz;
struct audio_buf_info info;
if (host_bigendian) FORMAT_S16 = AFMT_S16_BE;
else FORMAT_S16 = AFMT_S16_LE;
tmp = COM_CheckParm("-ossdev");
if (tmp != 0 && tmp < com_argc - 1)
ossdev = com_argv[tmp + 1];
Con_Printf ("OSS: Using device: %s\n", ossdev);
// open /dev/dsp, confirm capability to mmap, and get size of dma buffer
audio_fd = open(ossdev, O_RDWR|O_NONBLOCK);
if (audio_fd == -1)
{ // Failed open, retry up to 3 times if it's busy
tmp = 3;
while ( (audio_fd == -1) && tmp-- &&
((errno == EAGAIN) || (errno == EBUSY)) )
{
sleep (1);
audio_fd = open(ossdev, O_RDWR|O_NONBLOCK);
}
if (audio_fd == -1)
{
Con_Printf("Could not open %s. %s\n", ossdev, strerror(errno));
return false;
}
}
memset ((void *) dma, 0, sizeof(dma_t));
shm = dma;
if (ioctl(audio_fd, SNDCTL_DSP_RESET, 0) == -1)
{
Con_Printf("Could not reset %s. %s\n", ossdev, strerror(errno));
goto error;
}
if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps) == -1)
{
Con_Printf("Couldn't retrieve soundcard capabilities. %s\n", strerror(errno));
goto error;
}
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP))
{
Con_Printf("Audio driver doesn't support mmap or trigger\n");
goto error;
}
// set sample bits & speed
i = (loadas8bit.value) ? 8 : 16;
tmp = (i == 16) ? FORMAT_S16 : AFMT_U8;
if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp) == -1)
{
Con_Printf("Problems setting %d bit format, trying alternatives..\n", i);
// try what the device gives us
if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp) == -1)
{
Con_Printf("Unable to retrieve supported formats. %s\n", strerror(errno));
goto error;
}
if (tmp & FORMAT_S16)
{
i = 16;
tmp = FORMAT_S16;
}
else if (tmp & AFMT_U8)
{
i = 8;
tmp = AFMT_U8;
}
else
{
Con_Printf("Neither 8 nor 16 bit format supported.\n");
goto error;
}
if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp) == -1)
{
Con_Printf("Unable to set sound format. %s\n", strerror(errno));
goto error;
}
}
shm->samplebits = i;
tmp = (int)sndspeed.value;
if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp) == -1)
{
Con_Printf("Problems setting sample rate, trying alternatives..\n");
shm->speed = 0;
for (i = 0; i < MAX_TRYRATES; i++)
{
tmp = tryrates[i];
if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp) == -1)
{
Con_DPrintf ("Unable to set sample rate %d\n", tryrates[i]);
}
else
{
if (tmp != tryrates[i])
{
Con_Printf ("Warning: Rate set (%d) didn't match requested rate (%d)!\n", tmp, tryrates[i]);
// goto error;
}
shm->speed = tmp;
break;
}
}
if (shm->speed == 0)
{
Con_Printf("Unable to set any sample rates.\n");
goto error;
}
}
else
{
if (tmp != (int)sndspeed.value)
{
Con_Printf ("Warning: Rate set (%d) didn't match requested rate (%d)!\n", tmp, (int)sndspeed.value);
// goto error;
}
shm->speed = tmp;
}
i = (COM_CheckParm("-sndmono") == 0) ? 2 : 1;
tmp = (i == 2) ? 1 : 0;
if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp) == -1)
{
Con_Printf ("Problems setting channels to %s, retrying for %s\n",
(i == 2) ? "stereo" : "mono",
(i == 2) ? "mono" : "stereo");
tmp = (i == 2) ? 0 : 1;
if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp) == -1)
{
Con_Printf("unable to set desired channels. %s\n", strerror(errno));
goto error;
}
}
shm->channels = tmp +1;
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
{
Con_Printf("Couldn't retrieve buffer status. %s\n", strerror(errno));
goto error;
}
shm->samples = info.fragstotal * info.fragsize / (shm->samplebits / 8);
shm->submission_chunk = 1;
// memory map the dma buffer
sz = sysconf (_SC_PAGESIZE);
mmaplen = info.fragstotal * info.fragsize;
mmaplen = (mmaplen + sz - 1) & ~(sz - 1);
shm->buffer = (unsigned char *) mmap(NULL, mmaplen, PROT_READ|PROT_WRITE,
MAP_FILE|MAP_SHARED, audio_fd, 0);
if (!shm->buffer || shm->buffer == MAP_FAILED)
{
Con_Printf("Could not mmap %s. %s\n", ossdev, strerror(errno));
goto error;
}
Con_Printf ("OSS: mmaped %lu bytes buffer\n", mmaplen);
// toggle the trigger & start her up
tmp = 0;
if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp) == -1)
{
Con_Printf("Could not toggle %s. %s\n", ossdev, strerror(errno));
munmap (shm->buffer, mmaplen);
goto error;
}
tmp = PCM_ENABLE_OUTPUT;
if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp) == -1)
{
Con_Printf("Could not toggle %s. %s\n", ossdev, strerror(errno));
munmap (shm->buffer, mmaplen);
goto error;
}
shm->samplepos = 0;
return true;
error:
close(audio_fd);
audio_fd = -1;
shm->buffer = NULL;
shm = NULL;
return false;
}
int SNDDMA_GetDMAPos (void)
{
struct count_info count;
if (!shm)
return 0;
if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count) == -1)
{
Con_Printf("Uh, sound dead. %s\n", strerror(errno));
munmap (shm->buffer, mmaplen);
shm->buffer = NULL;
shm = NULL;
close(audio_fd);
audio_fd = -1;
return 0;
}
// shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
// fprintf(stderr, "%d \r", count.ptr);
shm->samplepos = count.ptr / (shm->samplebits / 8);
return shm->samplepos;
}
void SNDDMA_Shutdown (void)
{
int tmp = 0;
if (shm)
{
Con_Printf ("Shutting down OSS sound\n");
munmap (shm->buffer, mmaplen);
shm->buffer = NULL;
shm = NULL;
ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
close(audio_fd);
audio_fd = -1;
}
}
/*
==============
SNDDMA_LockBuffer
Makes sure dma buffer is valid
==============
*/
void SNDDMA_LockBuffer (void)
{
/* nothing to do here */
}
/*
==============
SNDDMA_Submit
Unlock the dma buffer /
Send sound to the device
===============
*/
void SNDDMA_Submit(void)
{
}
void SNDDMA_BlockSound (void)
{
}
void SNDDMA_UnblockSound (void)
{
}

View file

@ -1,773 +0,0 @@
/*
snd_win.c
$Id: snd_win.c,v 1.37 2008-12-28 14:34:34 sezero Exp $
Copyright (C) 1996-1997 Id Software, Inc.
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.
51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
*/
#define DX_DLSYM /* dynamic loading of dsound symbols */
#include "quakedef.h"
#include "winquake.h"
#include <mmsystem.h>
#include <dsound.h>
//#define SNDBUFSIZE 65536
// 64K is > 1 second at 16-bit, 22050 Hz
//#define WAV_BUFFERS 64
#define WAV_BUFFERS 128
#define WAV_MASK (WAV_BUFFERS - 1)
/* DirectSound : */
#ifndef DSBSIZE_MIN
#define DSBSIZE_MIN 4
#endif
#ifndef DSBSIZE_MAX
#define DSBSIZE_MAX 0x0FFFFFFF
#endif
static LPDIRECTSOUND pDS;
static LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
#if defined(DX_DLSYM) /* dynamic loading of dsound symbols */
static HINSTANCE hInstDS;
static HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter);
#else /* ! DX_DLSYM : we're linked to dsound */
#define pDirectSoundCreate DirectSoundCreate
#endif /* DX_DLSYM */
typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
static qboolean wavonly;
static qboolean dsound_init;
static qboolean wav_init;
static qboolean snd_firsttime = true, snd_isdirect, snd_iswave;
static qboolean primary_format_set;
static int sample16;
static int snd_sent, snd_completed;
static int ds_sbuf_size, wv_buf_size;
static HANDLE hData;
static HGLOBAL hWaveHdr;
static HPSTR lpData;
static LPWAVEHDR lpWaveHdr;
static HWAVEOUT hWaveOut;
//WAVEOUTCAPS wavecaps;
static DWORD gSndBufSize;
static MMTIME mmstarttime;
/*
==================
FreeSound
==================
*/
static void FreeSound (void)
{
int i;
if (pDSBuf)
{
IDirectSoundBuffer_Stop(pDSBuf);
IDirectSound_Release(pDSBuf);
}
// only release primary buffer if it's not also the mixing buffer we just released
if (pDSPBuf && (pDSBuf != pDSPBuf))
{
IDirectSound_Release(pDSPBuf);
}
if (pDS)
{
IDirectSound_SetCooperativeLevel(pDS, mainwindow, DSSCL_NORMAL);
IDirectSound_Release(pDS);
}
if (hWaveOut)
{
waveOutReset (hWaveOut);
if (lpWaveHdr)
{
for (i = 0; i < WAV_BUFFERS; i++)
waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR));
}
waveOutClose (hWaveOut);
if (hWaveHdr)
{
GlobalUnlock(hWaveHdr);
GlobalFree(hWaveHdr);
}
if (hData)
{
GlobalUnlock(hData);
GlobalFree(hData);
}
}
pDS = NULL;
pDSBuf = NULL;
pDSPBuf = NULL;
hWaveOut = 0;
hData = 0;
hWaveHdr = 0;
lpData = NULL;
lpWaveHdr = NULL;
dsound_init = false;
wav_init = false;
}
/*
==================
SNDDMA_InitDirect
Direct-Sound support
==================
*/
static sndinitstat SNDDMA_InitDirect (dma_t *dma)
{
DSBUFFERDESC dsbuf;
DSBCAPS dsbcaps;
DWORD dwSize, dwWrite;
DSCAPS dscaps;
WAVEFORMATEX format, pformat;
HRESULT hresult;
int reps;
memset((void *) dma, 0, sizeof(dma_t));
shm = dma;
shm->channels = 2; /* = desired_channels; */
shm->samplebits = (loadas8bit.value) ? 8 : 16;
shm->speed = sndspeed.value;
memset (&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = shm->channels;
format.wBitsPerSample = shm->samplebits;
format.nSamplesPerSec = shm->speed;
format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
format.cbSize = 0;
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
#if defined(DX_DLSYM)
if (!hInstDS)
{
hInstDS = LoadLibrary("dsound.dll");
if (hInstDS == NULL)
{
Con_SafePrintf ("Couldn't load dsound.dll\n");
return SIS_FAILURE;
}
pDirectSoundCreate = (HRESULT (WINAPI *)(GUID FAR *, LPDIRECTSOUND FAR *, IUnknown FAR *))
GetProcAddress(hInstDS,"DirectSoundCreate");
if (!pDirectSoundCreate)
{
Con_SafePrintf ("Couldn't get DS proc addr\n");
return SIS_FAILURE;
}
}
#endif /* DX_DLSYM */
hresult = pDirectSoundCreate(NULL, &pDS, NULL);
if (hresult != DS_OK)
{
if (hresult != DSERR_ALLOCATED)
{
Con_SafePrintf ("DirectSound create failed\n");
return SIS_FAILURE;
}
Con_SafePrintf ("DirectSoundCreate failure, hardware already in use\n");
return SIS_NOTAVAIL;
}
dscaps.dwSize = sizeof(dscaps);
if (DS_OK != IDirectSound_GetCaps(pDS, &dscaps))
{
Con_SafePrintf ("Couldn't get DS caps\n");
}
if (dscaps.dwFlags & DSCAPS_EMULDRIVER)
{
Con_SafePrintf ("No DirectSound driver installed\n");
FreeSound ();
return SIS_FAILURE;
}
// if (DS_OK != IDirectSound_SetCooperativeLevel(pDS, mainwindow, DSSCL_EXCLUSIVE))
/* Pa3PyX: Some MIDI synthesizers are software and require access to
waveOut; so if we set the coop level to exclusive, MIDI will fail
to init because the device is locked. We use priority level instead.
That way we don't lock out software synths and other apps, but can
still set the sound buffer format. */
if (DS_OK != IDirectSound_SetCooperativeLevel(pDS, mainwindow, DSSCL_PRIORITY))
{
Con_SafePrintf ("Set coop level failed\n");
FreeSound ();
return SIS_FAILURE;
}
// get access to the primary buffer, if possible, so we can set the
// sound hardware format
memset (&dsbuf, 0, sizeof(dsbuf));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbuf.dwBufferBytes = 0;
dsbuf.lpwfxFormat = NULL;
memset(&dsbcaps, 0, sizeof(dsbcaps));
dsbcaps.dwSize = sizeof(dsbcaps);
primary_format_set = false;
if (!COM_CheckParm ("-snoforceformat"))
{
if (DS_OK == IDirectSound_CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL))
{
pformat = format;
if (DS_OK != IDirectSoundBuffer_SetFormat(pDSPBuf, &pformat))
{
if (snd_firsttime)
Con_SafePrintf ("Set primary sound buffer format: no\n");
}
else
{
if (snd_firsttime)
Con_SafePrintf ("Set primary sound buffer format: yes\n");
primary_format_set = true;
}
}
}
if (!primary_format_set || !COM_CheckParm ("-primarysound"))
{
// create the secondary buffer we'll actually work with
memset (&dsbuf, 0, sizeof(dsbuf));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
if (ds_sbuf_size < DSBSIZE_MIN)
ds_sbuf_size = 1 << (Q_log2(DSBSIZE_MIN) + 1);
if (ds_sbuf_size > DSBSIZE_MAX)
ds_sbuf_size = 1 << Q_log2(DSBSIZE_MAX);
dsbuf.dwBufferBytes = ds_sbuf_size;
dsbuf.lpwfxFormat = &format;
memset(&dsbcaps, 0, sizeof(dsbcaps));
dsbcaps.dwSize = sizeof(dsbcaps);
if (DS_OK != IDirectSound_CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL))
{
Con_SafePrintf ("DS:CreateSoundBuffer Failed");
FreeSound ();
return SIS_FAILURE;
}
shm->channels = format.nChannels;
shm->samplebits = format.wBitsPerSample;
shm->speed = format.nSamplesPerSec;
if (DS_OK != IDirectSound_GetCaps(pDSBuf, &dsbcaps))
{
Con_SafePrintf ("DS:GetCaps failed\n");
FreeSound ();
return SIS_FAILURE;
}
if (snd_firsttime)
Con_SafePrintf ("Using secondary sound buffer\n");
}
else
{
if (DS_OK != IDirectSound_SetCooperativeLevel(pDS, mainwindow, DSSCL_WRITEPRIMARY))
{
Con_SafePrintf ("Set coop level failed\n");
FreeSound ();
return SIS_FAILURE;
}
if (DS_OK != IDirectSound_GetCaps(pDSPBuf, &dsbcaps))
{
Con_Printf ("DS:GetCaps failed\n");
return SIS_FAILURE;
}
pDSBuf = pDSPBuf;
Con_SafePrintf ("Using primary sound buffer\n");
}
// Make sure mixer is active
IDirectSoundBuffer_Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
if (snd_firsttime)
Con_SafePrintf ("%lu bytes in sound buffer\n", (unsigned long)dsbcaps.dwBufferBytes);
gSndBufSize = dsbcaps.dwBufferBytes;
// initialize the buffer
reps = 0;
while ((hresult = IDirectSoundBuffer_Lock(pDSBuf, 0, gSndBufSize, (LPVOID *) (HPSTR) &lpData, &dwSize, NULL, NULL, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n");
FreeSound ();
return SIS_FAILURE;
}
if (++reps > 10000)
{
Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n");
FreeSound ();
return SIS_FAILURE;
}
}
memset(lpData, 0, dwSize);
// lpData[4] = lpData[5] = 0x7f; // force a pop for debugging
IDirectSoundBuffer_Unlock(pDSBuf, lpData, dwSize, NULL, 0);
/* we don't want anyone to access the buffer directly w/o locking it first. */
lpData = NULL;
IDirectSoundBuffer_Stop(pDSBuf);
IDirectSoundBuffer_GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite);
IDirectSoundBuffer_Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
shm->samples = gSndBufSize / (shm->samplebits / 8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) lpData;
sample16 = (shm->samplebits / 8) - 1;
dsound_init = true;
return SIS_SUCCESS;
}
/*
==================
SNDDM_InitWav
Crappy windows multimedia base
==================
*/
static qboolean SNDDMA_InitWav (dma_t *dma)
{
WAVEFORMATEX format;
int i;
HRESULT hr;
snd_sent = 0;
snd_completed = 0;
memset((void *) dma, 0, sizeof(dma_t));
shm = dma;
shm->channels = 2; /* = desired_channels; */
shm->samplebits = (loadas8bit.value) ? 8 : 16;
shm->speed = sndspeed.value;
memset (&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = shm->channels;
format.wBitsPerSample = shm->samplebits;
format.nSamplesPerSec = shm->speed;
format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
format.cbSize = 0;
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
/* Open a waveform device for output using window callback. */
hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, &format, 0, 0L, CALLBACK_NULL);
if (hr != MMSYSERR_NOERROR)
{
if (hr != MMSYSERR_ALLOCATED)
{
Con_SafePrintf ("waveOutOpen failed\n");
return false;
}
Con_SafePrintf ("waveOutOpen failure, hardware already in use\n");
return false;
}
/*
* Allocate and lock memory for the waveform data. The memory
* for waveform data must be globally allocated with
* GMEM_MOVEABLE and GMEM_SHARE flags.
*/
gSndBufSize = WAV_BUFFERS * wv_buf_size;
hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize);
if (!hData)
{
Con_SafePrintf ("Sound: Out of memory.\n");
FreeSound ();
return false;
}
lpData = (HPSTR) GlobalLock(hData);
if (!lpData)
{
Con_SafePrintf ("Sound: Failed to lock.\n");
FreeSound ();
return false;
}
memset (lpData, 0, gSndBufSize);
/*
* Allocate and lock memory for the header. This memory must
* also be globally allocated with GMEM_MOVEABLE and
* GMEM_SHARE flags.
*/
hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS);
if (hWaveHdr == NULL)
{
Con_SafePrintf ("Sound: Failed to Alloc header.\n");
FreeSound ();
return false;
}
lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr);
if (lpWaveHdr == NULL)
{
Con_SafePrintf ("Sound: Failed to lock header.\n");
FreeSound ();
return false;
}
memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS);
/* After allocation, set up and prepare headers. */
for (i = 0; i < WAV_BUFFERS; i++)
{
lpWaveHdr[i].dwBufferLength = wv_buf_size;
lpWaveHdr[i].lpData = lpData + i * wv_buf_size;
if (waveOutPrepareHeader(hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
{
Con_SafePrintf ("Sound: failed to prepare wave headers\n");
FreeSound ();
return false;
}
}
shm->samples = gSndBufSize / (shm->samplebits / 8);
shm->samplepos = 0;
shm->submission_chunk = 1;
shm->buffer = (unsigned char *) lpData;
sample16 = (shm->samplebits / 8) - 1;
wav_init = true;
Con_SafePrintf ("%d sound buffers, %d bytes/sound buffer\n", WAV_BUFFERS, wv_buf_size);
return true;
}
/*
==================
SNDDMA_Init
Try to find a sound device to mix for.
Returns false if nothing is found.
==================
*/
qboolean SNDDMA_Init (dma_t *dma)
{
sndinitstat stat;
int sndbits = (loadas8bit.value) ? 8 : 16;
if (COM_CheckParm ("-wavonly"))
wavonly = true;
dsound_init = wav_init = 0;
stat = SIS_FAILURE; // assume DirectSound won't initialize
/* Calculate Wave and DS buffer sizes to set, to store
2 secs of data, round up to the next power of 2 */
ds_sbuf_size = 1 << (Q_log2((sndbits >> 3) * ((int)sndspeed.value << 1)) + 1);
wv_buf_size = 1 << (Q_log2(((int)sndspeed.value << 3) / WAV_BUFFERS) + 1);
/* Init DirectSound */
if (!wavonly)
{
if (snd_firsttime || snd_isdirect)
{
stat = SNDDMA_InitDirect (dma);
if (stat == SIS_SUCCESS)
{
snd_isdirect = true;
if (snd_firsttime)
Con_SafePrintf ("DirectSound initialized\n");
}
else
{
snd_isdirect = false;
Con_SafePrintf ("DirectSound failed to init\n");
}
}
}
// if DirectSound didn't succeed in initializing, try to initialize
// waveOut sound, unless DirectSound failed because the hardware is
// already allocated (in which case the user has already chosen not
// to have sound)
if (!dsound_init && (stat != SIS_NOTAVAIL))
{
if (snd_firsttime || snd_iswave)
{
snd_iswave = SNDDMA_InitWav (dma);
if (snd_iswave)
{
if (snd_firsttime)
Con_SafePrintf ("Wave sound initialized\n");
}
else
{
Con_SafePrintf ("Wave sound failed to init\n");
}
}
}
if (!dsound_init && !wav_init)
{
if (snd_firsttime)
Con_SafePrintf ("No sound device initialized\n");
snd_firsttime = false;
return false;
}
snd_firsttime = false;
return true;
}
/*
==============
SNDDMA_GetDMAPos
return the current sample position (in mono samples read)
inside the recirculating dma buffer, so the mixing code will know
how many sample are required to fill it up.
===============
*/
int SNDDMA_GetDMAPos (void)
{
MMTIME mmtime;
int s;
DWORD dwWrite;
if (dsound_init)
{
mmtime.wType = TIME_SAMPLES;
IDirectSoundBuffer_GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite);
s = mmtime.u.sample - mmstarttime.u.sample;
}
else if (wav_init)
{
s = snd_sent * wv_buf_size;
}
else
{ // we should not reach here...
return 0;
}
s >>= sample16;
s &= (shm->samples-1);
return s;
}
/*
==============
SNDDMA_LockBuffer
Makes sure dma buffer is valid
===============
*/
static DWORD locksize;
void SNDDMA_LockBuffer (void)
{
if (pDSBuf)
{
void *pData;
int reps;
HRESULT hresult;
DWORD dwStatus;
reps = 0;
shm->buffer = NULL;
if (IDirectSoundBuffer_GetStatus(pDSBuf, &dwStatus) != DS_OK)
Con_Printf ("Couldn't get sound buffer status\n");
if (dwStatus & DSBSTATUS_BUFFERLOST)
IDirectSoundBuffer_Restore(pDSBuf);
if (!(dwStatus & DSBSTATUS_PLAYING))
IDirectSoundBuffer_Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
while ((hresult = IDirectSoundBuffer_Lock(pDSBuf, 0, gSndBufSize, (void **) &pData, &locksize, NULL, NULL, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
Con_Printf ("SNDDMA_LockBuffer: DS::Lock Sound Buffer Failed\n");
S_Shutdown ();
return;
}
if (++reps > 10000)
{
Con_Printf ("SNDDMA_LockBuffer: DS: couldn't restore buffer\n");
S_Shutdown ();
return;
}
}
shm->buffer = (unsigned char *) pData;
}
}
/*
==============
SNDDMA_Submit
Unlock the dma buffer /
Send sound to the device
===============
*/
void SNDDMA_Submit (void)
{
LPWAVEHDR h;
int wResult;
if (pDSBuf)
IDirectSoundBuffer_Unlock(pDSBuf, shm->buffer, locksize, NULL, 0);
if (!wav_init)
return;
//
// find which sound blocks have completed
//
while (1)
{
if ( snd_completed == snd_sent )
{
Con_DPrintf ("Sound overrun\n");
break;
}
if ( ! (lpWaveHdr[snd_completed & WAV_MASK].dwFlags & WHDR_DONE) )
{
break;
}
snd_completed++; // this buffer has been played
}
//
// submit two new sound blocks
//
while (((snd_sent - snd_completed) >> sample16) < 4)
{
h = lpWaveHdr + (snd_sent & WAV_MASK);
snd_sent++;
/*
* Now the data block can be sent to the output device. The
* waveOutWrite function returns immediately and waveform
* data is sent to the output device in the background.
*/
wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR));
if (wResult != MMSYSERR_NOERROR)
{
Con_SafePrintf ("Failed to write block to device\n");
FreeSound ();
return;
}
}
}
/*
==================
SNDDMA_BlockSound
==================
*/
void SNDDMA_BlockSound (void)
{
// DirectSound takes care of blocking itself
if (snd_iswave)
{
waveOutReset (hWaveOut);
}
}
/*
==================
SNDDMA_UnblockSound
==================
*/
void SNDDMA_UnblockSound (void)
{
}
/*
==============
SNDDMA_Shutdown
Reset the sound device for exiting
===============
*/
void SNDDMA_Shutdown (void)
{
FreeSound ();
#if defined(DX_DLSYM)
if (hInstDS)
{
FreeLibrary(hInstDS);
hInstDS = NULL;
}
#endif /* DX_DLSYM */
}

View file

@ -1,78 +0,0 @@
/*
Copyright (C) 1996-2001 Id Software, Inc.
Copyright (C) 2002-2009 John Fitzgibbons and others
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// winquake.h: Win32-specific Quake header file
#ifndef __WINQUAKE_H
#define __WINQUAKE_H
/* include windows.h here, because we need the data types */
#include <windows.h>
/* required compatibility versions for directx components */
#define DIRECTDRAW_VERSION 0x0300
#define DIRECTSOUND_VERSION 0x0300
#define DIRECTINPUT_VERSION 0x0300
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif
extern qboolean Win95, Win95old, WinNT, WinVista;
extern HINSTANCE global_hInstance;
extern int global_nCmdShow;
extern qboolean DDActive;
extern HWND mainwindow;
extern qboolean ActiveApp, Minimized;
void VID_LockBuffer (void);
void VID_UnlockBuffer (void);
int VID_ForceUnlockedAndReturnState (void);
void VID_ForceLockState (int lk);
void IN_ShowMouse (void);
void IN_DeactivateMouse (void);
void IN_HideMouse (void);
void IN_ActivateMouse (void);
void IN_RestoreOriginalMouseState (void);
void IN_SetQuakeMouseState (void);
void IN_MouseEvent (int mstate);
extern cvar_t _windowed_mouse;
extern int window_center_x, window_center_y;
extern RECT window_rect;
extern qboolean mouseinitialized;
extern HWND hwnd_dialog;
extern HANDLE hinput, houtput;
void IN_UpdateClipCursor (void);
void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify);
void VID_SetDefaultMode (void);
#endif /* __WINQUAKE_H */