#include "stdafx.h" #include "common.h" #include #include #include #include #include "sabbu.h" #include "sound.h" #include "sound_out.h" #define BUFFER_SIZE 32 unsigned char audio_buffer[BUFFER_SIZE]; int audio_fd = -1; int m_channels = -1; int m_samplerate = -1; int m_bytes_written = 0; gboolean sound_playing = FALSE; GMutex *sound_playing_mutex = NULL; gboolean stop_sound = FALSE; GMutex *stop_sound_mutex = NULL; gboolean progress_thread_running = FALSE; GMutex *progress_thread_mutex = NULL; USER_CALLBACK m_userCallback = NULL; void soundserver_fill(struct sound_play_data *data); void mySoundProc(void *pSoundBuffer,long bufferLen); void soundserver_close(void); int soundserver_open(USER_CALLBACK pUserCallback, int channels, int samplerate) { if(audio_fd != -1) { close(audio_fd); audio_fd = -1; } if((audio_fd = open("/dev/dsp", O_WRONLY, 0)) == -1) { perror("could not open /dev/dsp"); return 0; } int format = AFMT_S16_LE; if(ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format) == -1) { perror("could not set format on /dev/dsp to signed 16 bit"); return 0; } if(format != AFMT_S16_LE) { perror("soundcard doesn't support signed 16 bit format"); return 0; } int channels_set = channels; if(ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels_set) == -1) { perror("could not set number of channels on /dev/dsp"); return 0; } if(channels_set != channels) { perror("soundcard doesn't support the requested number of channels"); return 0; } int speed = samplerate; if(ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed) == -1) { perror("could not set samplerate"); return 0; } if(speed != samplerate) { perror("soundcard doesn't support requested samplerate"); return 0; } m_userCallback = pUserCallback; m_channels = channels; m_samplerate = samplerate; return 1; } void soundserver_progress(struct sound_play_data *play_info) { int rv, bytes_left; while(TRUE) { g_mutex_lock(stop_sound_mutex); if(stop_sound) { g_mutex_unlock(stop_sound_mutex); g_mutex_lock(progress_thread_mutex); progress_thread_running = FALSE; g_mutex_unlock(progress_thread_mutex); sound_signal_pos_change(-1); break; } g_mutex_unlock(stop_sound_mutex); g_mutex_lock(sound_playing_mutex); if(!sound_playing_mutex || audio_fd == -1) { g_mutex_unlock(sound_playing_mutex); g_mutex_lock(progress_thread_mutex); progress_thread_running = FALSE; g_mutex_unlock(progress_thread_mutex); sound_signal_pos_change(-1); break; } g_mutex_unlock(sound_playing_mutex); long position; if((rv = ioctl(audio_fd, SNDCTL_DSP_GETODELAY, &bytes_left)) == -1) { position = -1; } else { position = (int) (((play_info->frame_start + (((double) m_bytes_written - bytes_left) / (m_channels * 2))) * 1000) / play_info->sfinfo->samplerate); } sound_signal_pos_change(position); usleep(35000); } gui_main_audio_play_mode(SOUND_NOT_PLAYING); } void soundserver_fill(struct sound_play_data *play_info) { gboolean done_playing = FALSE; if(audio_fd == -1) return; while(TRUE) { int bytes_left; int rv; if((rv = ioctl(audio_fd, SNDCTL_DSP_GETODELAY, &bytes_left)) == -1) perror("could not get position"); int size = m_userCallback(audio_buffer, BUFFER_SIZE, play_info); if(size == 0) done_playing = TRUE; else done_playing = FALSE; int written = write(audio_fd, audio_buffer, size); m_bytes_written += written; if(done_playing) { if(rv == -1 || bytes_left == 0) { soundserver_close(); g_mutex_lock(sound_playing_mutex); sound_playing = FALSE; g_mutex_unlock(sound_playing_mutex); return; } } //g_warning("write write write"); g_mutex_lock(stop_sound_mutex); if(stop_sound == TRUE) { soundserver_close(); g_mutex_unlock(stop_sound_mutex); g_mutex_lock(sound_playing_mutex); sound_playing = FALSE; g_mutex_unlock(sound_playing_mutex); return; } g_mutex_unlock(stop_sound_mutex); } } void soundserver_close(void) { ioctl(audio_fd, SNDCTL_DSP_RESET); close(audio_fd); audio_fd = -1; } void soundserver_stop() { g_mutex_lock(stop_sound_mutex); stop_sound = TRUE; g_mutex_unlock(stop_sound_mutex); while(TRUE) { g_mutex_lock(sound_playing_mutex); if(!sound_playing) { g_mutex_unlock(sound_playing_mutex); break; } g_mutex_unlock(sound_playing_mutex); } while(TRUE) { g_mutex_lock(progress_thread_mutex); if(!progress_thread_running) { g_mutex_unlock(progress_thread_mutex); break; } g_mutex_unlock(progress_thread_mutex); } g_mutex_lock(stop_sound_mutex); stop_sound = FALSE; g_mutex_unlock(stop_sound_mutex); } void soundserver_init() { sound_playing_mutex = g_mutex_new(); stop_sound_mutex = g_mutex_new(); progress_thread_mutex = g_mutex_new(); } void soundserver_mute(int channel) { } void soundserver_play(struct sound_play_data *data) { soundserver_stop(); g_mutex_lock(sound_playing_mutex); sound_playing = TRUE; g_mutex_unlock(sound_playing_mutex); g_mutex_lock(progress_thread_mutex); progress_thread_running = TRUE; g_mutex_unlock(progress_thread_mutex); m_bytes_written = 0; g_thread_create((GThreadFunc) soundserver_progress, data, FALSE, NULL); g_thread_create((GThreadFunc) soundserver_fill, data, FALSE, NULL); } enum sound_position_type soundserver_get_position_type() { return POSITION_MANUAL; } enum soundserver_position_rv soundserver_get_position(int *pos) { return SOUNDSERVER_ERROR; }