diff --git a/uisimulator/win32/SOURCES b/uisimulator/win32/SOURCES index a88115ade6..ab939af890 100644 --- a/uisimulator/win32/SOURCES +++ b/uisimulator/win32/SOURCES @@ -10,3 +10,4 @@ panic-win32.c string-win32.c thread-win32.c uisw32.c +sound.c diff --git a/uisimulator/win32/sound.c b/uisimulator/win32/sound.c new file mode 100644 index 0000000000..e2a827f0f3 --- /dev/null +++ b/uisimulator/win32/sound.c @@ -0,0 +1,151 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Magnus Holmgren + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "autoconf.h" + +#ifdef ROCKBOX_HAS_SIMSOUND + +#define WINDOWS_LEAN_AND_MEAN +#include + +#include +#include +#include + +#include "sound.h" +#include "kernel.h" +#include "thread-win32.h" +#include "debug.h" + +static void sound_play_chunk(HWAVEOUT wave_out, LPWAVEHDR header, + HANDLE event) +{ + unsigned char* buf; + long len; + + if (!(header->dwFlags & WHDR_DONE) || !sound_get_pcm) + { + return; + } + + EnterCriticalSection(&CriticalSection); + sound_get_pcm(&buf, &len); + LeaveCriticalSection(&CriticalSection); + + if (len == 0) + { + DEBUGF("simulator got no pcm\n"); + sound_get_pcm = NULL; + return; + } + + header->lpData = buf; + header->dwBufferLength = len; + header->dwBytesRecorded = 0; + header->dwUser = 0; + header->dwFlags = 0; + header->dwLoops = 1; + header->lpNext = NULL; + header->reserved = 0; + + if (MMSYSERR_NOERROR != waveOutPrepareHeader(wave_out, header, + sizeof(*header))) + { + return; + } + + ResetEvent(event); + + waveOutWrite(wave_out, header, sizeof(*header)); +} + +static int sound_init(LPHWAVEOUT wave_out, HANDLE event) +{ + static const WAVEFORMATEX format = + { + WAVE_FORMAT_PCM, /* Format */ + 2, /* Number of channels */ + 44100, /* Samples per second */ + 44100 * 4, /* Bytes per second */ + 4, /* Block align */ + 16, /* Bits per sample */ + 0 /* Extra size */ + }; + + if (MMSYSERR_NOERROR != waveOutOpen(wave_out, WAVE_MAPPER, &format, + (DWORD_PTR) event, 0, CALLBACK_EVENT)) + { + return -1; + } + + /* Full volume on left and right */ + waveOutSetVolume(*wave_out, 0xffffffff); + + return 0; +} + +void sound_playback_thread(void) +{ + /* To get smooth playback, two buffers are needed, which are queued for + * playback. (There can still be glitches though.) + */ + HWAVEOUT wave_out; + WAVEHDR header1; + WAVEHDR header2; + HANDLE event; + int result = -1; + + if ((event = CreateEvent(NULL, FALSE, FALSE, NULL))) + { + result = sound_init(&wave_out, event); + } + + while(-1 == result || !event) + { + Sleep(100000); /* Wait forever, can't play sound! */ + } + + while (true) + { + while (!sound_get_pcm) + { + /* TODO: fix a fine thread-synch mechanism here */ + Sleep(100); + } + + DEBUGF("starting simulator playback\n"); + header1.dwFlags = WHDR_DONE; + header2.dwFlags = WHDR_DONE; + sound_play_chunk(wave_out, &header1, event); + sound_play_chunk(wave_out, &header2, event); + + while (sound_get_pcm + && (WAIT_FAILED != WaitForSingleObject(event, 1000))) + { + sound_play_chunk(wave_out, &header1, event); + sound_play_chunk(wave_out, &header2, event); + } + + DEBUGF("stopping simulator playback\n"); + + waveOutReset(wave_out); + } +} + +#endif /* ROCKBOX_HAS_SIMSOUND */ diff --git a/uisimulator/win32/sound.h b/uisimulator/win32/sound.h new file mode 100644 index 0000000000..87499cac8e --- /dev/null +++ b/uisimulator/win32/sound.h @@ -0,0 +1,22 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Daniel Stenberg + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +void sound_playback_thread(void); + +extern void (*sound_get_pcm)(unsigned char** start, long* size); diff --git a/uisimulator/win32/uisw32.c b/uisimulator/win32/uisw32.c index f492b9de36..fb15a856b7 100644 --- a/uisimulator/win32/uisw32.c +++ b/uisimulator/win32/uisw32.c @@ -21,12 +21,14 @@ #include #include #include +#include "autoconf.h" #include "uisw32.h" #include "resource.h" #include "button.h" #include "thread.h" #include "thread-win32.h" #include "kernel.h" +#include "sound.h" #ifndef LR_VGACOLOR /* Should be under MINGW32 builds? */ #define LR_VGACOLOR LR_COLOR @@ -44,6 +46,9 @@ unsigned int uThreadID; // id of mod thread PBYTE lpKeys; bool bActive; // window active? HANDLE hGUIThread; // thread for GUI +#ifdef ROCKBOX_HAS_SIMSOUND +HANDLE hSoundThread; // thread for sound +#endif bool bIsWinNT; // Windows NT derivate? bool lcd_display_redraw=true; // Used for player simulator @@ -262,6 +267,9 @@ int GUIDown () DestroyWindow (hGUIWnd); CloseHandle (hGUIThread); +#ifdef ROCKBOX_HAS_SIMSOUND + CloseHandle (hSoundThread); +#endif for (i = 0; i < nThreads; i++) { @@ -313,6 +321,14 @@ int WINAPI WinMain ( if (hGUIThread == NULL) return MessageBox (NULL, "Error creating gui thread!", "Error", MB_OK); +#ifdef ROCKBOX_HAS_SIMSOUND + hSoundThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) + sound_playback_thread, NULL, 0, &dwThreadID); + + if (hGUIThread == NULL) + MessageBox (NULL, "Error creating sound thread!", "Warning", MB_OK); +#endif + GUIMessageLoop (); return GUIDown ();