#include "TexFont.h"
#include "fbn.h"
#include <pthread.h>
int fbnSoundSupported = 1;
pthread_mutex_t dsp_mutex;
int fbnSoundInit(){
int format = FBN_SND_FORMAT;
int stereo = FBN_SND_STEREO;
int speed = FBN_SND_SPEED;
if ((audio_fd = open("/dev/dsp", O_WRONLY)) == -1){
perror("/dev/dsp");
fbnSoundSupported = 0;
}
if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1){
perror("SNDCTL_DSP_SETFMT");
fbnSoundSupported = 0;
}
if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1){
perror("SNDCTL_DSP_STEREO");
fbnSoundSupported = 0;
}
if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1){
perror("SNDCTL_DSP_SPEED");
fbnSoundSupported = 0;
}
if(fbnSoundSupported)
pthread_mutex_init(&dsp_mutex, NULL);
return(fbnSoundSupported);
}
void fbnSoundFini(){
if(fbnSoundSupported){
pthread_mutex_lock(&dsp_mutex);
if(close(audio_fd) == -1){
debug("ignoring fbnSoundStop failure\n");
}
pthread_mutex_destroy(&dsp_mutex);
}
}
void fbnSoundLoadData(SoundSet *soundset){
int i;
FILE *file;
for(i=0;i<soundset->numsounds;i++){
soundset->sounds[i].data_length =
fbnSizeofFile(soundset->sounds[i].sound_file);
if( soundset->sounds[i].data_length <= 0){
debug("fbnSoundLoadData problem loading sound %d out of %d\n", i, MAX_SOUNDS);
exit(1);
}
soundset->sounds[i].data = (void *)malloc(soundset->sounds[i].data_length);
if(soundset->sounds[i].data == NULL){
debug("fbnSoundLoadData failed to malloc memory\n");
exit(1);
}
file = fopen(soundset->sounds[i].sound_file, "r");
if(soundset->sounds[i].data == NULL){
debug("fbnSoundLoadData failed to open sound datafile\n");
exit(1);
}
fread(soundset->sounds[i].data, 1, soundset->sounds[i].data_length, file);
}
}
void fbnSoundUnloadData(SoundSet *soundset){
int i;
pthread_mutex_lock(&dsp_mutex);
for(i=0;i<MAX_SOUNDS;i++){
free(soundset->sounds[i].data);
soundset->sounds[i].data = NULL;
}
pthread_mutex_unlock(&dsp_mutex);
}
void fbnSoundPlay(int sound_id, SoundSet *soundset){
pthread_t thread;
int len;
if(!fbnSoundSupported) return;
pthread_create(&thread, NULL,
(void*)&fbnSoundPlay_subthread,
(void*)&(soundset->sounds[sound_id]));
}
void fbnSoundPlay_subthread(void *ptr){
Sound *snd;
int len;
snd = (Sound *)ptr;
pthread_mutex_lock(&dsp_mutex);
len = write(audio_fd, snd->data, snd->data_length);
pthread_mutex_unlock(&dsp_mutex);
if(len == -1){
debug("fbnSoundPlay problem\n");
exit(1);
}
}
void fbnSoundWait(void){
if(fbnSoundSupported){
pthread_mutex_lock(&dsp_mutex);
pthread_mutex_unlock(&dsp_mutex);
}
}
int fbnSizeofFile(const char *filename){
struct stat thing;
if(stat(filename, &thing) == -1){
debug("bnSizeofFile %s failed\n", filename);
exit(1);
} else {
return(thing.st_size);
}
}
void fbnTxfGLStateSet(void){
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, 100.0, 0.0, 100.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glAlphaFunc(GL_GEQUAL, 0.0625);
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0, -3);
}
void fbnTxfGLStateUnset(void){
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glDisable(GL_POLYGON_OFFSET_FILL);
glEnable(GL_LIGHTING);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
void fbnTxfRenderString(char *screen_string, char *maxstring,
float x, float y, float w, float h,
float r, float g, float b, float a,
TexFont *our_txf)
{
int width, ascent, descent;
float txf_scale_factor;
if(!maxstring) maxstring = screen_string;
txfBindFontTexture(our_txf);
txfGetStringMetrics(our_txf, maxstring, strlen(maxstring),
&width, &ascent, &descent);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if(getenv("FBN_TXF_DEBUG")){
// debug, show a black background rectangle
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glBegin(GL_TRIANGLE_STRIP);
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
glVertex3f(x - w / 2.0f, y + h / 2.0f, 0.0f);
glVertex3f(x + w / 2.0f, y + h / 2.0f, 0.0f);
glVertex3f(x - w / 2.0f, y - h / 2.0f, 0.0f);
glVertex3f(x + w / 2.0f, y - h / 2.0f, 0.0f);
glEnd();
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
} // end debug
glTranslatef(x - w / 2.0f, y - h / 2.0f, 0.0f);
glScalef(w / width, h / ascent, 1.0f);
glColor4f(r, g, b, a);
txfRenderString(our_txf, screen_string, strlen(screen_string));
}
void fbnTxfRenderStringExtruded(char *string, char *maxstring,
float center_x, float center_y,
float width, float height,
float extrude_x, float extrude_y,
int steps,
float fg_r,
float fg_g,
float fg_b,
float fg_a,
float bg_r,
float bg_g,
float bg_b,
float bg_a,
TexFont *txf){
int i;
float effect_delta_x;
float effect_delta_y;
float effect_delta_r;
float effect_delta_g;
float effect_delta_b;
float effect_delta_a;
effect_delta_x = extrude_x / (float)steps;
effect_delta_y = extrude_y / (float)steps;
effect_delta_r = (fg_r - bg_r) / (float)steps;
effect_delta_g = (fg_g - bg_g) / (float)steps;
effect_delta_b = (fg_b - bg_b) / (float)steps;
effect_delta_a = (fg_a - bg_a) / (float)steps;
glDisable(GL_DEPTH_TEST);
for(i=0; i<steps; i++)
fbnTxfRenderString(string, maxstring,
center_x + i * effect_delta_x,
center_y + i * effect_delta_y,
width, height,
bg_r + i * effect_delta_r,
bg_g + i * effect_delta_g,
bg_b + i * effect_delta_b,
bg_a + i * effect_delta_a,
txf);
glEnable(GL_DEPTH_TEST);
}
void fbnSetPlaceString(char *placestring, int place){
switch(place % 100){
case 11:
case 12:
case 13:
sprintf(placestring, "%dth", place);
break;
default:
switch(place % 10){
case 1:
sprintf(placestring, "%dst", place);
break;
case 2:
sprintf(placestring, "%dnd", place);
break;
case 3:
sprintf(placestring, "%drd", place);
break;
default:
sprintf(placestring, "%dth", place);
break;
}
break;
}
}