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); }
_______________________________________________ gtk-list mailing list gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list