ngunix/tracker/tracker_linux.c

233 lines
6.3 KiB
C

/*
Copyright (C) 2015 Marco "eukara" Hladik
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 the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef DUMB
#include "globaldef.h"
#include "dumb.h"
#include <AL/al.h>
#include <AL/alc.h>
// eukara - added in tracker playback using DUMB - UNIX ONLY!
char name[256];
DUH *trackmod; // The music file ~eukara
DUH_SIGRENDERER *sr; // The DUMB renderer
ALCdevice *oss_device;
ALuint oss_source;
ALuint oss_buffer;
static qboolean bTracker_Initialized = false;
// Set up the renderer options
static int depth = 16; // by default 16bit, only affects output not internal 32bit processing
static int unsign = 0;
static int freq = 22050;// 22050 is enough for most music
static int n_channels = 2; // stereo action
static float trackervolume = 1.0f; // default volume...?
static float delay = 0.0f; // You shouldn't need to touch this.
static float delta; // For the speed, combination of frequency
static int bufsize;
static qboolean playing = false;// Is the music playing or not?
extern cvar_t *midivolume;
union {
short s16[2048]; // was 8192
char s8[4096]; // was twice as the thing above
} tracker_buffer;
void Tracker_Play(byte track, qboolean looping)
{
if(bTracker_Initialized == false)
return;
alGenSources((ALuint)1, &oss_source);
alSourcef(oss_source, AL_PITCH, 1);
alSourcef(oss_source, AL_GAIN, 1);
alSource3f(oss_source, AL_POSITION, 0, 0, 0);
alSource3f(oss_source, AL_VELOCITY, 0, 0, 0);
alSourcei(oss_source, AL_LOOPING, AL_FALSE);
alGenBuffers((ALuint)1, &oss_buffer);
dumb_register_stdfiles(); // Initialize loading files
// Attempt to load every format imaginable, TODO: better method?
sprintf (name, "%s/music/track%d.it", com_gamedir, track);
trackmod = dumb_load_it(name);
if (!trackmod) {
sprintf (name, "%s/music/track%d.xm", com_gamedir, track);
trackmod = dumb_load_xm(name);
if (!trackmod) {
sprintf (name, "%s/music/track%d.s3m", com_gamedir, track);
trackmod = dumb_load_s3m(name);
if (!trackmod) {
sprintf (name, "%s/music/track%d.mod", com_gamedir, track);
trackmod = dumb_load_mod(name);
if (!trackmod) {
fprintf(stderr, "Unable to open %s!\n", name);
return;
}
}
}
}
// Let us know which track you are playing
Con_Printf("Playing %s\n", name);
sr = duh_start_sigrenderer(trackmod, 0, n_channels, 0); // start rendering, action happens in Tracker_Update
if (!sr) { // If it doesn't want to render, stop it before it's too late
unload_duh(trackmod); // Unload the track safely
fprintf(stderr, "Unable to play file!\n");
return;
}
delta = 61536.0f / freq; // This affects the speed
bufsize = depth == 16 ? 2048 : 4096; // Buffer size, small buffer = laggy music; big buff = laggy game
bufsize /= n_channels; // Tell him we are hopefully stereo
playing = true; // Announce that we have a track playing
}
void Tracker_Stop(void)
{
if(bTracker_Initialized == false || playing == false)
return;
if(!trackmod || !sr)
return;
playing = false; // Not playing the song anymore to prevent Tracker_Update
Con_Printf("Stopping %s\n", name); // Just print that we are stopping whatever track
duh_end_sigrenderer(sr); // Stop the renderer safely
unload_duh(trackmod); // Unload the song!
}
void Tracker_Pause(void)
{
if(bTracker_Initialized == false)
return;
playing = false; // Prevent from Tracker_Update from happening
Con_Printf("Paused %s\n", name);
}
void Tracker_Resume(void)
{
if(bTracker_Initialized == false)
return;
// Just making sure we aren't calling Tracker_Update with no song...
if(!trackmod || !sr)
return;
playing = true; // Tracker_Update should now be triggered again
Con_Printf("Resuming %s\n", name);
}
static void Tracker_f (void)
{
char *command;
int ret;
int n;
if (Cmd_Argc() < 2)
return;
command = Cmd_Argv (1);
if (Q_strcasecmp(command, "play") == 0)
{
Tracker_Play((byte)Q_atoi(Cmd_Argv (2)), false);
return;
}
if (Q_strcasecmp(command, "stop") == 0)
{
Tracker_Stop();
return;
}
if (Q_strcasecmp(command, "frequency") == 0)
{
freq = (int)Q_atoi(Cmd_Argv (2));
return;
}
if (Q_strcasecmp(command, "pause") == 0)
{
Tracker_Pause();
return;
}
if (Q_strcasecmp(command, "resume") == 0)
{
Tracker_Resume();
return;
}
}
void Tracker_Update(void)
{
int i;
// Only update when a song is playing and the renderer works...
if (!sr)
return;
if(playing == false)
return;
if (midivolume->value != trackervolume)
trackervolume = midivolume->value;
// Render the song
int l = duh_render(sr, depth, unsign, trackervolume, delta, bufsize, &tracker_buffer);
if (depth == 16) { // On 16 bit, fill the buffer accordingly
for (i = 0; i < l * n_channels; i++) {
short val = tracker_buffer.s16[i];
tracker_buffer.s8[i*2] = (char)val;
tracker_buffer.s8[i*2+1] = (char)(val >> 8);
}
}
alBufferData(oss_buffer, AL_FORMAT_STEREO16, &tracker_buffer.s8, 4096, freq);
alSourceQueueBuffers(oss_source, 1, &oss_buffer);
alSourcePlay(oss_source);
}
int Tracker_Init(void)
{
if (COM_CheckParm("-notracker"))
return -1;
oss_device = alcOpenDevice(NULL);
if (!oss_device)
{
perror("/dev/dsp");
return 0; // just get out if there's none
}
Cmd_AddCommand ("dumb", Tracker_f); // link DUMB
bTracker_Initialized = true;
Con_Printf("DUMB Initialized\n"); // Tell them we are ready
return 1; // return that we have successfully initialised
}
void Tracker_Shutdown(void)
{
Tracker_Stop(); // First stop the track
dumb_exit(); // Kill DUMB
alcCloseDevice(oss_device);
}
#endif