problems with g_cond_wait
- From: joël krähemann <joel weedlight ch>
- To: gtk-list gnome org
- Subject: problems with g_cond_wait
- Date: Wed, 25 Nov 2009 22:22:22 +0100
Hi
I want to write a composition program and I have some problems, that my
application stays in "real time". I use g_cond_wait for
synchronization. I'm asking me if g_cond_signal is too slow for my
needs or am I doing something wrong? In the attachment is the C file
which is part of my project. You may to start at the function
ags_devout_run() that's where the threads will be started. I get some
sound when testing with the drum sequencer but it sounds as it has been
played too slow.
#include "ags_devout.h"
#include "ags_audio.h"
#include "ags_channel.h"
#include "ags_audio_signal.h"
#include "recall/ags_play_channel.h"
#include "file/ags_audio_file.h"
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <errno.h>
#include <string.h>
#include <math.h>
#include <time.h>
GType ags_devout_get_type();
void ags_devout_class_init(AgsDevoutClass *devout);
void ags_devout_init(AgsDevout *devout);
void ags_devout_destroy(GObject *gobject);
void ags_devout_device_init(AgsDevout *devout);
void ags_devout_device_free(AgsDevout *devout);
void ags_devout_ao_device_init(AgsDevout *devout);
void ags_devout_ao_device_free(AgsDevout *devout);
void ags_devout_run(AgsDevout *devout);
// void ags_devout_request(AgsDevout *devout); obsoleted by ags_devout_play_audio
void ags_devout_play_recall(AgsDevout *devout);
void ags_devout_play_audio(AgsDevout *devout);
gpointer ags_devout_play_functions(gpointer devout);
gpointer ags_devout_play(gpointer devout);
gpointer ags_devout_garbage_collector(AgsDevout *devout);
void ags_devout_stop(AgsDevout *devout);
gpointer ags_devout_ao_play(AgsDevout *devout);
void ags_devout_ao_stop(AgsDevout *devout);
GType
ags_devout_get_type (void)
{
static GType ags_type_devout = 0;
if(!ags_type_devout){
static const GTypeInfo ags_devout_info = {
sizeof (AgsDevoutClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) ags_devout_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (AgsDevout),
0, /* n_preallocs */
(GInstanceInitFunc) ags_devout_init,
};
ags_type_devout = g_type_register_static(G_TYPE_OBJECT, "AgsDevout\0", &ags_devout_info, 0);
}
return (ags_type_devout);
}
void
ags_devout_class_init(AgsDevoutClass *devout)
{
devout->run = ags_devout_run;
devout->stop = ags_devout_stop;
}
void
ags_devout_init(AgsDevout *devout)
{
devout->flags = AGS_DEVOUT_WAIT_RECALL | AGS_DEVOUT_WAIT_DEVICE;
devout->dsp_channels = 2;
devout->pcm_channels = 2;
devout->bits = 16;
devout->buffer_size = 512;
devout->frequence = 44100;
// devout->sleep.tv_sec = 0;
// devout->sleep.tv_nsec = (guint) floor(1000000000.0 / (double)devout->frequence * (double)devout->buffer_size);
devout->play_cond = g_cond_new();
devout->play_functions_cond = g_cond_new();
devout->garbage_collector_cond = g_cond_new();
devout->offset = 0;
devout->note_delay = (guint) round((double)devout->frequence / (double)devout->buffer_size * 60.0 / 120.0 / 16.0);
devout->note_counter = 0;
devout->note_offset = 0;
devout->buffer[0] = (short *) malloc(devout->dsp_channels * devout->buffer_size * sizeof(short));
devout->buffer[1] = (short *) malloc(devout->dsp_channels * devout->buffer_size * sizeof(short));
devout->buffer[2] = (short *) malloc(devout->dsp_channels * devout->buffer_size * sizeof(short));
devout->buffer[3] = (short *) malloc(devout->dsp_channels * devout->buffer_size * sizeof(short));
devout->system = AGS_DEVOUT_OSS;
devout->device = "/dev/dsp\0";
devout->garbage_collector = ags_garbage_collector_new();
devout->garbage_collector->devout = (GObject *) devout;
devout->recall = NULL;
devout->audio = NULL;
}
void
ags_devout_destroy(GObject *gobject)
{
g_object_unref (gobject);
}
void
ags_devout_device_init(AgsDevout *devout)
{
int stereo, fmt;
if((devout->out.device_fd = open ("/dev/dsp\0", O_WRONLY, 0)) == -1 &&
(devout->out.device_fd = open ("/dev/sound/dsp\0", O_WRONLY, 0)) == -1){
perror("ags_devout_device_init : open \0");
exit(1);
}
stereo = 0;
if(ioctl (devout->out.device_fd, SNDCTL_DSP_STEREO, &stereo) == -1){
/* Fatal error */
perror("ags_devout_device_init : stereo \0");
exit(1);
}
if(ioctl (devout->out.device_fd, SNDCTL_DSP_RESET, 0)){
perror("ags_devout_device_init : reset \0");
exit(1);
}
fmt = AFMT_S16_LE; // CPU_IS_BIG_ENDIAN ? AFMT_S16_BE : AFMT_S16_LE ;
if(ioctl (devout->out.device_fd, SOUND_PCM_SETFMT, &fmt) != 0){
perror("ags_devout_device_init : set format \0");
exit(1);
}
if(ioctl (devout->out.device_fd, SOUND_PCM_WRITE_CHANNELS, &(devout->pcm_channels)) != 0){
perror("ags_devout_device_init : channels \0");
exit(1);
}
if(ioctl (devout->out.device_fd, SOUND_PCM_WRITE_RATE, &(devout->frequence)) != 0){
perror ("ags_devout_device_init : sample rate \0") ;
exit(1);
}
if(ioctl (devout->out.device_fd, SNDCTL_DSP_SYNC, 0) != 0){
perror("ags_devout_device_init : sync \0") ;
exit(1);
}
}
void
ags_devout_device_free(AgsDevout *devout)
{
if(ioctl (AGS_DEVOUT(devout)->out.device_fd, SNDCTL_DSP_POST, 0) == -1)
perror ("ioctl (SNDCTL_DSP_POST) \0") ;
if(ioctl (devout->out.device_fd, SNDCTL_DSP_SYNC, 0) == -1)
perror ("ioctl (SNDCTL_DSP_SYNC) \0") ;
close(devout->out.device_fd);
}
void
ags_devout_ao_device_init(AgsDevout *devout)
{
ao_sample_format *format;
ao_initialize();
devout->out.ao.driver_ao = ao_default_driver_id();
format = &(devout->out.ao.format);
format->bits = 16;
format->channels = 2;
format->rate = 44100;
format->byte_format = AO_FMT_LITTLE;
devout->out.ao.device = ao_open_live(devout->out.ao.driver_ao, format, NULL /* no options */);
if(devout->out.ao.device == NULL){
fprintf(stderr, "Error opening device.\n\0");
exit(1);
}
}
void
ags_devout_ao_device_free(AgsDevout *devout)
{
ao_close(devout->out.ao.device);
ao_shutdown();
}
void
ags_devout_play_recall(AgsDevout *devout)
{
AgsRecall *recall;
GList *list, *list_next;
guint whence;
GStaticMutex mutex = G_STATIC_MUTEX_INIT;
devout->flags |= AGS_DEVOUT_PLAYING_RECALL;
whence = 0;
ags_devout_play_recall0:
list = devout->recall;
if(list == NULL){
devout->flags &= (~AGS_DEVOUT_PLAY_RECALL);
AGS_DEVOUT_GET_CLASS(devout)->stop(devout);
}
while(list != NULL){
recall = AGS_RECALL(list->data);
list_next = list->next;
if((AGS_RECALL_CANCEL & (recall->flags)) != 0){
g_static_mutex_lock(&mutex);
devout->play_recall_ref--;
devout->recall = g_list_remove(devout->recall, recall);
g_static_mutex_unlock(&mutex);
g_signal_emit_by_name((GObject *) recall, "cancel\0");
}else if((AGS_RECALL_REMOVE & (recall->flags)) != 0){
g_static_mutex_lock(&mutex);
devout->play_recall_ref--;
devout->recall = g_list_remove(devout->recall, recall);
g_static_mutex_unlock(&mutex);
g_signal_emit_by_name((GObject *) recall, "stop\0");
}else{
if(whence == 0){
g_signal_emit_by_name((GObject *) recall, "run_pre\0");
}else if(whence == 1){
g_signal_emit_by_name((GObject *) recall, "run_inter\0");
}else{
g_signal_emit_by_name((GObject *) recall, "run_post\0");
}
}
list = list_next;
}
if(whence == 0){
whence = 1;
goto ags_devout_play_recall0;
}else if(whence == 1){
whence = 2;
goto ags_devout_play_recall0;
}
devout->flags &= (~AGS_DEVOUT_PLAYING_RECALL);
}
void
ags_devout_play_audio(AgsDevout *devout)
{
AgsAudio *audio;
AgsChannel *channel;
GList *list_audio, *list_next_audio;
guint whence;
gboolean cancel;
GStaticMutex mutex = G_STATIC_MUTEX_INIT;
void ags_devout_play_audio_play(AgsChannel *channel){
AgsRecall *recall;
GList *list_play, *list_next_play;
list_play = channel->play;
while(list_play != NULL){
list_next_play = list_play->next;
recall = AGS_RECALL(list_play->data);
if((AGS_RECALL_HIDE & recall->flags) == 0){
if((AGS_RECALL_CANCEL & (recall->flags)) != 0 || cancel){
g_signal_emit_by_name((GObject *) recall, "cancel\0");
}else if((AGS_RECALL_REMOVE & (recall->flags)) != 0){
channel->play = g_list_remove(channel->play, recall);
g_signal_emit_by_name((GObject *) recall, "stop\0");
}else{
if(whence == 0)
g_signal_emit_by_name((GObject *) recall, "run_pre\0");
else if(whence == 1)
g_signal_emit_by_name((GObject *) recall, "run_inter\0");
else
g_signal_emit_by_name((GObject *) recall, "run_post\0");
}
}
list_play = list_next_play;
}
}
void ags_devout_play_audio_recall(AgsChannel *channel){
AgsRecall *recall;
GList *list_recall, *list_next_recall;
list_recall = channel->recall;
while(list_recall != NULL){
list_next_recall = list_recall->next;
recall = AGS_RECALL(list_recall->data);
if((AGS_RECALL_HIDE & recall->flags) == 0){
if((AGS_RECALL_CANCEL & (recall->flags)) != 0 || cancel){
g_signal_emit_by_name((GObject *) recall, "cancel\0");
}else if((AGS_RECALL_REMOVE & (recall->flags)) != 0){
channel->play = g_list_remove(channel->play, recall);
g_signal_emit_by_name((GObject *) recall, "stop\0");
}else{
if(whence == 0)
g_signal_emit_by_name((GObject *) recall, "run_pre\0");
else if(whence == 1)
g_signal_emit_by_name((GObject *) recall, "run_inter\0");
else
g_signal_emit_by_name((GObject *) recall, "run_post\0");
}
}
list_recall = list_next_recall;
}
}
void ags_devout_play_audio_audio_recall(AgsAudio *audio){
AgsRecall *recall;
GList *list_recall, *list_next_recall;
list_recall = audio->recall;
while(list_recall != NULL){
list_next_recall = list_recall->next;
recall = AGS_RECALL(list_recall->data);
if((AGS_RECALL_HIDE & recall->flags) == 0){
if((AGS_RECALL_CANCEL & (recall->flags)) != 0 || cancel){
g_signal_emit_by_name((GObject *) recall, "cancel\0");
}else if((AGS_RECALL_REMOVE & (recall->flags)) != 0){
audio->recall = g_list_remove(audio->recall, recall);
g_signal_emit_by_name((GObject *) recall, "stop\0");
}else{
if(whence == 0)
g_signal_emit_by_name((GObject *) recall, "run_pre\0");
else if(whence == 1)
g_signal_emit_by_name((GObject *) recall, "run_inter\0");
else
g_signal_emit_by_name((GObject *) recall, "run_post\0");
}
}
list_recall = list_next_recall;
}
}
void ags_devout_play_audio_recursive_recall(AgsChannel *output){
AgsAudio *audio;
AgsChannel *current, *input;
audio = AGS_AUDIO(output->audio);
if((AGS_AUDIO_SYNC & (audio->flags)) != 0){
if((AGS_AUDIO_ASYNC & (audio->flags)) != 0){
if(((AGS_CHANNEL_PRE_SYNC_ASYNC_DONE & (output->flags)) == 0 && whence == 0) ||
((AGS_CHANNEL_INTER_SYNC_ASYNC_DONE & (output->flags)) == 0 && whence == 1) ||
((AGS_CHANNEL_POST_SYNC_ASYNC_DONE & (output->flags)) == 0 && whence == 2)){
input = ags_channel_nth(audio->input, output->audio_channel);
while(input != NULL){
if(input->link != NULL)
ags_devout_play_audio_recursive_recall(input->link);
ags_devout_play_audio_recall(input);
input = input->next_pad;
}
current = output->next_pad;
while(current != NULL){
if(whence == 0)
current->flags |= AGS_CHANNEL_PRE_SYNC_ASYNC_DONE;
else if(whence == 1)
current->flags |= AGS_CHANNEL_INTER_SYNC_ASYNC_DONE;
else
current->flags |= AGS_CHANNEL_POST_SYNC_ASYNC_DONE;
current = current->next_pad;
}
current = output->prev_pad;
while(current != NULL){
if(whence == 0)
current->flags |= AGS_CHANNEL_PRE_SYNC_ASYNC_DONE;
else if(whence == 1)
current->flags |= AGS_CHANNEL_INTER_SYNC_ASYNC_DONE;
else
current->flags |= AGS_CHANNEL_POST_SYNC_ASYNC_DONE;
current = current->prev_pad;
}
}else{
if(whence == 0)
output->flags &= (~AGS_CHANNEL_PRE_SYNC_ASYNC_DONE);
else if(whence == 1)
output->flags &= (~AGS_CHANNEL_INTER_SYNC_ASYNC_DONE);
else
output->flags &= (~AGS_CHANNEL_POST_SYNC_ASYNC_DONE);
}
}else{
input = ags_channel_nth(audio->input, output->line);
if(input->link != NULL)
ags_devout_play_audio_recursive_recall(input->link);
ags_devout_play_audio_recall(input);
}
}else{
input = ags_channel_nth(audio->input, output->audio_channel);
while(input != NULL){
if(input->link != NULL)
ags_devout_play_audio_recursive_recall(input->link);
ags_devout_play_audio_recall(input);
input = input->next_pad;
}
}
/* call AgsAudio */
if((AGS_CHANNEL_AUDIO_DONE & (output->flags)) == 0){
ags_devout_play_audio_audio_recall(audio);
current = output->prev;
while(current != NULL){
current->flags |= AGS_CHANNEL_AUDIO_DONE;
current = current->prev;
}
current = output->next;
while(current != NULL){
current->flags |= AGS_CHANNEL_AUDIO_DONE;
current = current->next;
}
}else
output->flags &= (~AGS_CHANNEL_AUDIO_DONE);
/* call output*/
ags_devout_play_audio_recall(output);
}
void ags_devout_play_audio_recursive_play(AgsChannel *output){
AgsAudio *audio;
AgsChannel *current, *input;
audio = AGS_AUDIO(output->audio);
if((AGS_AUDIO_SYNC & (audio->flags)) != 0){
if((AGS_AUDIO_ASYNC & (audio->flags)) != 0){
if(((AGS_CHANNEL_PRE_SYNC_ASYNC_DONE & (output->flags)) == 0 && whence == 0) ||
((AGS_CHANNEL_INTER_SYNC_ASYNC_DONE & (output->flags)) == 0 && whence == 1) ||
((AGS_CHANNEL_POST_SYNC_ASYNC_DONE & (output->flags)) == 0 && whence == 2)){
input = ags_channel_nth(audio->input, output->audio_channel);
if((AGS_AUDIO_OUTPUT_HAS_RECYCLING & (audio->flags)) != 0){
/* AgsInput recursive AgsRecall */
while(input != NULL){
if(input->link != NULL)
ags_devout_play_audio_recursive_recall(input->link);
ags_devout_play_audio_recall(input);
input = input->next_pad;
}
}else{
/* !AGS_AUDIO_OUTPUT_HAS_RECYCLING */
while(input != NULL){
if(input->link != NULL)
ags_devout_play_audio_recursive_play(input->link);
ags_devout_play_audio_play(input);
input = input->next_pad;
}
}
current = output->next_pad;
while(current != NULL){
if(whence == 0)
current->flags |= AGS_CHANNEL_PRE_SYNC_ASYNC_DONE;
else if(whence == 1)
current->flags |= AGS_CHANNEL_INTER_SYNC_ASYNC_DONE;
else
current->flags |= AGS_CHANNEL_POST_SYNC_ASYNC_DONE;
current = current->next_pad;
}
current = output->prev_pad;
while(current != NULL){
if(whence == 0)
current->flags |= AGS_CHANNEL_PRE_SYNC_ASYNC_DONE;
else if(whence == 1)
current->flags |= AGS_CHANNEL_INTER_SYNC_ASYNC_DONE;
else
current->flags |= AGS_CHANNEL_POST_SYNC_ASYNC_DONE;
current = current->prev_pad;
}
}else{
if(whence == 0)
output->flags &= (~AGS_CHANNEL_PRE_SYNC_ASYNC_DONE);
else if(whence == 1)
output->flags &= (~AGS_CHANNEL_INTER_SYNC_ASYNC_DONE);
else
output->flags &= (~AGS_CHANNEL_POST_SYNC_ASYNC_DONE);
}
}else{
input = ags_channel_nth(audio->input, output->line);
if((AGS_AUDIO_OUTPUT_HAS_RECYCLING & (audio->flags)) != 0){
if(input->link != NULL)
ags_devout_play_audio_recursive_recall(input->link);
ags_devout_play_audio_recall(input);
}else{
if(input->link != NULL)
ags_devout_play_audio_recursive_play(input->link);
ags_devout_play_audio_play(input);
}
}
}else{
input = ags_channel_nth(audio->input, output->audio_channel);
if((AGS_AUDIO_OUTPUT_HAS_RECYCLING & (audio->flags)) != 0){
while(input != NULL){
if(input->link != NULL)
ags_devout_play_audio_recursive_recall(input->link);
ags_devout_play_audio_recall(input);
input = input->next_pad;
}
}else{
while(input != NULL){
if(input->link != NULL)
ags_devout_play_audio_recursive_play(input->link);
ags_devout_play_audio_play(input);
input = input->next_pad;
}
}
}
/* call AgsAudio */
if((AGS_CHANNEL_AUDIO_DONE & (output->flags)) == 0){
if(whence != 2)
ags_devout_play_audio_audio_recall(audio);
current = output->prev;
while(current != NULL){
current->flags |= AGS_CHANNEL_AUDIO_DONE;
current = current->prev;
}
current = output->next;
while(current != NULL){
current->flags |= AGS_CHANNEL_AUDIO_DONE;
current = current->next;
}
}else
output->flags &= (~AGS_CHANNEL_AUDIO_DONE);
/* call output */
ags_devout_play_audio_play(output);
}
devout->flags |= AGS_DEVOUT_PLAYING_AUDIO;
/* run_pre */
list_audio = devout->audio;
if(list_audio == NULL){
AGS_DEVOUT_GET_CLASS(devout)->stop(devout);
devout->flags &= (~AGS_DEVOUT_PLAY_AUDIO);
}
whence = 0;
while(list_audio != NULL){
if(list_audio->data == NULL){
list_audio = list_audio->next;
continue;
}
audio = AGS_AUDIO(list_audio->data);
list_next_audio = list_audio->next;
if((AGS_AUDIO_DEVOUT_PLAY_CANCEL & (audio->flags)) != 0){
devout->audio = g_list_remove(devout->audio, audio);
cancel = TRUE;
}else
cancel = FALSE;
channel = audio->output;
while(channel != NULL){
ags_devout_play_audio_recursive_play(channel);
channel = channel->next;
}
list_audio = list_next_audio;
}
/* run_inter */
list_audio = devout->audio;
whence = 1;
while(list_audio != NULL){
if(list_audio->data == NULL){
list_audio = list_audio->next;
continue;
}
audio = AGS_AUDIO(list_audio->data);
list_next_audio = list_audio->next;
if((AGS_AUDIO_DEVOUT_PLAY_CANCEL & (audio->flags)) != 0){
devout->audio = g_list_remove(devout->audio, audio);
cancel = TRUE;
}else
cancel = FALSE;
channel = audio->output;
while(channel != NULL){
ags_devout_play_audio_recursive_play(channel);
channel = channel->next;
}
list_audio = list_next_audio;
}
/* run_post */
list_audio = devout->audio;
whence = 2;
while(list_audio != NULL){
if(list_audio->data == NULL){
list_audio = list_audio->next;
continue;
}
audio = AGS_AUDIO(list_audio->data);
list_next_audio = list_audio->next;
if((AGS_AUDIO_DEVOUT_PLAY_CANCEL & (audio->flags)) != 0){
devout->audio = g_list_remove(devout->audio, audio);
cancel = TRUE;
}else
cancel = FALSE;
channel = audio->output;
while(channel != NULL){
ags_devout_play_audio_recursive_play(channel);
channel = channel->next;
}
if((AGS_AUDIO_DEVOUT_PLAY_REMOVE & (audio->flags)) != 0){
g_static_mutex_lock(&mutex);
devout->play_audio_ref--;
devout->audio = g_list_remove(devout->audio, audio);
g_static_mutex_unlock(&mutex);
}
list_audio = list_next_audio;
}
devout->flags &= (~AGS_DEVOUT_PLAYING_AUDIO);
}
void
ags_devout_run(AgsDevout *devout)
{
GList *stream;
guint i;
if((AGS_DEVOUT_PLAY & devout->flags) != 0){
fprintf(stdout, "ags_devout_run: allready playing\n\0");
return;
}
if((AGS_DEVOUT_LIBAO & devout->flags) != 0)
ags_devout_ao_device_init(devout);
else
ags_devout_device_init(devout);
memset(devout->buffer[0], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
memset(devout->buffer[1], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
memset(devout->buffer[2], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
memset(devout->buffer[3], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
devout->flags |= (AGS_DEVOUT_BUFFER0 | AGS_DEVOUT_PLAY | AGS_DEVOUT_WAIT_DEVICE | AGS_DEVOUT_WAIT_RECALL);
if((AGS_DEVOUT_LIBAO & devout->flags) != 0)
devout->play_thread = g_thread_create(ags_devout_ao_play, devout, FALSE, NULL);
else
devout->play_thread = g_thread_create(ags_devout_play, devout, FALSE, NULL);
devout->play_functions_thread = g_thread_create(ags_devout_play_functions, devout, FALSE, NULL);
}
gpointer
ags_devout_play_functions(gpointer devout0)
{
AgsDevout *devout = devout0;
// static struct timespec ts;
GStaticMutex mutex = G_STATIC_MUTEX_INIT;
void ags_devout_play_functions_timing(){
while((AGS_DEVOUT_WAIT_DEVICE & devout->flags) != 0){
g_cond_wait(devout->play_functions_cond,
g_static_mutex_get_mutex(&mutex));
// nanosleep(&ts, NULL);
}
devout->flags |= AGS_DEVOUT_WAIT_RECALL;
devout->flags |= AGS_DEVOUT_WAIT_DEVICE;
g_static_mutex_unlock(&mutex);
}
fprintf(stdout, "ags_devout_play_functions: start\n\0");
// ts.tv_sec = 0;
// ts.tv_nsec = 100;
while((AGS_DEVOUT_PLAY & devout->flags) != 0){
if((AGS_DEVOUT_PLAY_RECALL & devout->flags) != 0){
ags_devout_play_recall(devout);
if(devout->play_recall_ref == 0){
devout->flags &= (~AGS_DEVOUT_PLAY_RECALL);
AGS_DEVOUT_GET_CLASS(devout)->stop(devout);
fprintf(stdout, "devout->play_recall_ref == 0\n\0");
}
}
if((AGS_DEVOUT_PLAY_AUDIO & devout->flags) != 0){
ags_devout_play_audio(devout);
if(devout->play_audio_ref == 0){
devout->flags &= (~AGS_DEVOUT_PLAY_AUDIO);
AGS_DEVOUT_GET_CLASS(devout)->stop(devout);
fprintf(stdout, "devout->play_audio_ref == 0\n\0");
}
}
g_static_mutex_lock(&mutex);
devout->flags &= (~AGS_DEVOUT_WAIT_RECALL);
if((AGS_DEVOUT_WAIT_DEVICE & devout->flags) != 0){
ags_devout_play_functions_timing();
}else{
g_cond_signal(devout->play_cond);
g_static_mutex_unlock(&mutex);
}
}
return(NULL);
}
gpointer
ags_devout_play(gpointer devout0)
{
AgsDevout *devout = devout0;
// struct timespec ts;
GStaticMutex mutex = G_STATIC_MUTEX_INIT;
void ags_devout_play_timing(){
while((AGS_DEVOUT_WAIT_RECALL & devout->flags) != 0){
g_cond_wait(devout->play_functions_cond,
g_static_mutex_get_mutex(&mutex));
// nanosleep(&ts, NULL);
}
devout->flags |= AGS_DEVOUT_WAIT_RECALL;
devout->flags |= AGS_DEVOUT_WAIT_DEVICE;
g_static_mutex_unlock(&mutex);
}
// ts.tv_sec = 0;
// ts.tv_nsec = 100;
while((AGS_DEVOUT_PLAY & devout->flags) != 0){
if((AGS_DEVOUT_BUFFER0 & devout->flags) != 0){
memset(devout->buffer[3], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
write(devout->out.device_fd, devout->buffer[0], devout->buffer_size * sizeof(short));
g_static_mutex_lock(&mutex);
devout->flags &= (~AGS_DEVOUT_BUFFER0);
devout->flags |= AGS_DEVOUT_BUFFER1;
g_static_mutex_unlock(&mutex);
}else if((AGS_DEVOUT_BUFFER1 & devout->flags) != 0){
memset(devout->buffer[0], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
write(devout->out.device_fd, devout->buffer[1], devout->buffer_size * sizeof(short));
g_static_mutex_lock(&mutex);
devout->flags &= (~AGS_DEVOUT_BUFFER1);
devout->flags |= AGS_DEVOUT_BUFFER2;
g_static_mutex_unlock(&mutex);
}else if((AGS_DEVOUT_BUFFER2 & devout->flags) != 0){
memset(devout->buffer[1], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
write(devout->out.device_fd, devout->buffer[2], devout->buffer_size * sizeof(short));
g_static_mutex_lock(&mutex);
devout->flags &= (~AGS_DEVOUT_BUFFER2);
devout->flags |= AGS_DEVOUT_BUFFER3;
g_static_mutex_unlock(&mutex);
}else if((AGS_DEVOUT_BUFFER3 & devout->flags) != 0){
memset(devout->buffer[2], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
write(devout->out.device_fd, devout->buffer[3], devout->buffer_size * sizeof(short));
g_static_mutex_lock(&mutex);
devout->flags &= (~AGS_DEVOUT_BUFFER3);
devout->flags |= AGS_DEVOUT_BUFFER0;
g_static_mutex_unlock(&mutex);
}
if((AGS_DEVOUT_COUNT & devout->flags) != 0)
devout->offset++;
g_static_mutex_lock(&mutex);
devout->flags &= (~AGS_DEVOUT_WAIT_DEVICE);
if((AGS_DEVOUT_WAIT_RECALL & devout->flags) != 0){
ags_devout_play_timing();
}else{
g_cond_signal(devout->play_functions_cond);
g_static_mutex_unlock(&mutex);
}
}
if((AGS_DEVOUT_BUFFER0 & devout->flags) != 0){
memset(devout->buffer[3], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
write(devout->out.device_fd, devout->buffer[0], devout->buffer_size * sizeof(short));
devout->flags &= (~AGS_DEVOUT_BUFFER0);
}else if((AGS_DEVOUT_BUFFER1 & devout->flags) != 0){
memset(devout->buffer[0], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
write(devout->out.device_fd, devout->buffer[1], devout->buffer_size * sizeof(short));
devout->flags &= (~AGS_DEVOUT_BUFFER1);
}else if((AGS_DEVOUT_BUFFER2 & devout->flags) != 0){
memset(devout->buffer[1], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
write(devout->out.device_fd, devout->buffer[2], devout->buffer_size * sizeof(short));
devout->flags &= (~AGS_DEVOUT_BUFFER2);
}else if((AGS_DEVOUT_BUFFER3 & devout->flags) != 0){
memset(devout->buffer[2], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
write(devout->out.device_fd, devout->buffer[3], devout->buffer_size * sizeof(short));
devout->flags &= (~AGS_DEVOUT_BUFFER3);
}
// fprintf(stdout, "ags_devout_play: end\n\0");
ags_devout_device_free(devout);
return(NULL);
}
gpointer
ags_devout_garbage_collector(AgsDevout *devout)
{
return(NULL);
}
void
ags_devout_stop(AgsDevout *devout)
{
// fprintf(stdout, "ags_devout_stop:\n\0");
if((AGS_DEVOUT_PLAY_RECALL & devout->flags) == 0 && (AGS_DEVOUT_PLAY_AUDIO & devout->flags) == 0)
devout->flags &= (~AGS_DEVOUT_PLAY);
}
gpointer
ags_devout_ao_play(AgsDevout *devout)
{
// struct timespec ts;
GStaticMutex mutex = G_STATIC_MUTEX_INIT;
void ags_devout_ao_play_timing(){
while((AGS_DEVOUT_WAIT_RECALL & devout->flags) != 0){
g_cond_wait(devout->play_cond,
g_static_mutex_get_mutex(&mutex));
// nanosleep(&ts, NULL);
}
devout->flags |= AGS_DEVOUT_WAIT_RECALL;
g_static_mutex_unlock(&mutex);
}
// ts.tv_sec = 0;
// ts.tv_nsec = 100;
// fprintf(stdout, "ags_devout_play: start\n\0");
while((AGS_DEVOUT_PLAY & devout->flags) != 0){
// fprintf(stdout, "ags_devout_play:\n loop\n\0");
if((AGS_DEVOUT_BUFFER0 & devout->flags) != 0){
memset(devout->buffer[3], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
ao_play(devout->out.ao.device, devout->buffer[0], devout->buffer_size * sizeof(short));
g_static_mutex_lock(&mutex);
devout->flags &= (~AGS_DEVOUT_BUFFER0);
devout->flags |= AGS_DEVOUT_BUFFER1;
g_static_mutex_unlock(&mutex);
}else if((AGS_DEVOUT_BUFFER1 & devout->flags) != 0){
memset(devout->buffer[0], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
ao_play(devout->out.ao.device, devout->buffer[1], devout->buffer_size * sizeof(short));
g_static_mutex_lock(&mutex);
devout->flags &= (~AGS_DEVOUT_BUFFER1);
devout->flags |= AGS_DEVOUT_BUFFER2;
g_static_mutex_unlock(&mutex);
}else if((AGS_DEVOUT_BUFFER2 & devout->flags) != 0){
memset(devout->buffer[1], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
ao_play(devout->out.ao.device, devout->buffer[2], devout->buffer_size * sizeof(short));
g_static_mutex_lock(&mutex);
devout->flags &= (~AGS_DEVOUT_BUFFER2);
devout->flags |= AGS_DEVOUT_BUFFER3;
g_static_mutex_unlock(&mutex);
}else if((AGS_DEVOUT_BUFFER3 & devout->flags) != 0){
memset(devout->buffer[2], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
ao_play(devout->out.ao.device, devout->buffer[3], devout->buffer_size * sizeof(short));
g_static_mutex_lock(&mutex);
devout->flags &= (~AGS_DEVOUT_BUFFER3);
devout->flags |= AGS_DEVOUT_BUFFER0;
g_static_mutex_unlock(&mutex);
}
if((AGS_DEVOUT_COUNT & devout->flags) != 0)
devout->offset++;
g_static_mutex_lock(&mutex);
devout->flags &= (~AGS_DEVOUT_WAIT_DEVICE);
if((AGS_DEVOUT_WAIT_RECALL & devout->flags) != 0){
ags_devout_ao_play_timing();
}else{
g_cond_signal(devout->play_functions_cond);
g_static_mutex_unlock(&mutex);
}
}
if((AGS_DEVOUT_BUFFER0 & devout->flags) != 0){
memset(devout->buffer[3], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
ao_play(devout->out.ao.device, devout->buffer[0], devout->buffer_size * sizeof(short));
devout->flags &= (~AGS_DEVOUT_BUFFER0);
}else if((AGS_DEVOUT_BUFFER1 & devout->flags) != 0){
memset(devout->buffer[0], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
ao_play(devout->out.ao.device, devout->buffer[1], devout->buffer_size * sizeof(short));
devout->flags &= (~AGS_DEVOUT_BUFFER1);
}else if((AGS_DEVOUT_BUFFER2 & devout->flags) != 0){
memset(devout->buffer[1], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
ao_play(devout->out.ao.device, devout->buffer[2], devout->buffer_size * sizeof(short));
devout->flags &= (~AGS_DEVOUT_BUFFER2);
}else if((AGS_DEVOUT_BUFFER3 & devout->flags) != 0){
memset(devout->buffer[2], 0, devout->dsp_channels * devout->buffer_size * sizeof(short));
ao_play(devout->out.ao.device, devout->buffer[3], devout->buffer_size * sizeof(short));
devout->flags &= (~AGS_DEVOUT_BUFFER3);
}
fprintf(stdout, "ags_devout_play: end\n\0");
ags_devout_ao_device_free(devout);
return(NULL);
}
void
ags_devout_ao_stop(AgsDevout *devout)
{
if((AGS_DEVOUT_PLAY_RECALL & devout->flags) == 0 && (AGS_DEVOUT_PLAY_AUDIO & devout->flags) == 0)
devout->flags &= (~AGS_DEVOUT_PLAY);
}
AgsDevout*
ags_devout_new()
{
AgsDevout *devout;
devout = (AgsDevout *) g_object_new(AGS_TYPE_DEVOUT, NULL);
return(devout);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]