summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2010-05-15 21:02:47 +0000
committerThomas Martitz <kugel@rockbox.org>2010-05-15 21:02:47 +0000
commit3d0cee8abbaf764958743e8a7851eee94e60a913 (patch)
treea96b1ec825003a71643a7da4707c300f64824f82 /firmware
parentdcf442e61f21fb2aef5ce7de0547f733557b156e (diff)
downloadrockbox-3d0cee8abbaf764958743e8a7851eee94e60a913.tar.gz
rockbox-3d0cee8abbaf764958743e8a7851eee94e60a913.tar.bz2
rockbox-3d0cee8abbaf764958743e8a7851eee94e60a913.zip
- Move uisimulator/sdl/*.[ch] into the target tree, under firmware/target/hosted/sdl, uisdl.c is split up across button-sdl.c and system-sdl.c.
- Refactor the program startup. main() is now in main.c like on target, and the implicit application thread will now act as our main thread (previously a separate one was created for this in thread initialization). This is part of Rockbox as an application and is the first step to make an application port from the uisimulator. In a further step the sim bits from the sdl build will be separated out. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26065 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES21
-rw-r--r--firmware/drivers/audio/sdl.c186
-rw-r--r--firmware/drivers/button.c9
-rw-r--r--firmware/export/audiohw.h6
-rw-r--r--firmware/export/config/sim.h4
-rw-r--r--firmware/export/system.h1
-rw-r--r--firmware/kernel.c5
-rw-r--r--firmware/libc/include/stdlib.h3
-rw-r--r--firmware/sound.c85
-rw-r--r--firmware/target/hosted/sdl/button-sdl.c2018
-rw-r--r--firmware/target/hosted/sdl/button-sdl.h32
-rw-r--r--firmware/target/hosted/sdl/kernel-sdl.c162
-rw-r--r--firmware/target/hosted/sdl/lcd-bitmap.c416
-rw-r--r--firmware/target/hosted/sdl/lcd-bitmap.h35
-rw-r--r--firmware/target/hosted/sdl/lcd-charcells.c198
-rw-r--r--firmware/target/hosted/sdl/lcd-charcells.h34
-rw-r--r--firmware/target/hosted/sdl/lcd-remote-bitmap.c111
-rw-r--r--firmware/target/hosted/sdl/lcd-remote-bitmap.h32
-rw-r--r--firmware/target/hosted/sdl/lcd-sdl.c113
-rw-r--r--firmware/target/hosted/sdl/lcd-sdl.h43
-rw-r--r--firmware/target/hosted/sdl/pcm-sdl.c373
-rw-r--r--firmware/target/hosted/sdl/sim-ui-defines.h405
-rw-r--r--firmware/target/hosted/sdl/system-sdl.c236
-rw-r--r--firmware/target/hosted/sdl/system-sdl.h52
-rw-r--r--firmware/target/hosted/sdl/thread-sdl.c610
-rw-r--r--firmware/target/hosted/sdl/thread-sdl.h32
-rw-r--r--firmware/target/hosted/sdl/timer-sdl.c61
27 files changed, 5188 insertions, 95 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 68074dbbec..47249a2d6d 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -18,6 +18,22 @@ rolo.c
thread.c
timer.c
#endif /* SIMULATOR */
+#ifdef HAVE_SDL
+target/hosted/sdl/button-sdl.c
+target/hosted/sdl/kernel-sdl.c
+#ifdef HAVE_LCD_BITMAP
+target/hosted/sdl/lcd-bitmap.c
+#elif defined(HAVE_LCD_CHARCELLS)
+target/hosted/sdl/lcd-charcells.c
+#endif
+#ifdef HAVE_REMOTE_LCD
+target/hosted/sdl/lcd-remote-bitmap.c
+#endif
+target/hosted/sdl/lcd-sdl.c
+target/hosted/sdl/system-sdl.c
+target/hosted/sdl/thread-sdl.c
+target/hosted/sdl/timer-sdl.c
+#endif
panic.c
debug.c
@@ -292,6 +308,11 @@ drivers/audio/ak4537.c
#elif defined(HAVE_UDA1341)
drivers/audio/uda1341.c
#endif /* defined(HAVE_*) */
+#elif defined(HAVE_SDL_AUDIO)
+drivers/audio/sdl.c
+#if CONFIG_CODEC == SWCODEC
+target/hosted/sdl/pcm-sdl.c
+#endif
#endif /* !defined(SIMULATOR) && !defined(BOOTLOADER) */
/* USB Stack */
diff --git a/firmware/drivers/audio/sdl.c b/firmware/drivers/audio/sdl.c
new file mode 100644
index 0000000000..c063192873
--- /dev/null
+++ b/firmware/drivers/audio/sdl.c
@@ -0,0 +1,186 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright © 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <SDL_audio.h>
+#include "config.h"
+#include "audiohw.h"
+
+/**
+ * Audio Hardware api. Make them do nothing as we cannot properly simulate with
+ * SDL. if we used DSP we would run code that doesn't actually run on the target
+ **/
+
+extern void pcm_set_mixer_volume(int);
+
+void audiohw_set_volume(int volume)
+{
+#if CONFIG_CODEC == SWCODEC
+ pcm_set_mixer_volume(
+ SDL_MIX_MAXVOLUME * ((volume - VOLUME_MIN) / 10) / (VOLUME_RANGE / 10));
+#else
+ (void)volume;
+#endif
+}
+
+const struct sound_settings_info audiohw_settings[] = {
+ [SOUND_VOLUME] = {"dB", 0, 1, VOLUME_MIN / 10, VOLUME_MAX / 10, -25},
+/* Bass and treble tone controls */
+#ifdef AUDIOHW_HAVE_BASS
+ [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0},
+#endif
+#ifdef AUDIOHW_HAVE_TREBLE
+ [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0},
+#endif
+ [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
+ [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
+ [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
+#if defined(HAVE_RECORDING)
+ [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0},
+ [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0},
+ [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16},
+#endif
+#if defined(AUDIOHW_HAVE_BASS_CUTOFF)
+ [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
+ [SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_DEPTH_3D)
+ [SOUND_DEPTH_3D] = {"%", 0, 1, 0, 15, 0},
+#endif
+/* Hardware EQ tone controls */
+#if defined(AUDIOHW_HAVE_EQ_BAND1)
+ [SOUND_EQ_BAND1_GAIN] = {"dB", 0, 1, -12, 12, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND2)
+ [SOUND_EQ_BAND2_GAIN] = {"dB", 0, 1, -12, 12, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3)
+ [SOUND_EQ_BAND3_GAIN] = {"dB", 0, 1, -12, 12, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4)
+ [SOUND_EQ_BAND4_GAIN] = {"dB", 0, 1, -12, 12, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND5)
+ [SOUND_EQ_BAND5_GAIN] = {"dB", 0, 1, -12, 12, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND1_FREQUENCY)
+ [SOUND_EQ_BAND1_FREQUENCY] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND2_FREQUENCY)
+ [SOUND_EQ_BAND2_FREQUENCY] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3_FREQUENCY)
+ [SOUND_EQ_BAND3_FREQUENCY] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4_FREQUENCY)
+ [SOUND_EQ_BAND4_FREQUENCY] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND5_FREQUENCY)
+ [SOUND_EQ_BAND5_FREQUENCY] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND2_WIDTH)
+ [SOUND_EQ_BAND2_WIDTH] = {"", 0, 1, 0, 1, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3_WIDTH)
+ [SOUND_EQ_BAND3_WIDTH] = {"", 0, 1, 0, 1, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4_WIDTH)
+ [SOUND_EQ_BAND4_WIDTH] = {"", 0, 1, 0, 1, 0},
+#endif
+
+#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
+ [SOUND_LOUDNESS] = {"dB", 0, 1, 0, 17, 0},
+ [SOUND_AVC] = {"", 0, 1, -1, 4, 0},
+ [SOUND_MDB_STRENGTH] = {"dB", 0, 1, 0, 127, 48},
+ [SOUND_MDB_HARMONICS] = {"%", 0, 1, 0, 100, 50},
+ [SOUND_MDB_CENTER] = {"Hz", 0, 10, 20, 300, 60},
+ [SOUND_MDB_SHAPE] = {"Hz", 0, 10, 50, 300, 90},
+ [SOUND_MDB_ENABLE] = {"", 0, 1, 0, 1, 0},
+ [SOUND_SUPERBASS] = {"", 0, 1, 0, 1, 0},
+#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
+};
+
+/**
+ * stubs here, for the simulator
+ **/
+
+#if defined(AUDIOHW_HAVE_PRESCALER)
+void audiohw_set_prescaler(int value) { (void)value; }
+#endif
+#if defined(AUDIOHW_HAVE_BALANCE)
+void audiohw_set_balance(int value) { (void)value; }
+#endif
+#if defined(AUDIOHW_HAVE_BASS)
+void audiohw_set_bass(int value) { (void)value; }
+#endif
+#if defined(AUDIOHW_HAVE_TREBLE)
+void audiohw_set_treble(int value) { (void)value; }
+#endif
+#if CONFIG_CODEC != SWCODEC
+void audiohw_set_channel(int value) { (void)value; }
+void audiohw_set_stereo_width(int value){ (void)value; }
+#endif
+#if defined(AUDIOHW_HAVE_BASS_CUTOFF)
+void audiohw_set_bass_cutoff(int value) { (void)value; }
+#endif
+#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
+void audiohw_set_treble_cutoff(int value){ (void)value; }
+#endif
+/* EQ-based tone controls */
+#if defined(AUDIOHW_HAVE_EQ)
+void audiohw_set_eq_band_gain(unsigned int band, int value)
+ { (void)band; (void)value; }
+#endif
+#if defined(AUDIOHW_HAVE_EQ_FREQUENCY)
+void audiohw_set_eq_band_frequency(unsigned int band, int value)
+ { (void)band; (void)value; }
+#endif
+#if defined(AUDIOHW_HAVE_EQ_WIDTH)
+void audiohw_set_eq_band_width(unsigned int band, int value)
+ { (void)band; (void)value; }
+#endif
+#if defined(AUDIOHW_HAVE_DEPTH_3D)
+void audiohw_set_depth_3d(int value)
+ { (void)value; }
+#endif
+#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
+int mas_codec_readreg(int reg)
+{
+ (void)reg;
+ return 0;
+}
+
+int mas_codec_writereg(int reg, unsigned int val)
+{
+ (void)reg;
+ (void)val;
+ return 0;
+}
+int mas_writemem(int bank, int addr, const unsigned long* src, int len)
+{
+ (void)bank;
+ (void)addr;
+ (void)src;
+ (void)len;
+ return 0;
+}
+#endif
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c
index 100957b77a..f116ad646e 100644
--- a/firmware/drivers/button.c
+++ b/firmware/drivers/button.c
@@ -429,7 +429,6 @@ void button_init(void)
tick_add_task(button_tick);
}
-#ifndef SIMULATOR
#ifdef BUTTON_DRIVER_CLOSE
void button_close(void)
{
@@ -443,9 +442,10 @@ void button_close(void)
*/
static int button_flip(int button)
{
- int newbutton;
+ int newbutton = button;
- newbutton = button &
+#ifndef SIMULATOR
+ newbutton &=
~(BUTTON_LEFT | BUTTON_RIGHT
#if defined(BUTTON_UP) && defined(BUTTON_DOWN)
| BUTTON_UP | BUTTON_DOWN
@@ -503,7 +503,7 @@ static int button_flip(int button)
if (button & BUTTON_PREV)
newbutton |= BUTTON_NEXT;
#endif
-
+#endif /* !SIMULATOR */
return newbutton;
}
@@ -523,7 +523,6 @@ void button_set_flip(bool flip)
}
}
#endif /* HAVE_LCD_FLIP */
-#endif /* SIMULATOR */
#ifdef HAVE_BACKLIGHT
void set_backlight_filter_keypress(bool value)
diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h
index d7ee551e40..b8214e67b9 100644
--- a/firmware/export/audiohw.h
+++ b/firmware/export/audiohw.h
@@ -66,6 +66,10 @@
#elif defined(HAVE_AK4537)
#include "ak4537.h"
#endif
+#if defined(HAVE_SDL_AUDIO)
+/* #include <SDL_audio.h> gives errors in other code areas,
+ * we don't really need it here, so don't. but it should maybe be fixed */
+#endif
@@ -369,7 +373,7 @@ void audiohw_postinit(void);
*/
void audiohw_close(void);
-#ifdef AUDIOHW_HAVE_CLIPPING
+#if defined(AUDIOHW_HAVE_CLIPPING) || defined(HAVE_SDL_AUDIO)
/**
* Set new volume value
* @param val to set.
diff --git a/firmware/export/config/sim.h b/firmware/export/config/sim.h
index 6d2e6d24ea..d65b0fbbf8 100644
--- a/firmware/export/config/sim.h
+++ b/firmware/export/config/sim.h
@@ -80,6 +80,8 @@
#undef HAVE_SPEAKER
+#undef BUTTON_DRIVER_CLOSE
+
#if CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG
#undef CONFIG_BACKLIGHT_FADING
/* simulate SW_SETTING, as we handle sdl very similary */
@@ -97,4 +99,6 @@
#define DEFAULT_BRIGHTNESS_SETTING MAX_BRIGHTNESS_SETTING
#endif
+#define HAVE_SDL
+#define HAVE_SDL_AUDIO
#define _ISOC99_SOURCE 1
diff --git a/firmware/export/system.h b/firmware/export/system.h
index bd31c03028..fc582aac03 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -235,6 +235,7 @@ enum {
#if !defined(SIMULATOR) && !defined(__PCTOOL__)
#include "system-target.h"
#else /* SIMULATOR */
+#include "system-sdl.h"
static inline uint16_t swap16(uint16_t value)
/*
result[15..8] = value[ 7..0];
diff --git a/firmware/kernel.c b/firmware/kernel.c
index 64c8142540..d8c67e8485 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -22,14 +22,11 @@
#include <string.h>
#include "config.h"
#include "kernel.h"
-#ifdef SIMULATOR
-#include "system-sdl.h"
-#include "debug.h"
-#endif
#include "thread.h"
#include "cpu.h"
#include "system.h"
#include "panic.h"
+#include "debug.h"
/* Make this nonzero to enable more elaborate checks on objects */
#if defined(DEBUG) || defined(SIMULATOR)
diff --git a/firmware/libc/include/stdlib.h b/firmware/libc/include/stdlib.h
index 5f6db6da8a..57553367c4 100644
--- a/firmware/libc/include/stdlib.h
+++ b/firmware/libc/include/stdlib.h
@@ -29,6 +29,7 @@ void *malloc(size_t);
void *calloc (size_t nmemb, size_t size);
void free(void *);
void *realloc(void *, size_t);
+int atexit(void (*)(void));
#define RAND_MAX INT_MAX
@@ -51,7 +52,7 @@ void exit(int status);
#endif
int atoi (const char *str);
-
+
#ifdef __cplusplus
}
#endif
diff --git a/firmware/sound.c b/firmware/sound.c
index fb2f353d71..dccca12264 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -43,89 +43,6 @@
extern bool audio_is_initialized;
-#ifdef SIMULATOR
-extern void audiohw_set_volume(int value);
-/* dummy for sim */
-const struct sound_settings_info audiohw_settings[] = {
- [SOUND_VOLUME] = {"dB", 0, 1, VOLUME_MIN / 10, VOLUME_MAX / 10, -25},
-/* Bass and treble tone controls */
-#ifdef AUDIOHW_HAVE_BASS
- [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0},
-#endif
-#ifdef AUDIOHW_HAVE_TREBLE
- [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0},
-#endif
- [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
- [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
- [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
-#if defined(HAVE_RECORDING)
- [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0},
- [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0},
- [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16},
-#endif
-#if defined(AUDIOHW_HAVE_BASS_CUTOFF)
- [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 1},
-#endif
-#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
- [SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1},
-#endif
-#if defined(AUDIOHW_HAVE_DEPTH_3D)
- [SOUND_DEPTH_3D] = {"%", 0, 1, 0, 15, 0},
-#endif
-/* Hardware EQ tone controls */
-#if defined(AUDIOHW_HAVE_EQ_BAND1)
- [SOUND_EQ_BAND1_GAIN] = {"dB", 0, 1, -12, 12, 0},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND2)
- [SOUND_EQ_BAND2_GAIN] = {"dB", 0, 1, -12, 12, 0},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND3)
- [SOUND_EQ_BAND3_GAIN] = {"dB", 0, 1, -12, 12, 0},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND4)
- [SOUND_EQ_BAND4_GAIN] = {"dB", 0, 1, -12, 12, 0},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND5)
- [SOUND_EQ_BAND5_GAIN] = {"dB", 0, 1, -12, 12, 0},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND1_FREQUENCY)
- [SOUND_EQ_BAND1_FREQUENCY] = {"", 0, 1, 1, 4, 1},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND2_FREQUENCY)
- [SOUND_EQ_BAND2_FREQUENCY] = {"", 0, 1, 1, 4, 1},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND3_FREQUENCY)
- [SOUND_EQ_BAND3_FREQUENCY] = {"", 0, 1, 1, 4, 1},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND4_FREQUENCY)
- [SOUND_EQ_BAND4_FREQUENCY] = {"", 0, 1, 1, 4, 1},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND5_FREQUENCY)
- [SOUND_EQ_BAND5_FREQUENCY] = {"", 0, 1, 1, 4, 1},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND2_WIDTH)
- [SOUND_EQ_BAND2_WIDTH] = {"", 0, 1, 0, 1, 0},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND3_WIDTH)
- [SOUND_EQ_BAND3_WIDTH] = {"", 0, 1, 0, 1, 0},
-#endif
-#if defined(AUDIOHW_HAVE_EQ_BAND4_WIDTH)
- [SOUND_EQ_BAND4_WIDTH] = {"", 0, 1, 0, 1, 0},
-#endif
-
-#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
- [SOUND_LOUDNESS] = {"dB", 0, 1, 0, 17, 0},
- [SOUND_AVC] = {"", 0, 1, -1, 4, 0},
- [SOUND_MDB_STRENGTH] = {"dB", 0, 1, 0, 127, 48},
- [SOUND_MDB_HARMONICS] = {"%", 0, 1, 0, 100, 50},
- [SOUND_MDB_CENTER] = {"Hz", 0, 10, 20, 300, 60},
- [SOUND_MDB_SHAPE] = {"Hz", 0, 10, 50, 300, 90},
- [SOUND_MDB_ENABLE] = {"", 0, 1, 0, 1, 0},
- [SOUND_SUPERBASS] = {"", 0, 1, 0, 1, 0},
-#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
-};
-#endif
-
const char *sound_unit(int setting)
{
return audiohw_settings[setting].unit;
@@ -356,7 +273,7 @@ static void set_prescaled_volume(void)
#elif defined(HAVE_TLV320) || defined(HAVE_WM8978) || defined(HAVE_WM8985)
audiohw_set_headphone_vol(tenthdb2master(l), tenthdb2master(r));
-#elif defined(HAVE_JZ4740_CODEC)
+#elif defined(HAVE_JZ4740_CODEC) || defined(HAVE_SDL_AUDIO)
audiohw_set_volume(current_volume);
#endif
#else /* SIMULATOR */
diff --git a/firmware/target/hosted/sdl/button-sdl.c b/firmware/target/hosted/sdl/button-sdl.c
new file mode 100644
index 0000000000..51ba8cff92
--- /dev/null
+++ b/firmware/target/hosted/sdl/button-sdl.c
@@ -0,0 +1,2018 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Felix Arends
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <math.h>
+#include "sim-ui-defines.h"
+#include "lcd-charcells.h"
+#include "lcd-remote.h"
+#include "config.h"
+#include "button.h"
+#include "kernel.h"
+#include "backlight.h"
+#include "misc.h"
+#include "sim_tasks.h"
+#include "button-sdl.h"
+#include "backlight.h"
+
+#include "debug.h"
+
+#ifdef HAVE_TOUCHSCREEN
+#include "touchscreen.h"
+static int mouse_coords = 0;
+#endif
+/* how long until repeat kicks in */
+#define REPEAT_START 6
+
+/* the speed repeat starts at */
+#define REPEAT_INTERVAL_START 4
+
+/* speed repeat finishes at */
+#define REPEAT_INTERVAL_FINISH 2
+
+#ifdef HAVE_TOUCHSCREEN
+#define USB_KEY SDLK_c /* SDLK_u is taken by BUTTON_MIDLEFT */
+#else
+#define USB_KEY SDLK_u
+#endif
+
+#if defined(IRIVER_H100_SERIES) || defined (IRIVER_H300_SERIES)
+int _remote_type=REMOTETYPE_H100_LCD;
+
+int remote_type(void)
+{
+ return _remote_type;
+}
+#endif
+
+static int xy2button(int x, int y);
+
+struct event_queue button_queue;
+
+static int btn = 0; /* Hopefully keeps track of currently pressed keys... */
+
+#ifdef HAS_BUTTON_HOLD
+bool hold_button_state = false;
+bool button_hold(void) {
+ return hold_button_state;
+}
+#endif
+
+#ifdef HAS_REMOTE_BUTTON_HOLD
+bool remote_hold_button_state = false;
+bool remote_button_hold(void) {
+ return remote_hold_button_state;
+}
+#endif
+static void button_event(int key, bool pressed);
+extern bool debug_wps;
+extern bool mapping;
+static void gui_message_loop(void)
+{
+ SDL_Event event;
+ static int x,y,xybutton = 0;
+
+ if (SDL_PollEvent(&event))
+ {
+ switch(event.type)
+ {
+ case SDL_KEYDOWN:
+ button_event(event.key.keysym.sym, true);
+ break;
+ case SDL_KEYUP:
+ button_event(event.key.keysym.sym, false);
+ case SDL_MOUSEBUTTONDOWN:
+ switch ( event.button.button ) {
+#ifdef HAVE_SCROLLWHEEL
+ case SDL_BUTTON_WHEELUP:
+ button_event( SDLK_UP, true );
+ break;
+ case SDL_BUTTON_WHEELDOWN:
+ button_event( SDLK_DOWN, true );
+ break;
+#endif
+ case SDL_BUTTON_LEFT:
+ case SDL_BUTTON_MIDDLE:
+ if ( mapping && background ) {
+ x = event.button.x;
+ y = event.button.y;
+ }
+ if ( background ) {
+ xybutton = xy2button( event.button.x, event.button.y );
+ if( xybutton )
+ button_event( xybutton, true );
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (debug_wps && event.button.button == 1)
+ {
+ if ( background )
+#ifdef HAVE_REMOTE
+ if ( event.button.y < UI_REMOTE_POSY ) /* Main Screen */
+ printf("Mouse at: (%d, %d)\n", event.button.x - UI_LCD_POSX -1 , event.button.y - UI_LCD_POSY - 1 );
+ else
+ printf("Mouse at: (%d, %d)\n", event.button.x - UI_REMOTE_POSX -1 , event.button.y - UI_REMOTE_POSY - 1 );
+#else
+ printf("Mouse at: (%d, %d)\n", event.button.x - UI_LCD_POSX -1 , event.button.y - UI_LCD_POSY - 1 );
+#endif
+ else
+ if ( event.button.y/display_zoom < LCD_HEIGHT ) /* Main Screen */
+ printf("Mouse at: (%d, %d)\n", event.button.x/display_zoom, event.button.y/display_zoom );
+#ifdef HAVE_REMOTE
+ else
+ printf("Mouse at: (%d, %d)\n", event.button.x/display_zoom, event.button.y/display_zoom - LCD_HEIGHT );
+#endif
+ }
+ break;
+ case SDL_MOUSEBUTTONUP:
+ switch ( event.button.button ) {
+ /* The scrollwheel button up events are ignored as they are queued immediately */
+ case SDL_BUTTON_LEFT:
+ case SDL_BUTTON_MIDDLE:
+ if ( mapping && background ) {
+ printf(" { SDLK_, %d, %d, %d, \"\" },\n", x,
+#define SQUARE(x) ((x)*(x))
+ y, (int)sqrt( SQUARE(x-(int)event.button.x)
+ + SQUARE(y-(int)event.button.y)) );
+ }
+ if ( background && xybutton ) {
+ button_event( xybutton, false );
+ xybutton = 0;
+ }
+#ifdef HAVE_TOUCHSCREEN
+ else {
+ button_event(BUTTON_TOUCHSCREEN, false);
+ }
+#endif
+ break;
+ default:
+ break;
+ }
+ break;
+
+
+ case SDL_QUIT:
+ {
+ exit(EXIT_SUCCESS);
+ break;
+ }
+ default:
+ /*printf("Unhandled event\n"); */
+ break;
+ }
+ }
+}
+
+static void button_event(int key, bool pressed)
+{
+ int new_btn = 0;
+ static bool usb_connected = false;
+ if (usb_connected && key != USB_KEY)
+ return;
+ switch (key)
+ {
+
+#ifdef HAVE_TOUCHSCREEN
+ case BUTTON_TOUCHSCREEN:
+ switch (touchscreen_get_mode())
+ {
+ case TOUCHSCREEN_POINT:
+ new_btn = BUTTON_TOUCHSCREEN;
+ break;
+ case TOUCHSCREEN_BUTTON:
+ {
+ static int touchscreen_buttons[3][3] = {
+ {BUTTON_TOPLEFT, BUTTON_TOPMIDDLE, BUTTON_TOPRIGHT},
+ {BUTTON_MIDLEFT, BUTTON_CENTER, BUTTON_MIDRIGHT},
+ {BUTTON_BOTTOMLEFT, BUTTON_BOTTOMMIDDLE, BUTTON_BOTTOMRIGHT},
+ };
+ int px_x = ((mouse_coords&0xffff0000)>>16);
+ int px_y = ((mouse_coords&0x0000ffff));
+ new_btn = touchscreen_buttons[px_y/(LCD_HEIGHT/3)][px_x/(LCD_WIDTH/3)];
+ break;
+ }
+ }
+ break;
+ case SDLK_KP7:
+ case SDLK_7:
+ new_btn = BUTTON_TOPLEFT;
+ break;
+ case SDLK_KP8:
+ case SDLK_8:
+ case SDLK_UP:
+ new_btn = BUTTON_TOPMIDDLE;
+ break;
+ case SDLK_KP9:
+ case SDLK_9:
+ new_btn = BUTTON_TOPRIGHT;
+ break;
+ case SDLK_KP4:
+ case SDLK_u:
+ case SDLK_LEFT:
+ new_btn = BUTTON_MIDLEFT;
+ break;
+ case SDLK_KP5:
+ case SDLK_i:
+ new_btn = BUTTON_CENTER;
+ break;
+ case SDLK_KP6:
+ case SDLK_o:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_MIDRIGHT;
+ break;
+ case SDLK_KP1:
+ case SDLK_j:
+ new_btn = BUTTON_BOTTOMLEFT;
+ break;
+ case SDLK_KP2:
+ case SDLK_k:
+ case SDLK_DOWN:
+ new_btn = BUTTON_BOTTOMMIDDLE;
+ break;
+ case SDLK_KP3:
+ case SDLK_l:
+ new_btn = BUTTON_BOTTOMRIGHT;
+ break;
+ case SDLK_F4:
+ if(pressed)
+ {
+ touchscreen_set_mode(touchscreen_get_mode() == TOUCHSCREEN_POINT ? TOUCHSCREEN_BUTTON : TOUCHSCREEN_POINT);
+ printf("Touchscreen mode: %s\n", touchscreen_get_mode() == TOUCHSCREEN_POINT ? "TOUCHSCREEN_POINT" : "TOUCHSCREEN_BUTTON");
+ }
+ break;
+
+#endif
+ case USB_KEY:
+ if (!pressed)
+ {
+ usb_connected = !usb_connected;
+ if (usb_connected)
+ queue_post(&button_queue, SYS_USB_CONNECTED, 0);
+ else
+ queue_post(&button_queue, SYS_USB_DISCONNECTED, 0);
+ }
+ return;
+
+#ifdef HAS_BUTTON_HOLD
+ case SDLK_h:
+ if(pressed)
+ {
+ hold_button_state = !hold_button_state;
+ DEBUGF("Hold button is %s\n", hold_button_state?"ON":"OFF");
+ }
+ return;
+#endif
+
+#ifdef HAS_REMOTE_BUTTON_HOLD
+ case SDLK_j:
+ if(pressed)
+ {
+ remote_hold_button_state = !remote_hold_button_state;
+ DEBUGF("Remote hold button is %s\n",
+ remote_hold_button_state?"ON":"OFF");
+ }
+ return;
+#endif
+
+#if CONFIG_KEYPAD == GIGABEAT_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_A;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+
+#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_BACK;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP9:
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+
+#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_DIVIDE:
+ case SDLK_F1:
+ new_btn = BUTTON_REC;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+
+#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
+ case SDLK_KP4:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_LEFT:
+ new_btn = BUTTON_RC_REW;
+ break;
+ case SDLK_KP6:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RC_FF;
+ break;
+ case SDLK_KP8:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_UP:
+ new_btn = BUTTON_RC_VOL_UP;
+ break;
+ case SDLK_KP2:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_DOWN:
+ new_btn = BUTTON_RC_VOL_DOWN;
+ break;
+ case SDLK_KP_PERIOD:
+ new_btn = BUTTON_MODE;
+ break;
+ case SDLK_INSERT:
+ new_btn = BUTTON_RC_MODE;
+ break;
+ case SDLK_KP_DIVIDE:
+ new_btn = BUTTON_REC;
+ break;
+ case SDLK_F1:
+ new_btn = BUTTON_RC_REC;
+ break;
+ case SDLK_KP5:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_SPACE:
+ new_btn = BUTTON_RC_PLAY;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_RC_MENU;
+ break;
+
+#elif (CONFIG_KEYPAD == IPOD_1G2G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_SCROLL_BACK;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_SCROLL_FWD;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+
+#elif CONFIG_KEYPAD == IRIVER_H10_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_SCROLL_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_SCROLL_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_DIVIDE:
+ case SDLK_F1:
+ new_btn = BUTTON_REW;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F2:
+ new_btn = BUTTON_FF;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_PLAY;
+ break;
+
+#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
+ case SDLK_t:
+ if(pressed)
+ switch(_remote_type)
+ {
+ case REMOTETYPE_UNPLUGGED:
+ _remote_type=REMOTETYPE_H100_LCD;
+ DEBUGF("Changed remote type to H100\n");
+ break;
+ case REMOTETYPE_H100_LCD:
+ _remote_type=REMOTETYPE_H300_LCD;
+ DEBUGF("Changed remote type to H300\n");
+ break;
+ case REMOTETYPE_H300_LCD:
+ _remote_type=REMOTETYPE_H300_NONLCD;
+ DEBUGF("Changed remote type to H300 NON-LCD\n");
+ break;
+ case REMOTETYPE_H300_NONLCD:
+ _remote_type=REMOTETYPE_UNPLUGGED;
+ DEBUGF("Changed remote type to none\n");
+ break;
+ }
+ break;
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_ON;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_OFF;
+ break;
+ case SDLK_KP_DIVIDE:
+ case SDLK_F1:
+ new_btn = BUTTON_REC;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MODE;
+ break;
+
+#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_EQ;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MODE;
+ break;
+
+#elif CONFIG_KEYPAD == ONDIO_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_OFF;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+
+#elif CONFIG_KEYPAD == PLAYER_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_STOP;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_ON;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+
+#elif CONFIG_KEYPAD == RECORDER_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_ON;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_OFF;
+ break;
+ case SDLK_KP_DIVIDE:
+ case SDLK_F1:
+ new_btn = BUTTON_F1;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F2:
+ new_btn = BUTTON_F2;
+ break;
+ case SDLK_KP_MINUS:
+ case SDLK_F3:
+ new_btn = BUTTON_F3;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_PLAY;
+ break;
+
+#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_ON;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_OFF;
+ break;
+ case SDLK_KP_DIVIDE:
+ case SDLK_F1:
+ new_btn = BUTTON_F1;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F2:
+ new_btn = BUTTON_F2;
+ break;
+ case SDLK_KP_MINUS:
+ case SDLK_F3:
+ new_btn = BUTTON_F3;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+
+#elif CONFIG_KEYPAD == SANSA_E200_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_SCROLL_BACK;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_SCROLL_FWD;
+ break;
+ case SDLK_KP9:
+ case SDLK_PAGEUP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP3:
+ case SDLK_PAGEDOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP1:
+ case SDLK_HOME:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP7:
+ case SDLK_END:
+ new_btn = BUTTON_REC;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+
+#elif CONFIG_KEYPAD == SANSA_C200_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP1:
+ new_btn = BUTTON_REC;
+ break;
+ case SDLK_KP5:
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_VOL_UP;
+ break;
+
+#elif CONFIG_KEYPAD == MROBE500_PAD
+ case SDLK_F9:
+ new_btn = BUTTON_RC_HEART;
+ break;
+ case SDLK_F10:
+ new_btn = BUTTON_RC_MODE;
+ break;
+ case SDLK_F11:
+ new_btn = BUTTON_RC_VOL_DOWN;
+ break;
+ case SDLK_F12:
+ new_btn = BUTTON_RC_VOL_UP;
+ break;
+ case SDLK_MINUS:
+ case SDLK_LESS:
+ case SDLK_LEFTBRACKET:
+ case SDLK_KP_DIVIDE:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_PLUS:
+ case SDLK_GREATER:
+ case SDLK_RIGHTBRACKET:
+ case SDLK_KP_MULTIPLY:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_PAGEUP:
+ new_btn = BUTTON_RC_PLAY;
+ break;
+ case SDLK_PAGEDOWN:
+ new_btn = BUTTON_RC_DOWN;
+ break;
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+#elif CONFIG_KEYPAD == MROBE100_PAD
+ case SDLK_F9:
+ new_btn = BUTTON_RC_HEART;
+ break;
+ case SDLK_F10:
+ new_btn = BUTTON_RC_MODE;
+ break;
+ case SDLK_F11:
+ new_btn = BUTTON_RC_VOL_DOWN;
+ break;
+ case SDLK_F12:
+ new_btn = BUTTON_RC_VOL_UP;
+ break;
+ case SDLK_LEFT:
+ new_btn = BUTTON_RC_FF;
+ break;
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RC_REW;
+ break;
+ case SDLK_UP:
+ new_btn = BUTTON_RC_PLAY;
+ break;
+ case SDLK_DOWN:
+ new_btn = BUTTON_RC_DOWN;
+ break;
+ case SDLK_KP1:
+ new_btn = BUTTON_DISPLAY;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP4:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+
+#elif CONFIG_KEYPAD == COWON_D2_PAD
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ case SDLK_BACKSPACE:
+ case SDLK_DELETE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_EQUALS:
+ new_btn = BUTTON_PLUS;
+ break;
+ case SDLK_KP_MINUS:
+ case SDLK_MINUS:
+ new_btn = BUTTON_MINUS;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_SPACE:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+#elif CONFIG_KEYPAD == IAUDIO67_PAD
+ case SDLK_UP:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_DOWN:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_LEFT:
+ new_btn = BUTTON_STOP;
+ break;
+ case SDLK_RETURN:
+ case SDLK_KP_ENTER:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_PLUS:
+ new_btn = BUTTON_VOLUP;
+ break;
+ case SDLK_MINUS:
+ new_btn = BUTTON_VOLDOWN;
+ break;
+ case SDLK_SPACE:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_BACKSPACE:
+ new_btn = BUTTON_POWER;
+ break;
+#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
+ case SDLK_KP1:
+ new_btn = BUTTON_BACK;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_CUSTOM;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+#elif CONFIG_KEYPAD == CREATIVEZV_PAD
+ case SDLK_KP1:
+ new_btn = BUTTON_PREV;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_NEXT;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_BACK;
+ break;
+ case SDLK_p:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_z:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_s:
+ new_btn = BUTTON_VOL_UP;
+
+#elif CONFIG_KEYPAD == MEIZU_M6SL_PAD
+ case SDLK_KP1:
+ new_btn = BUTTON_PREV;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_NEXT;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+#elif CONFIG_KEYPAD == SANSA_FUZE_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_SCROLL_BACK;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_SCROLL_FWD;
+ break;
+ case SDLK_PAGEUP:
+ case SDLK_KP9:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_PAGEDOWN:
+ case SDLK_KP3:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_MINUS:
+ case SDLK_KP1:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_MULTIPLY:
+ new_btn = BUTTON_HOME;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_SELECT;
+ break;
+#elif CONFIG_KEYPAD == SANSA_CLIP_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+
+ case SDLK_INSERT:
+ case SDLK_KP_MULTIPLY:
+ new_btn = BUTTON_HOME;
+ break;
+ case SDLK_SPACE:
+ case SDLK_KP5:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_PAGEDOWN:
+ case SDLK_KP3:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_PAGEUP:
+ case SDLK_KP9:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_ESCAPE:
+ case SDLK_KP1:
+ new_btn = BUTTON_POWER;
+ break;
+#elif CONFIG_KEYPAD == SANSA_M200_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_PLUS:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP5:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_VOL_UP;
+ break;
+#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP1:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_PREV;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_NEXT;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_PAGEUP:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_PAGEDOWN:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP7:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP1:
+ new_btn = BUTTON_PLAYLIST;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_KP_MINUS:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP_PLUS:
+ new_btn = BUTTON_VIEW;
+ break;
+#elif CONFIG_KEYPAD == ONDAVX747_PAD
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_PLUS:
+ case SDLK_GREATER:
+ case SDLK_RIGHTBRACKET:
+ case SDLK_KP_MULTIPLY:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_KP_MINUS:
+ case SDLK_MINUS:
+ case SDLK_LESS:
+ case SDLK_LEFTBRACKET:
+ case SDLK_KP_DIVIDE:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_MENU;
+ break;
+#elif CONFIG_KEYPAD == ONDAVX777_PAD
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_KP_ENTER:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP9:
+ case SDLK_PAGEUP:
+ new_btn = BUTTON_FFWD;
+ break;
+#ifdef SAMSUNG_YH820
+ case SDLK_KP7:
+#else
+ case SDLK_KP3:
+#endif
+ case SDLK_PAGEDOWN:
+ new_btn = BUTTON_REW;
+ break;
+ case SDLK_KP_PLUS:
+ new_btn = BUTTON_REC;
+ break;
+#elif CONFIG_KEYPAD == MINI2440_PAD
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_A;
+ break;
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP_PLUS:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_KP_MINUS:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_PREV;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_NEXT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP5:
+ new_btn = BUTTON_OK;
+ break;
+ case SDLK_KP_DIVIDE:
+ new_btn = BUTTON_CANCEL;
+ break;
+ case SDLK_KP_PLUS:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_MULTIPLY:
+ new_btn = BUTTON_REC;
+ break;
+
+#elif CONFIG_KEYPAD == MPIO_HD200_PAD
+ case SDLK_UP:
+ new_btn = BUTTON_PREV;
+ break;
+ case SDLK_DOWN:
+ new_btn = BUTTON_NEXT;
+ break;
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_RETURN:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_LEFT:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_RIGHT:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_REC;
+ break;
+
+#else
+#error No keymap defined!
+#endif /* CONFIG_KEYPAD */
+ case SDLK_KP0:
+ case SDLK_F5:
+ if(pressed)
+ {
+ sim_trigger_screendump();
+ return;
+ }
+ break;
+ }
+
+ /* Call to make up for scrollwheel target implementation. This is
+ * not handled in the main button.c driver, but on the target
+ * implementation (look at button-e200.c for example if you are trying to
+ * figure out why using button_get_data needed a hack before).
+ */
+#if defined(BUTTON_SCROLL_FWD) && defined(BUTTON_SCROLL_BACK)
+ if((new_btn == BUTTON_SCROLL_FWD || new_btn == BUTTON_SCROLL_BACK) &&
+ pressed)
+ {
+ /* Clear these buttons from the data - adding them to the queue is
+ * handled in the scrollwheel drivers for the targets. They do not
+ * store the scroll forward/back buttons in their button data for
+ * the button_read call.
+ */
+#ifdef HAVE_BACKLIGHT
+ backlight_on();
+#endif
+#ifdef HAVE_BUTTON_LIGHT
+ buttonlight_on();
+#endif
+ queue_post(&button_queue, new_btn, 1<<24);
+ new_btn &= ~(BUTTON_SCROLL_FWD | BUTTON_SCROLL_BACK);
+ }
+#endif
+
+ if (pressed)
+ btn |= new_btn;
+ else
+ btn &= ~new_btn;
+}
+#if defined(HAVE_BUTTON_DATA) && defined(HAVE_TOUCHSCREEN)
+int button_read_device(int* data)
+{
+ *data = mouse_coords;
+#else
+int button_read_device(void)
+{
+#endif
+#ifdef HAS_BUTTON_HOLD
+ int hold_button = button_hold();
+
+#ifdef HAVE_BACKLIGHT
+ /* light handling */
+ static int hold_button_old = false;
+ if (hold_button != hold_button_old)
+ {
+ hold_button_old = hold_button;
+ backlight_hold_changed(hold_button);
+ }
+#endif
+
+ if (hold_button)
+ return BUTTON_NONE;
+ else
+#endif
+ gui_message_loop();
+
+ return btn;
+}
+
+
+#ifdef HAVE_TOUCHSCREEN
+extern bool debug_wps;
+void mouse_tick_task(void)
+{
+ static int last_check = 0;
+ int x,y;
+ if (TIME_BEFORE(current_tick, last_check+(HZ/10)))
+ return;
+ last_check = current_tick;
+ if (SDL_GetMouseState(&x, &y) & SDL_BUTTON(SDL_BUTTON_LEFT))
+ {
+ if(background)
+ {
+ x -= UI_LCD_POSX;
+ y -= UI_LCD_POSY;
+
+ if(x<0 || y<0 || x>SIM_LCD_WIDTH || y>SIM_LCD_HEIGHT)
+ return;
+ }
+
+ mouse_coords = (x<<16)|y;
+ button_event(BUTTON_TOUCHSCREEN, true);
+ if (debug_wps)
+ printf("Mouse at: (%d, %d)\n", x, y);
+ }
+}
+#endif
+
+void button_init_device(void)
+{
+ SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+#ifdef HAVE_TOUCHSCREEN
+ tick_add_task(mouse_tick_task);
+#endif
+}
+
+/* Button maps: simulated key, x, y, radius, name */
+/* Run sim with --mapping to get coordinates */
+/* or --debugbuttons to check */
+/* The First matching button is returned */
+struct button_map {
+ int button, x, y, radius;
+ char *description;
+};
+
+#ifdef SANSA_FUZE
+struct button_map bm[] = {
+ { SDLK_KP8, 70, 265, 35, "Scroll Back" },
+ { SDLK_KP9, 141, 255, 31, "Play" },
+ { SDLK_KP_MULTIPLY, 228, 267, 18, "Home" },
+ { SDLK_LEFT, 69, 329, 31, "Left" },
+ { SDLK_SPACE, 141, 330, 20, "Select" },
+ { SDLK_RIGHT, 214, 331, 23, "Right" },
+ { SDLK_KP3, 142, 406, 30, "Menu" },
+ { SDLK_DOWN, 221, 384, 24, "Scroll Fwd" },
+ { SDLK_KP_MINUS, 270, 299, 25, "Power" },
+ { SDLK_h, 269, 358, 26, "Hold" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SANSA_CLIP)
+struct button_map bm[] = {
+ { SDLK_KP_MULTIPLY, 165, 158, 17, "Home" },
+ { SDLK_KP5, 102, 230, 29, "Select" },
+ { SDLK_KP8, 100, 179, 25, "Play" },
+ { SDLK_KP4, 53, 231, 21, "Left" },
+ { SDLK_KP6, 147, 232, 19, "Right" },
+ { SDLK_KP2, 105, 275, 22, "Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SANSA_C200) || defined(SANSA_C200V2)
+struct button_map bm[] = {
+
+ { SDLK_KP7, 84, 7, 21, "Vol Down" },
+ { SDLK_KP9, 158, 7, 20, "Vol Up" },
+ { SDLK_KP1, 173, 130, 27, "Record" },
+ { SDLK_KP5, 277, 75, 21, "Select" },
+ { SDLK_KP4, 233, 75, 24, "Left" },
+ { SDLK_KP6, 313, 74, 18, "Right" },
+ { SDLK_KP8, 276, 34, 15, "Play" },
+ { SDLK_KP2, 277, 119, 17, "Down" },
+ { SDLK_KP3, 314, 113, 19, "Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SANSA_E200V2) || defined(SANSA_E200)
+struct button_map bm[] = {
+ { SDLK_KP7, 5, 92, 18, "Record" },
+ { SDLK_KP9, 128, 295, 43, "Play" },
+ { SDLK_KP4, 42, 380, 33, "Left" },
+ { SDLK_KP5, 129, 378, 36, "Select" },
+ { SDLK_KP6, 218, 383, 30, "Right" },
+ { SDLK_KP3, 129, 461, 29, "Down" },
+ { SDLK_KP1, 55, 464, 20, "Menu" },
+ { SDLK_KP8, 92, 338, 17, "Scroll Back" },
+ { SDLK_KP2, 167, 342, 17, "Scroll Fwd" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SANSA_M200V4)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 54, 14, 16, "Power" },
+ { SDLK_KP7, 96, 13, 12, "Vol Down" },
+ { SDLK_KP9, 139, 14, 14, "Vol Up" },
+ { SDLK_KP5, 260, 82, 20, "Select" },
+ { SDLK_KP8, 258, 35, 30, "Play" },
+ { SDLK_KP4, 214, 84, 25, "Left" },
+ { SDLK_KP6, 300, 83, 24, "Right" },
+ { SDLK_KP2, 262, 125, 28, "Repeat" },
+ { SDLK_h, 113, 151, 21, "Hold" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IPOD_VIDEO)
+struct button_map bm[] = {
+ { SDLK_KP_PERIOD, 174, 350, 35, "Menu" },
+ { SDLK_KP8, 110, 380, 33, "Scroll Back" },
+ { SDLK_KP2, 234, 377, 34, "Scroll Fwd" },
+ { SDLK_KP4, 78, 438, 47, "Left" },
+ { SDLK_KP5, 172, 435, 43, "Select" },
+ { SDLK_KP6, 262, 438, 52, "Right" },
+ { SDLK_KP_PLUS, 172, 519, 43, "Play" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_MINI) || defined(IPOD_MINI2G)
+struct button_map bm[] = {
+ { SDLK_KP5, 92, 267, 29, "Select" },
+ { SDLK_KP4, 31, 263, 37, "Left" },
+ { SDLK_KP6, 150, 268, 33, "Right" },
+ { SDLK_KP_PERIOD, 93, 209, 30, "Menu" },
+ { SDLK_KP_PLUS, 93, 324, 25, "Play" },
+ { SDLK_KP8, 53, 220, 29, "Scroll Back" },
+ { SDLK_KP2, 134, 219, 31, "Scroll Fwd" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_3G)
+struct button_map bm[] = {
+ { SDLK_KP5, 108, 296, 26, "Select" },
+ { SDLK_KP8, 70, 255, 26, "Scroll Back" },
+ { SDLK_KP2, 149, 256, 28, "Scroll Fwd" },
+ { SDLK_KP4, 27, 186, 22, "Left" },
+ { SDLK_KP_PERIOD, 82, 185, 22, "Menu" },
+ { SDLK_KP_PERIOD, 133, 185, 21, "Play" },
+ { SDLK_KP6, 189, 188, 21, "Right" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_4G)
+struct button_map bm[] = {
+ { SDLK_KP5, 96, 269, 27, "Select" },
+ { SDLK_KP4, 39, 267, 30, "Left" },
+ { SDLK_KP6, 153, 270, 27, "Right" },
+ { SDLK_KP_PERIOD, 96, 219, 30, "Menu" },
+ { SDLK_KP_PLUS, 95, 326, 27, "Play" },
+ { SDLK_KP8, 57, 233, 29, "Scroll Back" },
+ { SDLK_KP2, 132, 226, 29, "Scroll Fwd" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_COLOR)
+struct button_map bm[] = {
+ { SDLK_KP5, 128, 362, 35, "Select" },
+ { SDLK_KP4, 55, 358, 38, "Left" },
+ { SDLK_KP6, 203, 359, 39, "Right" },
+ { SDLK_KP_PERIOD, 128, 282, 34, "Menu" },
+ { SDLK_KP_PLUS, 129, 439, 41, "Play" },
+ { SDLK_KP8, 76, 309, 34, "Scroll Back" },
+ { SDLK_KP2, 182, 311, 45, "Scroll Fwd" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_1G2G)
+struct button_map bm[] = {
+ { SDLK_KP5, 112, 265, 31, "Select" },
+ { SDLK_KP8, 74, 224, 28, "Scroll Back" },
+ { SDLK_KP2, 146, 228, 28, "Scroll Fwd" },
+ /* Dummy button to make crescent shape */
+ { SDLK_y, 112, 265, 76, "None" },
+ { SDLK_KP8, 74, 224, 28, "Scroll Back" },
+ { SDLK_KP2, 146, 228, 28, "Scroll Fwd" },
+ { SDLK_KP6, 159, 268, 64, "Right" },
+ { SDLK_KP4, 62, 266, 62, "Left" },
+ { SDLK_KP_PERIOD, 111, 216, 64, "Menu" },
+ { SDLK_KP_PLUS, 111, 326, 55, "Down" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_NANO)
+struct button_map bm[] = {
+ { SDLK_KP5, 98, 316, 37, "Select" },
+ { SDLK_KP4, 37, 312, 28, "Left" },
+ { SDLK_KP6, 160, 313, 25, "Right" },
+ { SDLK_KP_PERIOD,102, 256, 23, "Menu" },
+ { SDLK_KP_PLUS, 99, 378, 28, "Play" },
+ { SDLK_KP8, 58, 272, 24, "Scroll Back" },
+ { SDLK_KP2, 141, 274, 22, "Scroll Fwd" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_NANO2G)
+struct button_map bm[] = {
+ { SDLK_KP5, 118, 346, 37, "Select" },
+ { SDLK_KP4, 51, 345, 28, "Left" },
+ { SDLK_KP6, 180, 346, 26, "Right" },
+ { SDLK_KP_PERIOD, 114, 286, 23, "Menu" },
+ { SDLK_KP_PLUS, 115, 412, 27, "Down" },
+ { SDLK_KP8, 67, 303, 28, "Scroll Back" },
+ { SDLK_KP2, 163, 303, 27, "Scroll Fwd" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (COWON_D2)
+struct button_map bm[] = {
+ { SDLK_DELETE, 51, 14, 17, "Power" },
+ { SDLK_h, 138, 14, 16, "Hold" },
+ { SDLK_MINUS, 320, 14, 10, "Minus" },
+ { SDLK_INSERT, 347, 13, 13, "Menu" },
+ { SDLK_KP_PLUS, 374, 14, 12, "Plus" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IAUDIO_M3)
+struct button_map bm[] = {
+ { SDLK_KP5, 256, 72, 29, "Play" },
+ { SDLK_KP6, 255, 137, 28, "Right" },
+ { SDLK_KP4, 257, 201, 26, "Left" },
+ { SDLK_KP8, 338, 31, 27, "Up" },
+ { SDLK_KP2, 339, 92, 23, "Down" },
+ { SDLK_KP_PERIOD, 336, 50, 23, "Mode" },
+ { SDLK_KP_DIVIDE, 336, 147, 23, "Rec" },
+ { SDLK_h, 336, 212, 30, "Hold" },
+ /* remote */
+ { SDLK_SPACE, 115, 308, 20, "RC Play" },
+ { SDLK_RIGHT, 85, 308, 20, "RC Rew" },
+ { SDLK_LEFT, 143, 308, 20, "RC FF" },
+ { SDLK_UP, 143, 498, 20, "RC Up" },
+ { SDLK_DOWN, 85, 498, 20, "RC Down" },
+ { SDLK_INSERT, 212, 308, 30, "RC Mode" },
+ { SDLK_F1, 275, 308, 25, "RC Rec" },
+ { SDLK_KP_ENTER, 115, 498, 20, "RC Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IAUDIO_M5)
+struct button_map bm[] = {
+ { SDLK_KP_ENTER, 333, 41, 17, "Enter" },
+ { SDLK_h, 334, 74, 21, "Hold" },
+ { SDLK_KP_DIVIDE, 333, 142, 24, "Record" },
+ { SDLK_KP_PLUS, 332, 213, 20, "Play" },
+ { SDLK_KP5, 250, 291, 19, "Select" },
+ { SDLK_KP8, 249, 236, 32, "Up" },
+ { SDLK_KP4, 194, 292, 29, "Left" },
+ { SDLK_KP6, 297, 290, 27, "Right" },
+ { SDLK_KP2, 252, 335, 28, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IAUDIO_7)
+struct button_map bm[] = {
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IAUDIO_X5)
+struct button_map bm[] = {
+ { SDLK_KP_ENTER, 275, 38, 17, "Power" },
+ { SDLK_h, 274, 83, 16, "Hold" },
+ { SDLK_KP_DIVIDE, 276, 128, 22, "Record" },
+ { SDLK_KP_PLUS, 274, 186, 22, "Play" },
+ { SDLK_KP5, 200, 247, 16, "Select" },
+ { SDLK_KP8, 200, 206, 16, "Up" },
+ { SDLK_KP4, 163, 248, 19, "Left" },
+ { SDLK_KP6, 225, 247, 24, "Right" },
+ { SDLK_KP2, 199, 279, 20, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (ARCHOS_PLAYER)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 79, 252, 23, "On" },
+ { SDLK_KP_PERIOD, 81, 310, 20, "Menu" },
+ { SDLK_KP8, 154, 237, 28, "Play" },
+ { SDLK_KP4, 121, 282, 23, "Left" },
+ { SDLK_KP6, 187, 282, 22, "Right" },
+ { SDLK_KP2, 157, 312, 20, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (ARCHOS_RECORDER)
+struct button_map bm[] = {
+ { SDLK_F1, 94, 205, 22, "F1" },
+ { SDLK_F2, 136, 204, 21, "F2" },
+ { SDLK_F3, 174, 204, 24, "F3" },
+ { SDLK_KP_PLUS, 75, 258, 19, "On" },
+ { SDLK_KP_ENTER, 76, 307, 15, "Off" },
+ { SDLK_KP5, 151, 290, 20, "Select" },
+ { SDLK_KP8, 152, 251, 23, "Up" },
+ { SDLK_KP4, 113, 288, 26, "Left" },
+ { SDLK_KP6, 189, 291, 23, "Right" },
+ { SDLK_KP2, 150, 327, 27, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (ARCHOS_FMRECORDER) || defined (ARCHOS_RECORDERV2)
+struct button_map bm[] = {
+ { SDLK_F1, 88, 210, 28, "F1" },
+ { SDLK_F2, 144, 212, 28, "F2" },
+ { SDLK_F3, 197, 212, 28, "F3" },
+ { SDLK_KP5, 144, 287, 21, "Select" },
+ { SDLK_KP_PLUS, 86, 320, 13, "Menu" },
+ { SDLK_KP_ENTER, 114, 347, 13, "Stop" },
+ { SDLK_y, 144, 288, 31, "None" },
+ { SDLK_KP8, 144, 259, 25, "Up" },
+ { SDLK_KP2, 144, 316, 31, "Down" },
+ { SDLK_KP6, 171, 287, 32, "Right" },
+ { SDLK_KP4, 117, 287, 31, "Left" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (ARCHOS_ONDIOSP) || defined (ARCHOS_ONDIOFM)
+struct button_map bm[] = {
+ { SDLK_KP_ENTER, 75, 23, 30, "Enter" },
+ { SDLK_KP8, 75, 174, 33, "KP8" },
+ { SDLK_KP4, 26, 186, 48, "KP4" },
+ { SDLK_KP6, 118, 196, 32, "KP6" },
+ { SDLK_KP2, 75, 234, 16, "KP2" },
+ { SDLK_KP_PERIOD, 54, 250, 24, "Period" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IRIVER_H10)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 38, 70, 37, "Power" },
+ { SDLK_KP4, 123, 194, 26, "Cancel" },
+ { SDLK_KP6, 257, 195, 34, "Select" },
+ { SDLK_KP8, 190, 221, 28, "Up" },
+ { SDLK_KP2, 192, 320, 27, "Down" },
+ { SDLK_KP_DIVIDE, 349, 49, 20, "Rew" },
+ { SDLK_KP5, 349, 96, 20, "Play" },
+ { SDLK_KP_MULTIPLY, 350, 141, 23, "FF" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IRIVER_H10_5GB)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 34, 76, 23, "Power" },
+ { SDLK_KP4, 106, 222, 28, "Cancel" },
+ { SDLK_KP6, 243, 220, 31, "Select" },
+ { SDLK_KP8, 176, 254, 34, "Up" },
+ { SDLK_KP2, 175, 371, 35, "Down" },
+ { SDLK_KP_DIVIDE, 319, 63, 26, "Rew" },
+ { SDLK_KP5, 320, 124, 26, "Play" },
+ { SDLK_KP_MULTIPLY, 320, 181, 32, "FF" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IRIVER_H120) || defined (IRIVER_H100)
+struct button_map bm[] = {
+ { SDLK_KP_DIVIDE, 46, 162, 13, "Record" },
+ { SDLK_KP_PLUS, 327, 36, 16, "Play" },
+ { SDLK_KP_ENTER, 330, 99, 18, "Stop" },
+ { SDLK_KP_PERIOD, 330, 163, 18, "AB" },
+ { SDLK_KP5, 186, 227, 27, "5" },
+ { SDLK_KP8, 187, 185, 19, "8" },
+ { SDLK_KP4, 142, 229, 23, "4" },
+ { SDLK_KP6, 231, 229, 22, "6" },
+ { SDLK_KP2, 189, 272, 28, "2" },
+/* Remote Buttons */
+ { SDLK_KP_ENTER, 250, 404, 20, "Stop" },
+ { SDLK_SPACE, 285, 439, 29, "Space" },
+ { SDLK_h, 336, 291, 24, "Hold" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IRIVER_H300)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 56, 335, 20, "Play" },
+ { SDLK_KP8, 140, 304, 29, "Up" },
+ { SDLK_KP_DIVIDE, 233, 331, 23, "Record" },
+ { SDLK_KP_ENTER, 54, 381, 24, "Stop" },
+ { SDLK_KP4, 100, 353, 17, "Left" },
+ { SDLK_KP5, 140, 351, 19, "Navi" },
+ { SDLK_KP6, 185, 356, 19, "Right" },
+ { SDLK_KP_PERIOD, 230, 380, 20, "AB" },
+ { SDLK_KP2, 142, 402, 24, "Down" },
+ { SDLK_KP_ENTER, 211, 479, 21, "Stop" },
+ { SDLK_KP_PLUS, 248, 513, 29, "Play" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (MROBE_500)
+struct button_map bm[] = {
+ { SDLK_KP9, 171, 609, 9, "Play" },
+ { SDLK_KP4, 158, 623, 9, "Left" },
+ { SDLK_KP6, 184, 622, 9, "Right" },
+ { SDLK_KP7, 171, 638, 11, "Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (MROBE_100)
+struct button_map bm[] = {
+ { SDLK_KP7, 80, 233, 30, "Menu" },
+ { SDLK_KP8, 138, 250, 19, "Up" },
+ { SDLK_KP9, 201, 230, 27, "Play" },
+ { SDLK_KP4, 63, 305, 25, "Left" },
+ { SDLK_KP5, 125, 309, 28, "Select" },
+ { SDLK_KP6, 200, 307, 35, "Right" },
+ { SDLK_KP1, 52, 380, 32, "Display" },
+ { SDLK_KP2, 125, 363, 30, "Down" },
+ { SDLK_KP9, 168, 425, 10, "Play" },
+ { SDLK_KP4, 156, 440, 11, "Left" },
+ { SDLK_KP6, 180, 440, 13, "Right" },
+ { SDLK_KP7, 169, 452, 10, "Menu" },
+ { SDLK_KP_MULTIPLY, 222, 15, 16, "Power" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (GIGABEAT_F)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 361, 187, 22, "Power" },
+ { SDLK_KP_PERIOD, 361, 270, 17, "Menu" },
+ { SDLK_KP9, 365, 345, 26, "Vol Up" },
+ { SDLK_KP3, 363, 433, 25, "Vol Down" },
+ { SDLK_KP_ENTER, 365, 520, 19, "A" },
+ { SDLK_KP8, 167, 458, 35, "Up" },
+ { SDLK_KP4, 86, 537, 29, "Left" },
+ { SDLK_KP5, 166, 536, 30, "Select" },
+ { SDLK_KP6, 248, 536, 30, "Right" },
+ { SDLK_KP2, 169, 617, 28, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (GIGABEAT_S)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 416, 383, 23, "Play" },
+ { SDLK_KP7, 135, 442, 46, "Back" },
+ { SDLK_KP9, 288, 447, 35, "Menu" },
+ { SDLK_KP8, 214, 480, 32, "Up" },
+ { SDLK_KP4, 128, 558, 33, "Left" },
+ { SDLK_KP5, 214, 556, 34, "Select" },
+ { SDLK_KP6, 293, 558, 35, "Right" },
+ { SDLK_KP2, 214, 637, 38, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SAMSUNG_YH820)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 330, 53, 23, "Record" },
+ { SDLK_KP7, 132, 208, 21, "Left" },
+ { SDLK_KP5, 182, 210, 18, "Play" },
+ { SDLK_KP9, 234, 211, 22, "Right" },
+ { SDLK_KP8, 182, 260, 15, "Up" },
+ { SDLK_KP4, 122, 277, 29, "Menu" },
+ { SDLK_KP6, 238, 276, 25, "Select" },
+ { SDLK_KP2, 183, 321, 24, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SAMSUNG_YH920) || defined (SAMSUNG_YH925)
+struct button_map bm[] = {
+ { SDLK_KP9, 370, 32, 15, "FF" },
+ { SDLK_KP5, 369, 84, 25, "Play" },
+ { SDLK_KP5, 367, 125, 27, "Play" },
+ { SDLK_KP3, 369, 188, 17, "Rew" },
+ { SDLK_KP_PLUS, 370, 330, 30, "Record" },
+ { SDLK_KP4, 146, 252, 32, "Menu" },
+ { SDLK_KP8, 204, 226, 27, "Up" },
+ { SDLK_KP6, 257, 250, 34, "Select" },
+ { SDLK_KP2, 205, 294, 35, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (ONDA_VX747) || defined (ONDA_VX747P)
+struct button_map bm[] = {
+ { SDLK_MINUS, 113, 583, 28, "Minus" },
+ { SDLK_PLUS, 227, 580, 28, "Plus" },
+ { SDLK_RETURN, 171, 583, 34, "Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (PHILIPS_SA9200)
+struct button_map bm[] = {
+ { SDLK_KP_ENTER, 25, 155, 33, "Power" },
+ { SDLK_PAGEUP, 210, 98, 31, "Vol Up" },
+ { SDLK_PAGEDOWN, 210, 168, 34, "Vol Down" },
+ { SDLK_KP7, 40, 249, 26, "Prev" },
+ { SDLK_KP8, 110, 247, 22, "Up" },
+ { SDLK_KP9, 183, 249, 31, "Next" },
+ { SDLK_KP4, 45, 305, 25, "Left" },
+ { SDLK_KP5, 111, 304, 24, "Play" },
+ { SDLK_KP6, 183, 304, 21, "Right" },
+ { SDLK_KP1, 43, 377, 21, "Menu" },
+ { SDLK_KP2, 112, 371, 24, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (CREATIVE_ZVM) || defined (CREATIVE_ZVM60GB) || \
+ defined (CREATIVE_ZV)
+struct button_map bm[] = {
+ { SDLK_KP7, 52, 414, 35, "Custom" },
+ { SDLK_KP8, 185, 406, 55, "Up" },
+ { SDLK_KP9, 315, 421, 46, "Play" },
+ { SDLK_KP4, 122, 500, 41, "Left" },
+ { SDLK_KP6, 247, 493, 49, "Right" },
+ { SDLK_KP1, 58, 577, 49, "Back" },
+ { SDLK_KP2, 186, 585, 46, "Down" },
+ { SDLK_KP3, 311, 569, 47, "Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (MPIO_HD200)
+struct button_map bm[] = {
+ { SDLK_ESCAPE, 369, 257, 20, "Rec" },
+ { SDLK_RETURN, 369, 305, 20, "Play/Stop" },
+ { SDLK_UP, 353, 168, 10, "Rew" },
+ { SDLK_DOWN, 353, 198, 10, "FF" },
+ { SDLK_SPACE, 353, 186, 10, "Select" },
+ { SDLK_LEFT, 123, 67, 20, "Vol Down" },
+ { SDLK_RIGHT, 206, 67, 20, "Vol Up" },
+ { SDLK_h, 369, 402, 30, "Hold" },
+ { 0, 0, 0, 0, "None" }
+};
+#else
+struct button_map bm[] = {
+ { 0, 0, 0, 0, ""}
+};
+#endif
+
+static int xy2button( int x, int y)
+{
+ int i;
+ extern bool debug_buttons;
+
+ for ( i = 0; bm[i].button; i++ )
+ /* check distance from center of button < radius */
+ if ( ( (x-bm[i].x)*(x-bm[i].x) ) + ( ( y-bm[i].y)*(y-bm[i].y) ) < bm[i].radius*bm[i].radius ) {
+ if (debug_buttons)
+ printf("Button: %s\n", bm[i].description );
+ return bm[i].button;
+ }
+ return 0;
+}
diff --git a/firmware/target/hosted/sdl/button-sdl.h b/firmware/target/hosted/sdl/button-sdl.h
new file mode 100644
index 0000000000..75a68c49bc
--- /dev/null
+++ b/firmware/target/hosted/sdl/button-sdl.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 by Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+
+#ifndef __BUTTON_SDL_H__
+#define __BUTTON_SDL_H__
+
+#include <stdbool.h>
+#include "config.h"
+
+bool button_hold(void);
+void button_init_device(void);
+
+#endif /* __BUTTON_SDL_H__ */
diff --git a/firmware/target/hosted/sdl/kernel-sdl.c b/firmware/target/hosted/sdl/kernel-sdl.c
new file mode 100644
index 0000000000..d796921e35
--- /dev/null
+++ b/firmware/target/hosted/sdl/kernel-sdl.c
@@ -0,0 +1,162 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Felix Arends
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <SDL.h>
+#include <SDL_thread.h>
+#include "memory.h"
+#include "system-sdl.h"
+#include "thread-sdl.h"
+#include "kernel.h"
+#include "thread.h"
+#include "panic.h"
+#include "debug.h"
+
+static SDL_TimerID tick_timer_id;
+long start_tick;
+
+/* Condition to signal that "interrupts" may proceed */
+static SDL_cond *sim_thread_cond;
+/* Mutex to serialize changing levels and exclude other threads while
+ * inside a handler */
+static SDL_mutex *sim_irq_mtx;
+static int interrupt_level = HIGHEST_IRQ_LEVEL;
+static int handlers_pending = 0;
+static int status_reg = 0;
+
+/* Nescessary logic:
+ * 1) All threads must pass unblocked
+ * 2) Current handler must always pass unblocked
+ * 3) Threads must be excluded when irq routine is running
+ * 4) No more than one handler routine should execute at a time
+ */
+int set_irq_level(int level)
+{
+ SDL_LockMutex(sim_irq_mtx);
+
+ int oldlevel = interrupt_level;
+
+ if (status_reg == 0 && level == 0 && oldlevel != 0)
+ {
+ /* Not in a handler and "interrupts" are being reenabled */
+ if (handlers_pending > 0)
+ SDL_CondSignal(sim_thread_cond);
+ }
+
+ interrupt_level = level; /* save new level */
+
+ SDL_UnlockMutex(sim_irq_mtx);
+ return oldlevel;
+}
+
+void sim_enter_irq_handler(void)
+{
+ SDL_LockMutex(sim_irq_mtx);
+ handlers_pending++;
+
+ if(interrupt_level != 0)
+ {
+ /* "Interrupts" are disabled. Wait for reenable */
+ SDL_CondWait(sim_thread_cond, sim_irq_mtx);
+ }
+
+ status_reg = 1;
+}
+
+void sim_exit_irq_handler(void)
+{
+ if (--handlers_pending > 0)
+ SDL_CondSignal(sim_thread_cond);
+
+ status_reg = 0;
+ SDL_UnlockMutex(sim_irq_mtx);
+}
+
+static bool sim_kernel_init(void)
+{
+ sim_irq_mtx = SDL_CreateMutex();
+ if (sim_irq_mtx == NULL)
+ {
+ panicf("Cannot create sim_handler_mtx\n");
+ return false;
+ }
+
+ sim_thread_cond = SDL_CreateCond();
+ if (sim_thread_cond == NULL)
+ {
+ panicf("Cannot create sim_thread_cond\n");
+ return false;
+ }
+
+ return true;
+}
+
+void sim_kernel_shutdown(void)
+{
+ SDL_RemoveTimer(tick_timer_id);
+ SDL_DestroyMutex(sim_irq_mtx);
+ SDL_DestroyCond(sim_thread_cond);
+}
+
+Uint32 tick_timer(Uint32 interval, void *param)
+{
+ long new_tick;
+
+ (void) interval;
+ (void) param;
+
+ new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ);
+
+ while(new_tick != current_tick)
+ {
+ sim_enter_irq_handler();
+
+ /* Run through the list of tick tasks - increments tick
+ * on each iteration. */
+ call_tick_tasks();
+
+ sim_exit_irq_handler();
+ }
+
+ return 1;
+}
+
+void tick_start(unsigned int interval_in_ms)
+{
+ if (!sim_kernel_init())
+ {
+ panicf("Could not initialize kernel!");
+ exit(-1);
+ }
+
+ if (tick_timer_id != NULL)
+ {
+ SDL_RemoveTimer(tick_timer_id);
+ tick_timer_id = NULL;
+ }
+ else
+ {
+ start_tick = SDL_GetTicks();
+ }
+
+ tick_timer_id = SDL_AddTimer(interval_in_ms, tick_timer, NULL);
+}
diff --git a/firmware/target/hosted/sdl/lcd-bitmap.c b/firmware/target/hosted/sdl/lcd-bitmap.c
new file mode 100644
index 0000000000..6dfbffff37
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-bitmap.c
@@ -0,0 +1,416 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "debug.h"
+#include "sim-ui-defines.h"
+#include "system.h"
+#include "lcd-sdl.h"
+#include "screendump.h"
+
+SDL_Surface* lcd_surface;
+
+#if LCD_DEPTH <= 8
+#ifdef HAVE_BACKLIGHT
+SDL_Color lcd_bl_color_dark = {RED_CMP(LCD_BL_DARKCOLOR),
+ GREEN_CMP(LCD_BL_DARKCOLOR),
+ BLUE_CMP(LCD_BL_DARKCOLOR), 0};
+SDL_Color lcd_bl_color_bright = {RED_CMP(LCD_BL_BRIGHTCOLOR),
+ GREEN_CMP(LCD_BL_BRIGHTCOLOR),
+ BLUE_CMP(LCD_BL_BRIGHTCOLOR), 0};
+#ifdef HAVE_LCD_SPLIT
+SDL_Color lcd_bl_color2_dark = {RED_CMP(LCD_BL_DARKCOLOR_2),
+ GREEN_CMP(LCD_BL_DARKCOLOR_2),
+ BLUE_CMP(LCD_BL_DARKCOLOR_2), 0};
+SDL_Color lcd_bl_color2_bright = {RED_CMP(LCD_BL_BRIGHTCOLOR_2),
+ GREEN_CMP(LCD_BL_BRIGHTCOLOR_2),
+ BLUE_CMP(LCD_BL_BRIGHTCOLOR_2), 0};
+#endif
+#endif /* HAVE_BACKLIGHT */
+SDL_Color lcd_color_dark = {RED_CMP(LCD_DARKCOLOR),
+ GREEN_CMP(LCD_DARKCOLOR),
+ BLUE_CMP(LCD_DARKCOLOR), 0};
+SDL_Color lcd_color_bright = {RED_CMP(LCD_BRIGHTCOLOR),
+ GREEN_CMP(LCD_BRIGHTCOLOR),
+ BLUE_CMP(LCD_BRIGHTCOLOR), 0};
+#ifdef HAVE_LCD_SPLIT
+SDL_Color lcd_color2_dark = {RED_CMP(LCD_DARKCOLOR_2),
+ GREEN_CMP(LCD_DARKCOLOR_2),
+ BLUE_CMP(LCD_DARKCOLOR_2), 0};
+SDL_Color lcd_color2_bright = {RED_CMP(LCD_BRIGHTCOLOR_2),
+ GREEN_CMP(LCD_BRIGHTCOLOR_2),
+ BLUE_CMP(LCD_BRIGHTCOLOR_2), 0};
+#endif
+
+#ifdef HAVE_LCD_SPLIT
+#define NUM_SHADES 128
+#else
+#define NUM_SHADES 129
+#endif
+
+#else /* LCD_DEPTH > 8 */
+
+#ifdef HAVE_TRANSFLECTIVE_LCD
+#define BACKLIGHT_OFF_ALPHA 85 /* 1/3 brightness */
+#else
+#define BACKLIGHT_OFF_ALPHA 0 /* pitch black */
+#endif
+
+#endif /* LCD_DEPTH */
+
+#if LCD_DEPTH < 8
+unsigned long (*lcd_ex_getpixel)(int, int) = NULL;
+#endif /* LCD_DEPTH < 8 */
+
+#if LCD_DEPTH == 2
+/* Only defined for positive, non-split LCD for now */
+static const unsigned char colorindex[4] = {128, 85, 43, 0};
+#endif
+
+static unsigned long get_lcd_pixel(int x, int y)
+{
+#if LCD_DEPTH == 1
+#ifdef HAVE_NEGATIVE_LCD
+ return (lcd_framebuffer[y/8][x] & (1 << (y & 7))) ? (NUM_SHADES-1) : 0;
+#else
+ return (lcd_framebuffer[y/8][x] & (1 << (y & 7))) ? 0 : (NUM_SHADES-1);
+#endif
+#elif LCD_DEPTH == 2
+#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
+ return colorindex[(lcd_framebuffer[y][x/4] >> (2 * (~x & 3))) & 3];
+#elif LCD_PIXELFORMAT == VERTICAL_PACKING
+ return colorindex[(lcd_framebuffer[y/4][x] >> (2 * (y & 3))) & 3];
+#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
+ unsigned bits = (lcd_framebuffer[y/8][x] >> (y & 7)) & 0x0101;
+ return colorindex[(bits | (bits >> 7)) & 3];
+#endif
+#elif LCD_DEPTH == 16
+#if LCD_PIXELFORMAT == RGB565SWAPPED
+ unsigned bits = lcd_framebuffer[y][x];
+ return (bits >> 8) | (bits << 8);
+#else
+#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+ return *(&lcd_framebuffer[0][0]+LCD_HEIGHT*x+y);
+#else
+ return lcd_framebuffer[y][x];
+#endif
+#endif
+#endif
+}
+
+void lcd_update(void)
+{
+ /* update a full screen rect */
+ lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
+}
+
+void lcd_update_rect(int x_start, int y_start, int width, int height)
+{
+ sdl_update_rect(lcd_surface, x_start, y_start, width, height,
+ LCD_WIDTH, LCD_HEIGHT, get_lcd_pixel);
+ sdl_gui_update(lcd_surface, x_start, y_start, width,
+ height + LCD_SPLIT_LINES, SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
+ background ? UI_LCD_POSX : 0, background? UI_LCD_POSY : 0);
+}
+
+#ifdef HAVE_BACKLIGHT
+void sim_backlight(int value)
+{
+#if LCD_DEPTH <= 8
+ if (value > 0) {
+ sdl_set_gradient(lcd_surface, &lcd_bl_color_dark,
+ &lcd_bl_color_bright, 0, NUM_SHADES);
+#ifdef HAVE_LCD_SPLIT
+ sdl_set_gradient(lcd_surface, &lcd_bl_color2_dark,
+ &lcd_bl_color2_bright, NUM_SHADES, NUM_SHADES);
+#endif
+ } else {
+ sdl_set_gradient(lcd_surface, &lcd_color_dark,
+ &lcd_color_bright, 0, NUM_SHADES);
+#ifdef HAVE_LCD_SPLIT
+ sdl_set_gradient(lcd_surface, &lcd_color2_dark,
+ &lcd_color2_bright, NUM_SHADES, NUM_SHADES);
+#endif
+ }
+#else /* LCD_DEPTH > 8 */
+ SDL_SetAlpha(lcd_surface, SDL_SRCALPHA, (value * 255) / 100);
+#endif /* LCD_DEPTH */
+
+ sdl_gui_update(lcd_surface, 0, 0, SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
+ SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
+ background ? UI_LCD_POSX : 0, background? UI_LCD_POSY : 0);
+}
+#endif /* HAVE_BACKLIGHT */
+
+/* initialise simulator lcd driver */
+void sim_lcd_init(void)
+{
+#if LCD_DEPTH == 16
+ lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ SIM_LCD_WIDTH * display_zoom,
+ SIM_LCD_HEIGHT * display_zoom,
+ LCD_DEPTH, 0, 0, 0, 0);
+#elif LCD_DEPTH <= 8
+ lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ SIM_LCD_WIDTH * display_zoom,
+ SIM_LCD_HEIGHT * display_zoom,
+ 8, 0, 0, 0, 0);
+
+#ifdef HAVE_BACKLIGHT
+ sdl_set_gradient(lcd_surface, &lcd_bl_color_dark,
+ &lcd_bl_color_bright, 0, NUM_SHADES);
+#ifdef HAVE_LCD_SPLIT
+ sdl_set_gradient(lcd_surface, &lcd_bl_color2_dark,
+ &lcd_bl_color2_bright, NUM_SHADES, NUM_SHADES);
+#endif
+#else /* !HAVE_BACKLIGHT */
+ sdl_set_gradient(lcd_surface, &lcd_color_dark,
+ &lcd_color_bright, 0, NUM_SHADES);
+#ifdef HAVE_LCD_SPLIT
+ sdl_set_gradient(lcd_surface, &lcd_color2_dark,
+ &lcd_color2_bright, NUM_SHADES, NUM_SHADES);
+#endif
+#endif /* !HAVE_BACKLIGHT */
+#endif /* LCD_DEPTH */
+}
+
+#if LCD_DEPTH < 8
+void sim_lcd_ex_init(unsigned long (*getpixel)(int, int))
+{
+ lcd_ex_getpixel = getpixel;
+}
+
+void sim_lcd_ex_update_rect(int x_start, int y_start, int width, int height)
+{
+ if (lcd_ex_getpixel) {
+ sdl_update_rect(lcd_surface, x_start, y_start, width, height,
+ LCD_WIDTH, LCD_HEIGHT, lcd_ex_getpixel);
+ sdl_gui_update(lcd_surface, x_start, y_start, width,
+ height + LCD_SPLIT_LINES, SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
+ background ? UI_LCD_POSX : 0,
+ background ? UI_LCD_POSY : 0);
+ }
+}
+#endif
+
+#ifdef HAVE_LCD_COLOR
+/**
+ * |R| |1.000000 -0.000001 1.402000| |Y'|
+ * |G| = |1.000000 -0.334136 -0.714136| |Pb|
+ * |B| |1.000000 1.772000 0.000000| |Pr|
+ * Scaled, normalized, rounded and tweaked to yield RGB 565:
+ * |R| |74 0 101| |Y' - 16| >> 9
+ * |G| = |74 -24 -51| |Cb - 128| >> 8
+ * |B| |74 128 0| |Cr - 128| >> 9
+ */
+#define YFAC (74)
+#define RVFAC (101)
+#define GUFAC (-24)
+#define GVFAC (-51)
+#define BUFAC (128)
+
+static inline int clamp(int val, int min, int max)
+{
+ if (val < min)
+ val = min;
+ else if (val > max)
+ val = max;
+ return val;
+}
+
+void lcd_yuv_set_options(unsigned options)
+{
+ (void)options;
+}
+
+/* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
+ in the core */
+void lcd_blit_yuv(unsigned char * const src[3],
+ int src_x, int src_y, int stride,
+ int x, int y, int width, int height)
+{
+ const unsigned char *ysrc, *usrc, *vsrc;
+ int linecounter;
+ fb_data *dst, *row_end;
+ long z;
+
+ /* width and height must be >= 2 and an even number */
+ width &= ~1;
+ linecounter = height >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst = &lcd_framebuffer[y][x];
+ row_end = dst + width;
+#else
+ dst = &lcd_framebuffer[x][LCD_WIDTH - y - 1];
+ row_end = dst + LCD_WIDTH * width;
+#endif
+
+ z = stride * src_y;
+ ysrc = src[0] + z + src_x;
+ usrc = src[1] + (z >> 2) + (src_x >> 1);
+ vsrc = src[2] + (usrc - src[1]);
+
+ /* stride => amount to jump from end of last row to start of next */
+ stride -= width;
+
+ /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
+
+ do
+ {
+ do
+ {
+ int y, cb, cr, rv, guv, bu, r, g, b;
+
+ y = YFAC*(*ysrc++ - 16);
+ cb = *usrc++ - 128;
+ cr = *vsrc++ - 128;
+
+ rv = RVFAC*cr;
+ guv = GUFAC*cb + GVFAC*cr;
+ bu = BUFAC*cb;
+
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+
+ y = YFAC*(*ysrc++ - 16);
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+ }
+ while (dst < row_end);
+
+ ysrc += stride;
+ usrc -= width >> 1;
+ vsrc -= width >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ row_end += LCD_WIDTH;
+ dst += LCD_WIDTH - width;
+#else
+ row_end -= 1;
+ dst -= LCD_WIDTH*width + 1;
+#endif
+
+ do
+ {
+ int y, cb, cr, rv, guv, bu, r, g, b;
+
+ y = YFAC*(*ysrc++ - 16);
+ cb = *usrc++ - 128;
+ cr = *vsrc++ - 128;
+
+ rv = RVFAC*cr;
+ guv = GUFAC*cb + GVFAC*cr;
+ bu = BUFAC*cb;
+
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+
+ y = YFAC*(*ysrc++ - 16);
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+ }
+ while (dst < row_end);
+
+ ysrc += stride;
+ usrc += stride >> 1;
+ vsrc += stride >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ row_end += LCD_WIDTH;
+ dst += LCD_WIDTH - width;
+#else
+ row_end -= 1;
+ dst -= LCD_WIDTH*width + 1;
+#endif
+ }
+ while (--linecounter > 0);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ lcd_update_rect(x, y, width, height);
+#else
+ lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
+#endif
+}
+#endif /* HAVE_LCD_COLOR */
diff --git a/firmware/target/hosted/sdl/lcd-bitmap.h b/firmware/target/hosted/sdl/lcd-bitmap.h
new file mode 100644
index 0000000000..a898744b41
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-bitmap.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __LCDBITMAP_H__
+#define __LCDBITMAP_H__
+
+#include "lcd.h"
+#include "SDL.h"
+
+void sim_lcd_init(void);
+#if LCD_DEPTH < 8
+void sim_lcd_ex_init(unsigned long (*getpixel)(int, int));
+void sim_lcd_ex_update_rect(int x, int y, int width, int height);
+#endif
+
+#endif /* #ifndef __LCDBITMAP_H__ */
+
diff --git a/firmware/target/hosted/sdl/lcd-charcells.c b/firmware/target/hosted/sdl/lcd-charcells.c
new file mode 100644
index 0000000000..900cbb04dd
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-charcells.c
@@ -0,0 +1,198 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "system.h"
+#include "debug.h"
+#include "lcd.h"
+#include "lcd-charcell.h"
+#include "screendump.h"
+#include "general.h"
+
+#include "lcd-playersim.h"
+#include "sim-ui-defines.h"
+#include "lcd-sdl.h"
+
+/* can't include file.h here */
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+/* extern functions, needed for screendump() */
+extern int sim_creat(const char *name, mode_t mode);
+
+SDL_Surface* lcd_surface;
+
+SDL_Color lcd_bl_color_dark = {RED_CMP(LCD_BL_DARKCOLOR),
+ GREEN_CMP(LCD_BL_DARKCOLOR),
+ BLUE_CMP(LCD_BL_DARKCOLOR), 0};
+SDL_Color lcd_bl_color_bright = {RED_CMP(LCD_BL_BRIGHTCOLOR),
+ GREEN_CMP(LCD_BL_BRIGHTCOLOR),
+ BLUE_CMP(LCD_BL_BRIGHTCOLOR), 0};
+SDL_Color lcd_color_dark = {RED_CMP(LCD_DARKCOLOR),
+ GREEN_CMP(LCD_DARKCOLOR),
+ BLUE_CMP(LCD_DARKCOLOR), 0};
+SDL_Color lcd_color_bright = {RED_CMP(LCD_BRIGHTCOLOR),
+ GREEN_CMP(LCD_BRIGHTCOLOR),
+ BLUE_CMP(LCD_BRIGHTCOLOR), 0};
+
+
+static unsigned long get_lcd_pixel(int x, int y)
+{
+ return sim_lcd_framebuffer[y][x];
+}
+
+void sim_lcd_update_rect(int x_start, int y_start, int width, int height)
+{
+ sdl_update_rect(lcd_surface, x_start, y_start, width, height,
+ SIM_LCD_WIDTH, SIM_LCD_HEIGHT, get_lcd_pixel);
+ sdl_gui_update(lcd_surface, x_start, y_start, width, height,
+ SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
+ background ? UI_LCD_POSX : 0, background ? UI_LCD_POSY : 0);
+}
+
+void lcd_update(void)
+{
+ int x, y;
+
+ for (y = 0; y < lcd_pattern_count; y++)
+ if (lcd_patterns[y].count > 0)
+ sim_lcd_define_pattern(y, lcd_patterns[y].pattern);
+
+ for (y = 0; y < LCD_HEIGHT; y++)
+ for (x = 0; x < LCD_WIDTH; x++)
+ lcd_print_char(x, y, lcd_charbuffer[y][x]);
+
+ if (lcd_cursor.visible)
+ lcd_print_char(lcd_cursor.x, lcd_cursor.y, lcd_cursor.hw_char);
+
+ sim_lcd_update_rect(0, ICON_HEIGHT, SIM_LCD_WIDTH,
+ LCD_HEIGHT*CHAR_HEIGHT*CHAR_PIXEL);
+}
+
+#ifdef HAVE_BACKLIGHT
+void sim_backlight(int value)
+{
+ if (value > 0) {
+ sdl_set_gradient(lcd_surface, &lcd_bl_color_bright,
+ &lcd_bl_color_dark, 0, (1<<LCD_DEPTH));
+ } else {
+ sdl_set_gradient(lcd_surface, &lcd_color_bright,
+ &lcd_color_dark, 0, (1<<LCD_DEPTH));
+ }
+
+ sim_lcd_update_rect(0, 0, SIM_LCD_WIDTH, SIM_LCD_HEIGHT);
+}
+#endif
+
+/* initialise simulator lcd driver */
+void sim_lcd_init(void)
+{
+ lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ SIM_LCD_WIDTH * display_zoom,
+ SIM_LCD_HEIGHT * display_zoom,
+ 8, 0, 0, 0, 0);
+
+ sdl_set_gradient(lcd_surface, &lcd_bl_color_bright,
+ &lcd_bl_color_dark, 0, (1<<LCD_DEPTH));
+}
+
+#define BMP_COMPRESSION 0 /* BI_RGB */
+#define BMP_NUMCOLORS (1 << LCD_DEPTH)
+#define BMP_BPP 1
+#define BMP_LINESIZE (((SIM_LCD_WIDTH + 31) / 32) * 4)
+
+#define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS)
+#define BMP_DATASIZE (BMP_LINESIZE * SIM_LCD_HEIGHT)
+#define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE)
+
+#define LE16_CONST(x) (x)&0xff, ((x)>>8)&0xff
+#define LE32_CONST(x) (x)&0xff, ((x)>>8)&0xff, ((x)>>16)&0xff, ((x)>>24)&0xff
+
+static const unsigned char bmpheader[] =
+{
+ 0x42, 0x4d, /* 'BM' */
+ LE32_CONST(BMP_TOTALSIZE), /* Total file size */
+ 0x00, 0x00, 0x00, 0x00, /* Reserved */
+ LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */
+
+ 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
+ LE32_CONST(SIM_LCD_WIDTH), /* Width in pixels */
+ LE32_CONST(SIM_LCD_HEIGHT), /* Height in pixels */
+ 0x01, 0x00, /* Number of planes (always 1) */
+ LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */
+ LE32_CONST(BMP_COMPRESSION),/* Compression mode */
+ LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */
+ 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
+ 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
+ LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */
+ LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */
+
+ BMP_COLOR(LCD_BL_BRIGHTCOLOR),
+ BMP_COLOR(LCD_BL_DARKCOLOR)
+};
+
+void screen_dump(void)
+{
+ int fd;
+ char filename[MAX_PATH];
+ int x, y;
+ static unsigned char line[BMP_LINESIZE];
+
+ create_numbered_filename(filename, "", "dump_", ".bmp", 4
+ IF_CNFN_NUM_(, NULL));
+ DEBUGF("screen_dump\n");
+
+ fd = sim_creat(filename, 0666);
+ if (fd < 0)
+ return;
+
+ write(fd, bmpheader, sizeof(bmpheader));
+ SDL_LockSurface(lcd_surface);
+
+ /* BMP image goes bottom up */
+ for (y = SIM_LCD_HEIGHT - 1; y >= 0; y--)
+ {
+ Uint8 *src = (Uint8 *)lcd_surface->pixels
+ + y * SIM_LCD_WIDTH * display_zoom * display_zoom;
+ unsigned char *dst = line;
+ unsigned dst_mask = 0x80;
+
+ memset(line, 0, sizeof(line));
+ for (x = SIM_LCD_WIDTH; x > 0; x--)
+ {
+ if (*src)
+ *dst |= dst_mask;
+ src += display_zoom;
+ dst_mask >>= 1;
+ if (dst_mask == 0)
+ {
+ dst++;
+ dst_mask = 0x80;
+ }
+ }
+ write(fd, line, sizeof(line));
+ }
+ SDL_UnlockSurface(lcd_surface);
+ close(fd);
+}
diff --git a/firmware/target/hosted/sdl/lcd-charcells.h b/firmware/target/hosted/sdl/lcd-charcells.h
new file mode 100644
index 0000000000..890594f766
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-charcells.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __LCDCHARCELL_H__
+#define __LCDCHARCELL_H__
+
+#include "lcd.h"
+#include "SDL.h"
+
+#ifdef HAVE_LCD_CHARCELLS
+void sim_lcd_init(void);
+void screen_dump(void);
+#endif
+
+#endif /* #ifndef __LCDCHARCELL_H__ */
+
diff --git a/firmware/target/hosted/sdl/lcd-remote-bitmap.c b/firmware/target/hosted/sdl/lcd-remote-bitmap.c
new file mode 100644
index 0000000000..9972f3e423
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-remote-bitmap.c
@@ -0,0 +1,111 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "sim-ui-defines.h"
+#include "lcd-sdl.h"
+#include "lcd-remote-bitmap.h"
+#include "screendump.h"
+#include "system.h" /* background */
+
+SDL_Surface *remote_surface = 0;
+
+SDL_Color remote_bl_color_dark = {RED_CMP(LCD_REMOTE_BL_DARKCOLOR),
+ GREEN_CMP(LCD_REMOTE_BL_DARKCOLOR),
+ BLUE_CMP(LCD_REMOTE_BL_DARKCOLOR), 0};
+SDL_Color remote_bl_color_bright = {RED_CMP(LCD_REMOTE_BL_BRIGHTCOLOR),
+ GREEN_CMP(LCD_REMOTE_BL_BRIGHTCOLOR),
+ BLUE_CMP(LCD_REMOTE_BL_BRIGHTCOLOR), 0};
+SDL_Color remote_color_dark = {RED_CMP(LCD_REMOTE_DARKCOLOR),
+ GREEN_CMP(LCD_REMOTE_DARKCOLOR),
+ BLUE_CMP(LCD_REMOTE_DARKCOLOR), 0};
+SDL_Color remote_color_bright = {RED_CMP(LCD_REMOTE_BRIGHTCOLOR),
+ GREEN_CMP(LCD_REMOTE_BRIGHTCOLOR),
+ BLUE_CMP(LCD_REMOTE_BRIGHTCOLOR), 0};
+
+#define NUM_SHADES 129
+
+#if LCD_REMOTE_DEPTH == 2
+/* Only defined for positive, non-split LCD for now */
+static const unsigned char colorindex[4] = {128, 85, 43, 0};
+#endif
+
+static unsigned long get_lcd_remote_pixel(int x, int y)
+{
+#if LCD_REMOTE_DEPTH == 1
+ return lcd_remote_framebuffer[y/8][x] & (1 << (y & 7)) ? 0 : (NUM_SHADES-1);
+#elif LCD_REMOTE_DEPTH == 2
+#if LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED
+ unsigned bits = (lcd_remote_framebuffer[y/8][x] >> (y & 7)) & 0x0101;
+ return colorindex[(bits | (bits >> 7)) & 3];
+#endif
+#endif
+}
+
+void lcd_remote_update (void)
+{
+ lcd_remote_update_rect(0, 0, LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT);
+}
+
+void lcd_remote_update_rect(int x_start, int y_start, int width, int height)
+{
+ if (remote_surface)
+ {
+ sdl_update_rect(remote_surface, x_start, y_start, width, height,
+ LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT, get_lcd_remote_pixel);
+ sdl_gui_update(remote_surface, x_start, y_start, width, height,
+ LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT, background ? UI_REMOTE_POSX : 0,
+ background ? UI_REMOTE_POSY : LCD_HEIGHT);
+ }
+}
+
+void sim_remote_backlight(int value)
+{
+ if (remote_surface)
+ {
+ if (value > 0)
+ {
+ sdl_set_gradient(remote_surface, &remote_bl_color_dark,
+ &remote_bl_color_bright, 0, NUM_SHADES);
+ }
+ else
+ {
+ sdl_set_gradient(remote_surface, &remote_color_dark,
+ &remote_color_bright, 0, NUM_SHADES);
+ }
+ sdl_gui_update(remote_surface, 0, 0, LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT,
+ LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT,
+ background ? UI_REMOTE_POSX : 0,
+ background? UI_REMOTE_POSY : LCD_HEIGHT);
+ }
+}
+
+/* initialise simulator lcd remote driver */
+void sim_lcd_remote_init(void)
+{
+ remote_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ LCD_REMOTE_WIDTH * display_zoom,
+ LCD_REMOTE_HEIGHT * display_zoom,
+ 8, 0, 0, 0, 0);
+
+ sdl_set_gradient(remote_surface, &remote_bl_color_dark,
+ &remote_bl_color_bright, 0, NUM_SHADES);
+}
+
diff --git a/firmware/target/hosted/sdl/lcd-remote-bitmap.h b/firmware/target/hosted/sdl/lcd-remote-bitmap.h
new file mode 100644
index 0000000000..0a92ee6b79
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-remote-bitmap.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __LCDREMOTE_H__
+#define __LCDREMOTE_H__
+
+#include "lcd.h"
+#include "lcd-remote.h"
+#include "SDL.h"
+
+void sim_lcd_remote_init(void);
+
+#endif /* #ifndef __LCDREMOTE_H__ */
+
diff --git a/firmware/target/hosted/sdl/lcd-sdl.c b/firmware/target/hosted/sdl/lcd-sdl.c
new file mode 100644
index 0000000000..15e4ba95c3
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-sdl.c
@@ -0,0 +1,113 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <SDL.h>
+#include "lcd-sdl.h"
+#include "sim-ui-defines.h"
+#include "system.h" /* for MIN() and MAX() */
+
+int display_zoom = 1;
+
+void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width,
+ int height, int max_x, int max_y,
+ unsigned long (*getpixel)(int, int))
+{
+ int x, y;
+ int xmax, ymax;
+ SDL_Rect dest;
+
+ ymax = y_start + height;
+ xmax = x_start + width;
+
+ if(xmax > max_x)
+ xmax = max_x;
+ if(ymax >= max_y)
+ ymax = max_y;
+
+ SDL_LockSurface(surface);
+
+ dest.w = display_zoom;
+ dest.h = display_zoom;
+
+ for (x = x_start; x < xmax; x++) {
+ dest.x = x * display_zoom;
+
+#ifdef HAVE_LCD_SPLIT
+ for (y = y_start; y < MIN(ymax, LCD_SPLIT_POS); y++) {
+ dest.y = y * display_zoom;
+
+ SDL_FillRect(surface, &dest, (Uint32)(getpixel(x, y) | 0x80));
+ }
+ for (y = MAX(y_start, LCD_SPLIT_POS); y < ymax; y++) {
+ dest.y = (y + LCD_SPLIT_LINES) * display_zoom ;
+
+ SDL_FillRect(surface, &dest, (Uint32)getpixel(x, y));
+ }
+#else
+ for (y = y_start; y < ymax; y++) {
+ dest.y = y * display_zoom;
+
+ SDL_FillRect(surface, &dest, (Uint32)getpixel(x, y));
+ }
+#endif
+ }
+
+ SDL_UnlockSurface(surface);
+}
+
+void sdl_gui_update(SDL_Surface *surface, int x_start, int y_start, int width,
+ int height, int max_x, int max_y, int ui_x, int ui_y)
+{
+ if (x_start + width > max_x)
+ width = max_x - x_start;
+ if (y_start + height > max_y)
+ height = max_y - y_start;
+
+ SDL_Rect src = {x_start * display_zoom, y_start * display_zoom,
+ width * display_zoom, height * display_zoom};
+ SDL_Rect dest= {(ui_x + x_start) * display_zoom,
+ (ui_y + y_start) * display_zoom,
+ width * display_zoom, height * display_zoom};
+
+ if (surface->flags & SDL_SRCALPHA) /* alpha needs a black background */
+ SDL_FillRect(gui_surface, &dest, 0);
+
+ SDL_BlitSurface(surface, &src, gui_surface, &dest);
+
+ SDL_Flip(gui_surface);
+}
+
+/* set a range of bitmap indices to a gradient from startcolour to endcolour */
+void sdl_set_gradient(SDL_Surface *surface, SDL_Color *start, SDL_Color *end,
+ int first, int steps)
+{
+ int i;
+ SDL_Color palette[steps];
+
+ for (i = 0; i < steps; i++) {
+ palette[i].r = start->r + (end->r - start->r) * i / (steps - 1);
+ palette[i].g = start->g + (end->g - start->g) * i / (steps - 1);
+ palette[i].b = start->b + (end->b - start->b) * i / (steps - 1);
+ }
+
+ SDL_SetPalette(surface, SDL_LOGPAL|SDL_PHYSPAL, palette, first, steps);
+}
+
diff --git a/firmware/target/hosted/sdl/lcd-sdl.h b/firmware/target/hosted/sdl/lcd-sdl.h
new file mode 100644
index 0000000000..1f57b06b95
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-sdl.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __LCDSDL_H__
+#define __LCDSDL_H__
+
+#include "lcd.h"
+#include "SDL.h"
+
+/* Default display zoom level */
+extern int display_zoom;
+extern SDL_Surface *gui_surface;
+
+void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width,
+ int height, int max_x, int max_y,
+ unsigned long (*getpixel)(int, int));
+
+void sdl_gui_update(SDL_Surface *surface, int x_start, int y_start, int width,
+ int height, int max_x, int max_y, int ui_x, int ui_y);
+
+void sdl_set_gradient(SDL_Surface *surface, SDL_Color *start, SDL_Color *end,
+ int first, int steps);
+
+#endif /* #ifndef __LCDSDL_H__ */
+
diff --git a/firmware/target/hosted/sdl/pcm-sdl.c b/firmware/target/hosted/sdl/pcm-sdl.c
new file mode 100644
index 0000000000..1772db94f4
--- /dev/null
+++ b/firmware/target/hosted/sdl/pcm-sdl.c
@@ -0,0 +1,373 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Nick Lanham
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "autoconf.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <SDL.h>
+#include "config.h"
+#include "debug.h"
+#include "sound.h"
+#include "audiohw.h"
+#include "system.h"
+
+#include "pcm.h"
+#include "pcm_sampr.h"
+
+#ifdef DEBUG
+#include <stdio.h>
+extern bool debug_audio;
+#endif
+
+static int sim_volume = 0;
+
+#if CONFIG_CODEC == SWCODEC
+static int cvt_status = -1;
+
+static Uint8* pcm_data;
+static size_t pcm_data_size;
+static size_t pcm_sample_bytes;
+static size_t pcm_channel_bytes;
+
+struct pcm_udata
+{
+ Uint8 *stream;
+ Uint32 num_in;
+ Uint32 num_out;
+#ifdef DEBUG
+ FILE *debug;
+#endif
+} udata;
+
+static SDL_AudioSpec obtained;
+static SDL_AudioCVT cvt;
+
+void pcm_play_lock(void)
+{
+ SDL_LockAudio();
+}
+
+void pcm_play_unlock(void)
+{
+ SDL_UnlockAudio();
+}
+
+static void pcm_dma_apply_settings_nolock(void)
+{
+ cvt_status = SDL_BuildAudioCVT(&cvt, AUDIO_S16SYS, 2, pcm_sampr,
+ obtained.format, obtained.channels, obtained.freq);
+
+ if (cvt_status < 0) {
+ cvt.len_ratio = (double)obtained.freq / (double)pcm_sampr;
+ }
+}
+
+void pcm_dma_apply_settings(void)
+{
+ pcm_play_lock();
+ pcm_dma_apply_settings_nolock();
+ pcm_play_unlock();
+}
+
+void pcm_play_dma_start(const void *addr, size_t size)
+{
+ pcm_dma_apply_settings_nolock();
+
+ pcm_data = (Uint8 *) addr;
+ pcm_data_size = size;
+
+ SDL_PauseAudio(0);
+}
+
+void pcm_play_dma_stop(void)
+{
+ SDL_PauseAudio(1);
+#ifdef DEBUG
+ if (udata.debug != NULL) {
+ fclose(udata.debug);
+ udata.debug = NULL;
+ DEBUGF("Audio debug file closed\n");
+ }
+#endif
+}
+
+void pcm_play_dma_pause(bool pause)
+{
+ if (pause)
+ SDL_PauseAudio(1);
+ else
+ SDL_PauseAudio(0);
+}
+
+size_t pcm_get_bytes_waiting(void)
+{
+ return pcm_data_size;
+}
+
+void write_to_soundcard(struct pcm_udata *udata)
+{
+#ifdef DEBUG
+ if (debug_audio && (udata->debug == NULL)) {
+ udata->debug = fopen("audiodebug.raw", "ab");
+ DEBUGF("Audio debug file open\n");
+ }
+#endif
+ if (cvt.needed) {
+ Uint32 rd = udata->num_in;
+ Uint32 wr = (double)rd * cvt.len_ratio;
+
+ if (wr > udata->num_out) {
+ wr = udata->num_out;
+ rd = (double)wr / cvt.len_ratio;
+
+ if (rd > udata->num_in)
+ {
+ rd = udata->num_in;
+ wr = (double)rd * cvt.len_ratio;
+ }
+ }
+
+ if (wr == 0 || rd == 0)
+ {
+ udata->num_out = udata->num_in = 0;
+ return;
+ }
+
+ if (cvt_status > 0) {
+ cvt.len = rd * pcm_sample_bytes;
+ cvt.buf = (Uint8 *) malloc(cvt.len * cvt.len_mult);
+
+ memcpy(cvt.buf, pcm_data, cvt.len);
+
+ SDL_ConvertAudio(&cvt);
+ SDL_MixAudio(udata->stream, cvt.buf, cvt.len_cvt, sim_volume);
+
+ udata->num_in = cvt.len / pcm_sample_bytes;
+ udata->num_out = cvt.len_cvt / pcm_sample_bytes;
+
+#ifdef DEBUG
+ if (udata->debug != NULL) {
+ fwrite(cvt.buf, sizeof(Uint8), cvt.len_cvt, udata->debug);
+ }
+#endif
+ free(cvt.buf);
+ }
+ else {
+ /* Convert is bad, so do silence */
+ Uint32 num = wr*obtained.channels;
+ udata->num_in = rd;
+ udata->num_out = wr;
+
+ switch (pcm_channel_bytes)
+ {
+ case 1:
+ {
+ Uint8 *stream = udata->stream;
+ while (num-- > 0)
+ *stream++ = obtained.silence;
+ break;
+ }
+ case 2:
+ {
+ Uint16 *stream = (Uint16 *)udata->stream;
+ while (num-- > 0)
+ *stream++ = obtained.silence;
+ break;
+ }
+ }
+#ifdef DEBUG
+ if (udata->debug != NULL) {
+ fwrite(udata->stream, sizeof(Uint8), wr, udata->debug);
+ }
+#endif
+ }
+ } else {
+ udata->num_in = udata->num_out = MIN(udata->num_in, udata->num_out);
+ SDL_MixAudio(udata->stream, pcm_data,
+ udata->num_out * pcm_sample_bytes, sim_volume);
+#ifdef DEBUG
+ if (udata->debug != NULL) {
+ fwrite(pcm_data, sizeof(Uint8), udata->num_out * pcm_sample_bytes,
+ udata->debug);
+ }
+#endif
+ }
+}
+
+void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len)
+{
+ udata->stream = stream;
+
+ /* Write what we have in the PCM buffer */
+ if (pcm_data_size > 0)
+ goto start;
+
+ /* Audio card wants more? Get some more then. */
+ while (len > 0) {
+ if ((ssize_t)pcm_data_size <= 0) {
+ pcm_data_size = 0;
+
+ if (pcm_callback_for_more)
+ pcm_callback_for_more(&pcm_data, &pcm_data_size);
+ }
+
+ if (pcm_data_size > 0) {
+ start:
+ udata->num_in = pcm_data_size / pcm_sample_bytes;
+ udata->num_out = len / pcm_sample_bytes;
+
+ write_to_soundcard(udata);
+
+ udata->num_in *= pcm_sample_bytes;
+ udata->num_out *= pcm_sample_bytes;
+
+ pcm_data += udata->num_in;
+ pcm_data_size -= udata->num_in;
+ udata->stream += udata->num_out;
+ len -= udata->num_out;
+ } else {
+ DEBUGF("sdl_audio_callback: No Data.\n");
+ pcm_play_dma_stop();
+ pcm_play_dma_stopped_callback();
+ break;
+ }
+ }
+}
+
+const void * pcm_play_dma_get_peak_buffer(int *count)
+{
+ uintptr_t addr = (uintptr_t)pcm_data;
+ *count = pcm_data_size / 4;
+ return (void *)((addr + 2) & ~3);
+}
+
+#ifdef HAVE_RECORDING
+void pcm_rec_lock(void)
+{
+}
+
+void pcm_rec_unlock(void)
+{
+}
+
+void pcm_rec_dma_init(void)
+{
+}
+
+void pcm_rec_dma_close(void)
+{
+}
+
+void pcm_rec_dma_start(void *start, size_t size)
+{
+ (void)start;
+ (void)size;
+}
+
+void pcm_rec_dma_stop(void)
+{
+}
+
+void pcm_rec_dma_record_more(void *start, size_t size)
+{
+ (void)start;
+ (void)size;
+}
+
+unsigned long pcm_rec_status(void)
+{
+ return 0;
+}
+
+const void * pcm_rec_dma_get_peak_buffer(void)
+{
+ return NULL;
+}
+
+#endif /* HAVE_RECORDING */
+
+void pcm_play_dma_init(void)
+{
+ if (SDL_InitSubSystem(SDL_INIT_AUDIO))
+ {
+ DEBUGF("Could not initialize SDL audio subsystem!\n");
+ return;
+ }
+
+ SDL_AudioSpec wanted_spec;
+#ifdef DEBUG
+ udata.debug = NULL;
+ if (debug_audio) {
+ udata.debug = fopen("audiodebug.raw", "wb");
+ DEBUGF("Audio debug file open\n");
+ }
+#endif
+ /* Set 16-bit stereo audio at 44Khz */
+ wanted_spec.freq = 44100;
+ wanted_spec.format = AUDIO_S16SYS;
+ wanted_spec.channels = 2;
+ wanted_spec.samples = 2048;
+ wanted_spec.callback =
+ (void (SDLCALL *)(void *userdata,
+ Uint8 *stream, int len))sdl_audio_callback;
+ wanted_spec.userdata = &udata;
+
+ /* Open the audio device and start playing sound! */
+ if(SDL_OpenAudio(&wanted_spec, &obtained) < 0) {
+ DEBUGF("Unable to open audio: %s\n", SDL_GetError());
+ return;
+ }
+
+ switch (obtained.format)
+ {
+ case AUDIO_U8:
+ case AUDIO_S8:
+ pcm_channel_bytes = 1;
+ break;
+ case AUDIO_U16LSB:
+ case AUDIO_S16LSB:
+ case AUDIO_U16MSB:
+ case AUDIO_S16MSB:
+ pcm_channel_bytes = 2;
+ break;
+ default:
+ DEBUGF("Unknown sample format obtained: %u\n",
+ (unsigned)obtained.format);
+ return;
+ }
+
+ pcm_sample_bytes = obtained.channels * pcm_channel_bytes;
+
+ pcm_dma_apply_settings_nolock();
+}
+
+void pcm_postinit(void)
+{
+}
+
+void pcm_set_mixer_volume(int volume)
+{
+ sim_volume = volume;
+}
+
+#endif /* CONFIG_CODEC == SWCODEC */
diff --git a/firmware/target/hosted/sdl/sim-ui-defines.h b/firmware/target/hosted/sdl/sim-ui-defines.h
new file mode 100644
index 0000000000..567a618fc3
--- /dev/null
+++ b/firmware/target/hosted/sdl/sim-ui-defines.h
@@ -0,0 +1,405 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __UISDL_H__
+#define __UISDL_H__
+
+#include <stdbool.h>
+#include "SDL.h"
+#include "config.h"
+
+/* colour definitions are R, G, B */
+
+#if defined(ARCHOS_RECORDER)
+#define UI_TITLE "Jukebox Recorder"
+#define UI_WIDTH 270 /* width of GUI window */
+#define UI_HEIGHT 406 /* height of GUI window */
+#define UI_LCD_POSX 80 /* x position of lcd */
+#define UI_LCD_POSY 104 /* y position of lcd */
+
+#elif defined(ARCHOS_PLAYER)
+#define UI_TITLE "Jukebox Player"
+#define UI_WIDTH 284 /* width of GUI window */
+#define UI_HEIGHT 420 /* height of GUI window */
+#define UI_LCD_POSX 75 /* x position of lcd */
+#define UI_LCD_POSY 116 /* y position of lcd */
+
+#elif defined(ARCHOS_FMRECORDER) || defined(ARCHOS_RECORDERV2)
+#define UI_TITLE "Jukebox FM Recorder"
+#define UI_WIDTH 285 /* width of GUI window */
+#define UI_HEIGHT 414 /* height of GUI window */
+#define UI_LCD_POSX 87 /* x position of lcd */
+#define UI_LCD_POSY 77 /* y position of lcd */
+
+#elif defined(ARCHOS_ONDIOSP) || defined(ARCHOS_ONDIOFM)
+#define UI_TITLE "Ondio"
+#define UI_WIDTH 155 /* width of GUI window */
+#define UI_HEIGHT 334 /* height of GUI window */
+#define UI_LCD_POSX 21 /* x position of lcd */
+#define UI_LCD_POSY 82 /* y position of lcd */
+
+#elif defined(IRIVER_H120) || defined(IRIVER_H100)
+#define UI_TITLE "iriver H1x0"
+#define UI_WIDTH 379 /* width of GUI window */
+#define UI_HEIGHT 508 /* height of GUI window */
+#define UI_LCD_POSX 109 /* x position of lcd */
+#define UI_LCD_POSY 23 /* y position of lcd */
+#define UI_REMOTE_POSX 50 /* x position of remote lcd */
+#define UI_REMOTE_POSY 403 /* y position of remote lcd */
+
+#elif defined(IRIVER_H300)
+#define UI_TITLE "iriver H300"
+#define UI_WIDTH 288 /* width of GUI window */
+#define UI_HEIGHT 581 /* height of GUI window */
+#define UI_LCD_POSX 26 /* x position of lcd */
+#define UI_LCD_POSY 36 /* y position of lcd */
+#define UI_REMOTE_POSX 12 /* x position of remote lcd */
+#define UI_REMOTE_POSY 478 /* y position of remote lcd */
+
+#elif defined(IPOD_1G2G)
+#define UI_TITLE "iPod 1G/2G"
+#define UI_WIDTH 224 /* width of GUI window */
+#define UI_HEIGHT 382 /* height of GUI window */
+#define UI_LCD_POSX 32 /* x position of lcd */
+#define UI_LCD_POSY 12 /* y position of lcd */
+
+#elif defined(IPOD_3G)
+#define UI_TITLE "iPod 3G"
+#define UI_WIDTH 218 /* width of GUI window */
+#define UI_HEIGHT 389 /* height of GUI window */
+#define UI_LCD_POSX 29 /* x position of lcd */
+#define UI_LCD_POSY 16 /* y position of lcd */
+
+#elif defined(IPOD_4G)
+#define UI_TITLE "iPod 4G"
+#define UI_WIDTH 196 /* width of GUI window */
+#define UI_HEIGHT 370 /* height of GUI window */
+#define UI_LCD_POSX 19 /* x position of lcd */
+#define UI_LCD_POSY 14 /* y position of lcd */
+
+#elif defined(IPOD_MINI) || defined(IPOD_MINI2G)
+#define UI_TITLE "iPod mini"
+#define UI_WIDTH 191 /* width of GUI window */
+#define UI_HEIGHT 365 /* height of GUI window */
+#define UI_LCD_POSX 24 /* x position of lcd */
+#define UI_LCD_POSY 17 /* y position of lcd */
+
+#elif defined(IPOD_COLOR)
+#define UI_TITLE "iPod Color"
+#define UI_WIDTH 261 /* width of GUI window */
+#define UI_HEIGHT 493 /* height of GUI window */
+#define UI_LCD_POSX 21 /* x position of lcd */
+#define UI_LCD_POSY 16 /* y position of lcd */
+
+#elif defined(IPOD_NANO)
+#define UI_TITLE "iPod Nano"
+#define UI_WIDTH 199 /* width of GUI window */
+#define UI_HEIGHT 421 /* height of GUI window */
+#define UI_LCD_POSX 13 /* x position of lcd */
+#define UI_LCD_POSY 14 /* y position of lcd */
+
+#elif defined(IPOD_NANO2G)
+#define UI_TITLE "iPod Nano 2G"
+#define UI_WIDTH 235 /* width of GUI window */
+#define UI_HEIGHT 537 /* height of GUI window */
+#define UI_LCD_POSX 29 /* x position of lcd */
+#define UI_LCD_POSY 33 /* y position of lcd */
+
+#elif defined(IPOD_VIDEO)
+#define UI_TITLE "iPod Video"
+#define UI_WIDTH 350 /* width of GUI window */
+#define UI_HEIGHT 591 /* height of GUI window */
+#define UI_LCD_POSX 14 /* x position of lcd */
+#define UI_LCD_POSY 12 /* y position of lcd */
+
+#elif defined(IAUDIO_X5)
+#define UI_TITLE "iAudio X5"
+#define UI_WIDTH 300 /* width of GUI window */
+#define UI_HEIGHT 558 /* height of GUI window */
+#define UI_LCD_POSX 55 /* x position of lcd */
+#define UI_LCD_POSY 61 /* y position of lcd */
+#define UI_REMOTE_POSX 12 /* x position of remote lcd */
+#define UI_REMOTE_POSY 462 /* y position of remote lcd */
+
+#elif defined(IAUDIO_M5)
+#define UI_TITLE "iAudio M5"
+#define UI_WIDTH 374 /* width of GUI window */
+#define UI_HEIGHT 650 /* height of GUI window */
+#define UI_LCD_POSX 82 /* x position of lcd */
+#define UI_LCD_POSY 74 /* y position of lcd */
+#define UI_REMOTE_POSX 59 /* x position of remote lcd */
+#define UI_REMOTE_POSY 509 /* y position of remote lcd */
+
+#elif defined(IAUDIO_M3)
+#define UI_TITLE "iAudio M3"
+#define UI_WIDTH 397 /* width of GUI window */
+#define UI_HEIGHT 501 /* height of GUI window */
+#define UI_LCD_POSX 92 /* x position of lcd */
+#define UI_LCD_POSY 348 /* y position of lcd */
+
+#elif defined(GIGABEAT_F)
+#define UI_TITLE "Toshiba Gigabeat"
+#define UI_WIDTH 401 /* width of GUI window */
+#define UI_HEIGHT 655 /* height of GUI window */
+#define UI_LCD_POSX 48 /* x position of lcd */
+#define UI_LCD_POSY 60 /* y position of lcd */
+
+#elif defined(GIGABEAT_S)
+#define UI_TITLE "Toshiba Gigabeat"
+#define UI_WIDTH 450 /* width of GUI window */
+#define UI_HEIGHT 688 /* height of GUI window */
+#define UI_LCD_POSX 96 /* x position of lcd */
+#define UI_LCD_POSY 90 /* y position of lcd */
+
+#elif defined(MROBE_500)
+#if LCD_WIDTH==320
+#define UI_TITLE "Olympus M:Robe 500"
+#define UI_WIDTH 450 /* width of GUI window */
+#define UI_HEIGHT 350 /* height of GUI window */
+#define UI_LCD_POSX 65 /* x position of lcd */
+#define UI_LCD_POSY 30 /* y position of lcd */
+#define UI_REMOTE_POSX 36 /* x position of remote lcd */
+#define UI_REMOTE_POSY 318 /* y position of remote lcd */
+#else
+#define UI_TITLE "Olympus M:Robe 500"
+#define UI_WIDTH 895 /* width of GUI window */
+#define UI_HEIGHT 646 /* height of GUI window */
+#define UI_LCD_POSX 129 /* x position of lcd */
+#define UI_LCD_POSY 60 /* y position of lcd */
+#define UI_REMOTE_POSX 37 /* x position of remote lcd */
+#define UI_REMOTE_POSY 615 /* y position of remote lcd */
+#endif
+
+#elif defined(IRIVER_H10)
+#define UI_TITLE "iriver H10 20Gb"
+#define UI_WIDTH 392 /* width of GUI window */
+#define UI_HEIGHT 391 /* height of GUI window */
+#define UI_LCD_POSX 111 /* x position of lcd */
+#define UI_LCD_POSY 30 /* y position of lcd */
+
+#elif defined(IRIVER_H10_5GB)
+#define UI_TITLE "iriver H10 5/6Gb"
+#define UI_WIDTH 353 /* width of GUI window */
+#define UI_HEIGHT 460 /* height of GUI window */
+#define UI_LCD_POSX 112 /* x position of lcd */
+#define UI_LCD_POSY 45 /* y position of lcd */
+
+#elif defined(SANSA_E200) || defined(SANSA_E200V2)
+#ifdef SANSA_E200
+#define UI_TITLE "Sansa e200"
+#else
+#define UI_TITLE "Sansa e200v2"
+#endif
+#define UI_WIDTH 260 /* width of GUI window */
+#define UI_HEIGHT 502 /* height of GUI window */
+#define UI_LCD_POSX 42 /* x position of lcd */
+#define UI_LCD_POSY 37 /* y position of lcd */
+
+#elif defined(SANSA_C200) || defined(SANSA_C200V2)
+#ifdef SANSA_C200
+#define UI_TITLE "Sansa c200"
+#else
+#define UI_TITLE "Sansa c200v2"
+#endif
+#define UI_WIDTH 350 /* width of GUI window */
+#define UI_HEIGHT 152 /* height of GUI window */
+#define UI_LCD_POSX 42 /* x position of lcd */
+#define UI_LCD_POSY 35 /* y position of lcd */
+
+#elif defined(IRIVER_IFP7XX)
+#define UI_TITLE "iriver iFP7xx"
+#define UI_WIDTH 425 /* width of GUI window */
+#define UI_HEIGHT 183 /* height of GUI window */
+#define UI_LCD_POSX 115 /* x position of lcd */
+#define UI_LCD_POSY 54 /* y position of lcd */
+
+#elif defined(ARCHOS_AV300)
+#define UI_TITLE "Archos AV300"
+/* We are temporarily using a 2bpp LCD driver and dummy bitmap */
+#define UI_WIDTH 420 /* width of GUI window */
+#define UI_HEIGHT 340 /* height of GUI window */
+#define UI_LCD_POSX 50 /* x position of lcd */
+#define UI_LCD_POSY 50 /* y position of lcd */
+
+#elif defined(MROBE_100)
+#define UI_TITLE "Olympus M:Robe 100"
+#define UI_WIDTH 247 /* width of GUI window */
+#define UI_HEIGHT 462 /* height of GUI window */
+#define UI_LCD_POSX 43 /* x position of lcd */
+#define UI_LCD_POSY 25 /* y position of lcd */
+#define UI_REMOTE_POSX 34 /* x position of remote lcd */
+#define UI_REMOTE_POSY 432 /* y position of remote lcd */
+
+#elif defined(COWON_D2)
+#define UI_TITLE "Cowon D2"
+#define UI_WIDTH 472 /* width of GUI window */
+#define UI_HEIGHT 368 /* height of GUI window */
+#define UI_LCD_POSX 58 /* x position of lcd */
+#define UI_LCD_POSY 67 /* y position of lcd */
+
+#elif defined(IAUDIO_7)
+#define UI_TITLE "iAudio7"
+#define UI_WIDTH 494 /* width of GUI window */
+#define UI_HEIGHT 214 /* height of GUI window */
+#define UI_LCD_POSX 131 /* x position of lcd */
+#define UI_LCD_POSY 38 /* y position of lcd */
+
+#elif defined(CREATIVE_ZVM) || defined(CREATIVE_ZVM60GB)
+#ifdef CREATIVE_ZVM
+ #define UI_TITLE "Creative Zen Vision:M 30GB"
+#else
+ #define UI_TITLE "Creative Zen Vision:M 60GB"
+#endif
+#define UI_WIDTH 383 /* width of GUI window */
+#define UI_HEIGHT 643 /* height of GUI window */
+#define UI_LCD_POSX 31 /* x position of lcd */
+#define UI_LCD_POSY 62 /* y position of lcd */
+
+#elif defined(CREATIVE_ZV)
+#define UI_TITLE "Creative Zen Vision"
+#define UI_WIDTH 1054 /* width of GUI window */
+#define UI_HEIGHT 643 /* height of GUI window */
+#define UI_LCD_POSX 129 /* x position of lcd */
+#define UI_LCD_POSY 85 /* y position of lcd */
+
+#elif defined(MEIZU_M6SL)
+#define UI_TITLE "Meizu M6"
+#define UI_WIDTH 512 /* width of GUI window */
+#define UI_HEIGHT 322 /* height of GUI window */
+#define UI_LCD_POSX 39 /* x position of lcd */
+#define UI_LCD_POSY 38 /* y position of lcd */
+
+#elif defined(SANSA_FUZE) || defined(SANSA_FUZEV2)
+#ifdef SANSA_FUZE
+#define UI_TITLE "Sansa Fuze"
+#else
+#define UI_TITLE "Sansa Fuzev2"
+#endif
+#define UI_WIDTH 279 /* width of GUI window */
+#define UI_HEIGHT 449 /* height of GUI window */
+#define UI_LCD_POSX 30 /* x position of lcd */
+#define UI_LCD_POSY 31 /* y position of lcd */
+
+#elif defined(SANSA_CLIP) || defined(SANSA_CLIPV2)
+#if defined(SANSA_CLIP)
+#define CLIP_VERSION ""
+#elif defined(SANSA_CLIPV2)
+#define CLIP_VERSION "v2"
+#endif
+#define UI_TITLE "Sansa Clip"CLIP_VERSION
+#define UI_WIDTH 205 /* width of GUI window */
+#define UI_HEIGHT 325 /* height of GUI window */
+#define UI_LCD_POSX 38 /* x position of lcd */
+#define UI_LCD_POSY 38 /* y position of lcd */
+
+#elif defined(SANSA_CLIPPLUS)
+#define UI_TITLE "Sansa Clip+"
+#define UI_WIDTH 205 /* width of GUI window */
+#define UI_HEIGHT 325 /* height of GUI window */
+#define UI_LCD_POSX 42 /* x position of lcd */
+#define UI_LCD_POSY 42 /* y position of lcd */
+
+
+
+#elif defined(PHILIPS_SA9200)
+#define UI_TITLE "Philips GoGear SA9200"
+#define UI_WIDTH 233 /* width of GUI window */
+#define UI_HEIGHT 435 /* height of GUI window */
+#define UI_LCD_POSX 50 /* x position of lcd */
+#define UI_LCD_POSY 50 /* y position of lcd */
+
+#elif defined(PHILIPS_HDD1630)
+#define UI_TITLE "Philips GoGear HDD1630"
+#define UI_WIDTH 407 /* width of GUI window */
+#define UI_HEIGHT 391 /* height of GUI window */
+#define UI_LCD_POSX 143 /* x position of lcd */
+#define UI_LCD_POSY 27 /* y position of lcd */
+
+#elif defined(SANSA_M200V4)
+#define UI_TITLE "sansa m200v4"
+#define UI_WIDTH 350 /* width of GUI window */
+#define UI_HEIGHT 168 /* height of GUI window */
+#define UI_LCD_POSX 42 /* x position of lcd */
+#define UI_LCD_POSY 55 /* y position of lcd */
+
+#elif defined(ONDA_VX747) || defined(ONDA_VX747P)
+#ifdef ONDA_VX747
+#define UI_TITLE "Onda VX747"
+#else
+#define UI_TITLE "Onda VX747+"
+#endif
+#define UI_WIDTH 340 /* width of GUI window */
+#define UI_HEIGHT 601 /* height of GUI window */
+#define UI_LCD_POSX 45 /* x position of lcd */
+#define UI_LCD_POSY 90 /* y position of lcd */
+
+#elif defined(ONDA_VX777)
+#define UI_TITLE "Onda VX777"
+#define UI_WIDTH 306 /* width of GUI window */
+#define UI_HEIGHT 558 /* height of GUI window */
+#define UI_LCD_POSX 32 /* x position of lcd */
+#define UI_LCD_POSY 81 /* y position of lcd */
+
+#elif defined(SAMSUNG_YH820)
+#define UI_TITLE "Samsung YH-820"
+#define UI_WIDTH 368 /* width of GUI window */
+#define UI_HEIGHT 428 /* height of GUI window */
+#define UI_LCD_POSX 120 /* x position of lcd */
+#define UI_LCD_POSY 75 /* y position of lcd */
+
+#elif defined(SAMSUNG_YH920) || defined(SAMSUNG_YH925)
+#ifdef SAMSUNG_YH920
+#define UI_TITLE "Samsung YH-920"
+#else
+#define UI_TITLE "Samsung YH-925"
+#endif
+#define UI_WIDTH 408 /* width of GUI window */
+#define UI_HEIGHT 454 /* height of GUI window */
+#define UI_LCD_POSX 124 /* x position of lcd */
+#define UI_LCD_POSY 42 /* y position of lcd */
+
+#elif defined(MINI2440)
+#define UI_TITLE "Mini2440"
+#define UI_WIDTH 441 /* width of GUI window */
+#define UI_HEIGHT 436 /* height of GUI window */
+#define UI_LCD_POSX 148 /* x position of lcd */
+#define UI_LCD_POSY 50 /* y position of lcd */
+
+#elif defined(PBELL_VIBE500)
+#define UI_TITLE "Packard Bell Vibe 500"
+#define UI_WIDTH 287 /* width of GUI window */
+#define UI_HEIGHT 488 /* height of GUI window */
+#define UI_LCD_POSX 64 /* x position of lcd */
+#define UI_LCD_POSY 61 /* y position of lcd */
+
+#elif defined(MPIO_HD200)
+#define UI_TITLE "MPIO HD200"
+#define UI_WIDTH 430 /* width of GUI window */
+#define UI_HEIGHT 479 /* height of GUI window */
+#define UI_LCD_POSX 101
+#define UI_LCD_POSY 195
+
+#elif defined(SIMULATOR)
+#error no UI defines
+#endif
+
+#endif /* #ifndef __UISDL_H__ */
+
diff --git a/firmware/target/hosted/sdl/system-sdl.c b/firmware/target/hosted/sdl/system-sdl.c
new file mode 100644
index 0000000000..693e8d1b57
--- /dev/null
+++ b/firmware/target/hosted/sdl/system-sdl.c
@@ -0,0 +1,236 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 by Daniel Everton <dan@iocaine.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <SDL.h>
+#include <stdlib.h>
+#include <string.h>
+#include <setjmp.h>
+#include "system-sdl.h"
+#include "thread-sdl.h"
+#include "sim-ui-defines.h"
+#include "lcd-sdl.h"
+#ifdef HAVE_LCD_BITMAP
+#include "lcd-bitmap.h"
+#elif defined(HAVE_LCD_CHARCELLS)
+#include "lcd-charcells.h"
+#endif
+#ifdef HAVE_REMOTE_LCD
+#include "lcd-remote-bitmap.h"
+#endif
+#include "panic.h"
+#include "debug.h"
+
+SDL_Surface *gui_surface;
+
+bool background = true; /* use backgrounds by default */
+#ifdef HAVE_REMOTE_LCD
+bool showremote = true; /* include remote by default */
+#endif
+bool mapping = false;
+bool debug_buttons = false;
+
+bool lcd_display_redraw = true; /* Used for player simulator */
+char having_new_lcd = true; /* Used for player simulator */
+bool sim_alarm_wakeup = false;
+const char *sim_root_dir = NULL;
+extern int display_zoom;
+
+#ifdef DEBUG
+bool debug_audio = false;
+#endif
+
+bool debug_wps = false;
+int wps_verbose_level = 3;
+
+
+void sys_poweroff(void)
+{
+ /* Order here is relevent to prevent deadlocks and use of destroyed
+ sync primitives by kernel threads */
+ sim_thread_shutdown();
+ sim_kernel_shutdown();
+ SDL_Quit();
+}
+
+void system_init(void)
+{
+ SDL_Surface *picture_surface;
+ int width, height;
+
+ if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER))
+ panicf("%s", SDL_GetError());
+
+ /* Try and load the background image. If it fails go without */
+ if (background) {
+ picture_surface = SDL_LoadBMP("UI256.bmp");
+ if (picture_surface == NULL) {
+ background = false;
+ DEBUGF("warn: %s\n", SDL_GetError());
+ }
+ }
+
+ /* Set things up */
+ if (background)
+ {
+ width = UI_WIDTH;
+ height = UI_HEIGHT;
+ }
+ else
+ {
+#ifdef HAVE_REMOTE_LCD
+ if (showremote)
+ {
+ width = SIM_LCD_WIDTH > SIM_REMOTE_WIDTH ? SIM_LCD_WIDTH : SIM_REMOTE_WIDTH;
+ height = SIM_LCD_HEIGHT + SIM_REMOTE_HEIGHT;
+ }
+ else
+#endif
+ {
+ width = SIM_LCD_WIDTH;
+ height = SIM_LCD_HEIGHT;
+ }
+ }
+
+
+ if ((gui_surface = SDL_SetVideoMode(width * display_zoom, height * display_zoom, 24, SDL_HWSURFACE|SDL_DOUBLEBUF)) == NULL) {
+ panicf("%s", SDL_GetError());
+ }
+
+ SDL_WM_SetCaption(UI_TITLE, NULL);
+
+ sim_lcd_init();
+#ifdef HAVE_REMOTE_LCD
+ if (showremote)
+ sim_lcd_remote_init();
+#endif
+
+ if (background && picture_surface != NULL) {
+ SDL_BlitSurface(picture_surface, NULL, gui_surface, NULL);
+ SDL_UpdateRect(gui_surface, 0, 0, 0, 0);
+ }
+}
+
+void system_exception_wait(void)
+{
+ sim_thread_exception_wait();
+}
+
+void system_reboot(void)
+{
+ sim_thread_exception_wait();
+}
+
+void sys_handle_argv(int argc, char *argv[])
+{
+ if (argc >= 1)
+ {
+ int x;
+ for (x = 1; x < argc; x++)
+ {
+#ifdef DEBUG
+ if (!strcmp("--debugaudio", argv[x]))
+ {
+ debug_audio = true;
+ printf("Writing debug audio file.\n");
+ }
+ else
+#endif
+ if (!strcmp("--debugwps", argv[x]))
+ {
+ debug_wps = true;
+ printf("WPS debug mode enabled.\n");
+ }
+ else if (!strcmp("--nobackground", argv[x]))
+ {
+ background = false;
+ printf("Disabling background image.\n");
+ }
+#ifdef HAVE_REMOTE_LCD
+ else if (!strcmp("--noremote", argv[x]))
+ {
+ showremote = false;
+ background = false;
+ printf("Disabling remote image.\n");
+ }
+#endif
+ else if (!strcmp("--old_lcd", argv[x]))
+ {
+ having_new_lcd = false;
+ printf("Using old LCD layout.\n");
+ }
+ else if (!strcmp("--zoom", argv[x]))
+ {
+ x++;
+ if(x < argc)
+ display_zoom=atoi(argv[x]);
+ else
+ display_zoom = 2;
+ printf("Window zoom is %d\n", display_zoom);
+ }
+ else if (!strcmp("--alarm", argv[x]))
+ {
+ sim_alarm_wakeup = true;
+ printf("Simulating alarm wakeup.\n");
+ }
+ else if (!strcmp("--root", argv[x]))
+ {
+ x++;
+ if (x < argc)
+ {
+ sim_root_dir = argv[x];
+ printf("Root directory: %s\n", sim_root_dir);
+ }
+ }
+ else if (!strcmp("--mapping", argv[x]))
+ {
+ mapping = true;
+ printf("Printing click coords with drag radii.\n");
+ }
+ else if (!strcmp("--debugbuttons", argv[x]))
+ {
+ debug_buttons = true;
+ printf("Printing background button clicks.\n");
+ }
+ else
+ {
+ printf("rockboxui\n");
+ printf("Arguments:\n");
+#ifdef DEBUG
+ printf(" --debugaudio \t Write raw PCM data to audiodebug.raw\n");
+#endif
+ printf(" --debugwps \t Print advanced WPS debug info\n");
+ printf(" --nobackground \t Disable the background image\n");
+#ifdef HAVE_REMOTE_LCD
+ printf(" --noremote \t Disable the remote image (will disable backgrounds)\n");
+#endif
+ printf(" --old_lcd \t [Player] simulate old playermodel (ROM version<4.51)\n");
+ printf(" --zoom [VAL]\t Window zoom (will disable backgrounds)\n");
+ printf(" --alarm \t Simulate a wake-up on alarm\n");
+ printf(" --root [DIR]\t Set root directory\n");
+ printf(" --mapping \t Output coordinates and radius for mapping backgrounds\n");
+ exit(0);
+ }
+ }
+ }
+ if (display_zoom > 1) {
+ background = false;
+ }
+}
diff --git a/firmware/target/hosted/sdl/system-sdl.h b/firmware/target/hosted/sdl/system-sdl.h
new file mode 100644
index 0000000000..917e6e89da
--- /dev/null
+++ b/firmware/target/hosted/sdl/system-sdl.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2007 by Michael Sevakis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _SYSTEM_SDL_H_
+#define _SYSTEM_SDL_H_
+
+#include <stdbool.h>
+
+#define HIGHEST_IRQ_LEVEL 1
+
+int set_irq_level(int level);
+
+#define disable_irq() \
+ ((void)set_irq_level(HIGHEST_IRQ_LEVEL))
+
+#define enable_irq() \
+ ((void)set_irq_level(0))
+
+#define disable_irq_save() \
+ set_irq_level(HIGHEST_IRQ_LEVEL)
+
+#define restore_irq(level) \
+ ((void)set_irq_level(level))
+
+void sim_enter_irq_handler(void);
+void sim_exit_irq_handler(void);
+void sim_kernel_shutdown(void);
+void sys_poweroff(void);
+void sys_handle_argv(int argc, char *argv[]);
+
+extern bool background; /* True if the background image is enabled */
+extern int display_zoom;
+extern long start_tick;
+
+#endif /* _SYSTEM_SDL_H_ */
diff --git a/firmware/target/hosted/sdl/thread-sdl.c b/firmware/target/hosted/sdl/thread-sdl.c
new file mode 100644
index 0000000000..fbe2621d40
--- /dev/null
+++ b/firmware/target/hosted/sdl/thread-sdl.c
@@ -0,0 +1,610 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <stdbool.h>
+#include <time.h>
+#include <SDL.h>
+#include <SDL_thread.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <setjmp.h>
+#include "system-sdl.h"
+#include "thread-sdl.h"
+#include "system.h"
+#include "kernel.h"
+#include "thread.h"
+#include "debug.h"
+
+/* Define this as 1 to show informational messages that are not errors. */
+#define THREAD_SDL_DEBUGF_ENABLED 0
+
+#if THREAD_SDL_DEBUGF_ENABLED
+#define THREAD_SDL_DEBUGF(...) DEBUGF(__VA_ARGS__)
+static char __name[32];
+#define THREAD_SDL_GET_NAME(thread) \
+ ({ thread_get_name(__name, ARRAYLEN(__name), thread); __name; })
+#else
+#define THREAD_SDL_DEBUGF(...)
+#define THREAD_SDL_GET_NAME(thread)
+#endif
+
+#define THREAD_PANICF(str...) \
+ ({ fprintf(stderr, str); exit(-1); })
+
+/* Thread/core entries as in rockbox core */
+static struct core_entry cores[NUM_CORES];
+struct thread_entry threads[MAXTHREADS];
+/* Jump buffers for graceful exit - kernel threads don't stay neatly
+ * in their start routines responding to messages so this is the only
+ * way to get them back in there so they may exit */
+static jmp_buf thread_jmpbufs[MAXTHREADS];
+/* this mutex locks out other Rockbox threads while one runs,
+ * that enables us to simulate a cooperative environment even if
+ * the host is preemptive */
+static SDL_mutex *m;
+static volatile bool threads_exit = false;
+
+extern long start_tick;
+
+void sim_thread_shutdown(void)
+{
+ int i;
+
+ /* Tell all threads jump back to their start routines, unlock and exit
+ gracefully - we'll check each one in turn for it's status. Threads
+ _could_ terminate via remove_thread or multiple threads could exit
+ on each unlock but that is safe. */
+
+ /* Do this before trying to acquire lock */
+ threads_exit = true;
+
+ /* Take control */
+ SDL_LockMutex(m);
+
+ for (i = 0; i < MAXTHREADS; i++)
+ {
+ struct thread_entry *thread = &threads[i];
+ /* exit all current threads, except the main one */
+ if (thread->context.t != NULL)
+ {
+ /* Signal thread on delay or block */
+ SDL_Thread *t = thread->context.t;
+ SDL_SemPost(thread->context.s);
+ SDL_UnlockMutex(m);
+ /* Wait for it to finish */
+ SDL_WaitThread(t, NULL);
+ /* Relock for next thread signal */
+ SDL_LockMutex(m);
+ }
+ }
+
+ SDL_UnlockMutex(m);
+ SDL_DestroyMutex(m);
+}
+
+static void new_thread_id(unsigned int slot_num,
+ struct thread_entry *thread)
+{
+ unsigned int version =
+ (thread->id + (1u << THREAD_ID_VERSION_SHIFT))
+ & THREAD_ID_VERSION_MASK;
+
+ if (version == 0)
+ version = 1u << THREAD_ID_VERSION_SHIFT;
+
+ thread->id = version | (slot_num & THREAD_ID_SLOT_MASK);
+}
+
+static struct thread_entry * find_empty_thread_slot(void)
+{
+ struct thread_entry *thread = NULL;
+ int n;
+
+ for (n = 0; n < MAXTHREADS; n++)
+ {
+ int state = threads[n].state;
+
+ if (state == STATE_KILLED)
+ {
+ thread = &threads[n];
+ break;
+ }
+ }
+
+ return thread;
+}
+
+
+/* Initialize SDL threading */
+void init_threads(void)
+{
+ struct thread_entry *thread;
+ int n;
+
+ memset(cores, 0, sizeof(cores));
+ memset(threads, 0, sizeof(threads));
+
+ m = SDL_CreateMutex();
+
+ if (SDL_LockMutex(m) == -1)
+ {
+ fprintf(stderr, "Couldn't lock mutex\n");
+ return;
+ }
+
+ /* Initialize all IDs */
+ for (n = 0; n < MAXTHREADS; n++)
+ threads[n].id = THREAD_ID_INIT(n);
+
+ /* Slot 0 is reserved for the main thread - initialize it here and
+ then create the SDL thread - it is possible to have a quick, early
+ shutdown try to access the structure. */
+ thread = &threads[0];
+ thread->stack = (uintptr_t *)" ";
+ thread->stack_size = 8;
+ thread->name = "main";
+ thread->state = STATE_RUNNING;
+ thread->context.s = SDL_CreateSemaphore(0);
+ thread->context.t = NULL; /* NULL for the implicit main thread */
+ cores[CURRENT_CORE].running = thread;
+
+ if (thread->context.s == NULL)
+ {
+ fprintf(stderr, "Failed to create main semaphore\n");
+ return;
+ }
+
+ THREAD_SDL_DEBUGF("Main thread: %p\n", thread);
+
+ return;
+}
+
+void sim_thread_exception_wait(void)
+{
+ while (1)
+ {
+ SDL_Delay(HZ/10);
+ if (threads_exit)
+ thread_exit();
+ }
+}
+
+/* A way to yield and leave the threading system for extended periods */
+void sim_thread_lock(void *me)
+{
+ SDL_LockMutex(m);
+ cores[CURRENT_CORE].running = (struct thread_entry *)me;
+
+ if (threads_exit)
+ thread_exit();
+}
+
+void * sim_thread_unlock(void)
+{
+ struct thread_entry *current = cores[CURRENT_CORE].running;
+ SDL_UnlockMutex(m);
+ return current;
+}
+
+struct thread_entry * thread_id_entry(unsigned int thread_id)
+{
+ return (thread_id == THREAD_ID_CURRENT) ?
+ cores[CURRENT_CORE].running :
+ &threads[thread_id & THREAD_ID_SLOT_MASK];
+}
+
+static void add_to_list_l(struct thread_entry **list,
+ struct thread_entry *thread)
+{
+ if (*list == NULL)
+ {
+ /* Insert into unoccupied list */
+ thread->l.next = thread;
+ thread->l.prev = thread;
+ *list = thread;
+ }
+ else
+ {
+ /* Insert last */
+ thread->l.next = *list;
+ thread->l.prev = (*list)->l.prev;
+ thread->l.prev->l.next = thread;
+ (*list)->l.prev = thread;
+ }
+}
+
+static void remove_from_list_l(struct thread_entry **list,
+ struct thread_entry *thread)
+{
+ if (thread == thread->l.next)
+ {
+ /* The only item */
+ *list = NULL;
+ return;
+ }
+
+ if (thread == *list)
+ {
+ /* List becomes next item */
+ *list = thread->l.next;
+ }
+
+ /* Fix links to jump over the removed entry. */
+ thread->l.prev->l.next = thread->l.next;
+ thread->l.next->l.prev = thread->l.prev;
+}
+
+unsigned int thread_get_current(void)
+{
+ return cores[CURRENT_CORE].running->id;
+}
+
+void switch_thread(void)
+{
+ struct thread_entry *current = cores[CURRENT_CORE].running;
+
+ enable_irq();
+
+ switch (current->state)
+ {
+ case STATE_RUNNING:
+ {
+ SDL_UnlockMutex(m);
+ /* Any other thread waiting already will get it first */
+ SDL_LockMutex(m);
+ break;
+ } /* STATE_RUNNING: */
+
+ case STATE_BLOCKED:
+ {
+ int oldlevel;
+
+ SDL_UnlockMutex(m);
+ SDL_SemWait(current->context.s);
+ SDL_LockMutex(m);
+
+ oldlevel = disable_irq_save();
+ current->state = STATE_RUNNING;
+ restore_irq(oldlevel);
+ break;
+ } /* STATE_BLOCKED: */
+
+ case STATE_BLOCKED_W_TMO:
+ {
+ int result, oldlevel;
+
+ SDL_UnlockMutex(m);
+ result = SDL_SemWaitTimeout(current->context.s, current->tmo_tick);
+ SDL_LockMutex(m);
+
+ oldlevel = disable_irq_save();
+
+ if (current->state == STATE_BLOCKED_W_TMO)
+ {
+ /* Timed out */
+ remove_from_list_l(current->bqp, current);
+
+#ifdef HAVE_WAKEUP_EXT_CB
+ if (current->wakeup_ext_cb != NULL)
+ current->wakeup_ext_cb(current);
+#endif
+ current->state = STATE_RUNNING;
+ }
+
+ if (result == SDL_MUTEX_TIMEDOUT)
+ {
+ /* Other signals from an explicit wake could have been made before
+ * arriving here if we timed out waiting for the semaphore. Make
+ * sure the count is reset. */
+ while (SDL_SemValue(current->context.s) > 0)
+ SDL_SemTryWait(current->context.s);
+ }
+
+ restore_irq(oldlevel);
+ break;
+ } /* STATE_BLOCKED_W_TMO: */
+
+ case STATE_SLEEPING:
+ {
+ SDL_UnlockMutex(m);
+ SDL_SemWaitTimeout(current->context.s, current->tmo_tick);
+ SDL_LockMutex(m);
+ current->state = STATE_RUNNING;
+ break;
+ } /* STATE_SLEEPING: */
+ }
+
+ cores[CURRENT_CORE].running = current;
+
+ if (threads_exit)
+ thread_exit();
+}
+
+void sleep_thread(int ticks)
+{
+ struct thread_entry *current = cores[CURRENT_CORE].running;
+ int rem;
+
+ current->state = STATE_SLEEPING;
+
+ rem = (SDL_GetTicks() - start_tick) % (1000/HZ);
+ if (rem < 0)
+ rem = 0;
+
+ current->tmo_tick = (1000/HZ) * ticks + ((1000/HZ)-1) - rem;
+}
+
+void block_thread(struct thread_entry *current)
+{
+ current->state = STATE_BLOCKED;
+ add_to_list_l(current->bqp, current);
+}
+
+void block_thread_w_tmo(struct thread_entry *current, int ticks)
+{
+ current->state = STATE_BLOCKED_W_TMO;
+ current->tmo_tick = (1000/HZ)*ticks;
+ add_to_list_l(current->bqp, current);
+}
+
+unsigned int wakeup_thread(struct thread_entry **list)
+{
+ struct thread_entry *thread = *list;
+
+ if (thread != NULL)
+ {
+ switch (thread->state)
+ {
+ case STATE_BLOCKED:
+ case STATE_BLOCKED_W_TMO:
+ remove_from_list_l(list, thread);
+ thread->state = STATE_RUNNING;
+ SDL_SemPost(thread->context.s);
+ return THREAD_OK;
+ }
+ }
+
+ return THREAD_NONE;
+}
+
+unsigned int thread_queue_wake(struct thread_entry **list)
+{
+ unsigned int result = THREAD_NONE;
+
+ for (;;)
+ {
+ unsigned int rc = wakeup_thread(list);
+
+ if (rc == THREAD_NONE)
+ break;
+
+ result |= rc;
+ }
+
+ return result;
+}
+
+void thread_thaw(unsigned int thread_id)
+{
+ struct thread_entry *thread = thread_id_entry(thread_id);
+
+ if (thread->id == thread_id && thread->state == STATE_FROZEN)
+ {
+ thread->state = STATE_RUNNING;
+ SDL_SemPost(thread->context.s);
+ }
+}
+
+int runthread(void *data)
+{
+ struct thread_entry *current;
+ jmp_buf *current_jmpbuf;
+
+ /* Cannot access thread variables before locking the mutex as the
+ data structures may not be filled-in yet. */
+ SDL_LockMutex(m);
+ cores[CURRENT_CORE].running = (struct thread_entry *)data;
+ current = cores[CURRENT_CORE].running;
+ current_jmpbuf = &thread_jmpbufs[current - threads];
+
+ /* Setup jump for exit */
+ if (setjmp(*current_jmpbuf) == 0)
+ {
+ /* Run the thread routine */
+ if (current->state == STATE_FROZEN)
+ {
+ SDL_UnlockMutex(m);
+ SDL_SemWait(current->context.s);
+ SDL_LockMutex(m);
+ cores[CURRENT_CORE].running = current;
+ }
+
+ if (!threads_exit)
+ {
+ current->context.start();
+ THREAD_SDL_DEBUGF("Thread Done: %d (%s)\n",
+ current - threads, THREAD_SDL_GET_NAME(current));
+ /* Thread routine returned - suicide */
+ }
+
+ thread_exit();
+ }
+ else
+ {
+ /* Unlock and exit */
+ SDL_UnlockMutex(m);
+ }
+
+ return 0;
+}
+
+unsigned int create_thread(void (*function)(void),
+ void* stack, size_t stack_size,
+ unsigned flags, const char *name)
+{
+ struct thread_entry *thread;
+ SDL_Thread* t;
+ SDL_sem *s;
+
+ THREAD_SDL_DEBUGF("Creating thread: (%s)\n", name ? name : "");
+
+ thread = find_empty_thread_slot();
+ if (thread == NULL)
+ {
+ DEBUGF("Failed to find thread slot\n");
+ return 0;
+ }
+
+ s = SDL_CreateSemaphore(0);
+ if (s == NULL)
+ {
+ DEBUGF("Failed to create semaphore\n");
+ return 0;
+ }
+
+ t = SDL_CreateThread(runthread, thread);
+ if (t == NULL)
+ {
+ DEBUGF("Failed to create SDL thread\n");
+ SDL_DestroySemaphore(s);
+ return 0;
+ }
+
+ thread->stack = stack;
+ thread->stack_size = stack_size;
+ thread->name = name;
+ thread->state = (flags & CREATE_THREAD_FROZEN) ?
+ STATE_FROZEN : STATE_RUNNING;
+ thread->context.start = function;
+ thread->context.t = t;
+ thread->context.s = s;
+
+ THREAD_SDL_DEBUGF("New Thread: %d (%s)\n",
+ thread - threads, THREAD_SDL_GET_NAME(thread));
+
+ return thread->id;
+}
+
+#ifndef ALLOW_REMOVE_THREAD
+static void remove_thread(unsigned int thread_id)
+#else
+void remove_thread(unsigned int thread_id)
+#endif
+{
+ struct thread_entry *current = cores[CURRENT_CORE].running;
+ struct thread_entry *thread = thread_id_entry(thread_id);
+
+ SDL_Thread *t;
+ SDL_sem *s;
+
+ if (thread_id != THREAD_ID_CURRENT && thread->id != thread_id)
+ return;
+
+ int oldlevel = disable_irq_save();
+
+ t = thread->context.t;
+ s = thread->context.s;
+ thread->context.t = NULL;
+
+ if (thread != current)
+ {
+ switch (thread->state)
+ {
+ case STATE_BLOCKED:
+ case STATE_BLOCKED_W_TMO:
+ /* Remove thread from object it's waiting on */
+ remove_from_list_l(thread->bqp, thread);
+
+#ifdef HAVE_WAKEUP_EXT_CB
+ if (thread->wakeup_ext_cb != NULL)
+ thread->wakeup_ext_cb(thread);
+#endif
+ break;
+ }
+
+ SDL_SemPost(s);
+ }
+
+ THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n",
+ thread - threads, THREAD_SDL_GET_NAME(thread));
+
+ new_thread_id(thread->id, thread);
+ thread->state = STATE_KILLED;
+ thread_queue_wake(&thread->queue);
+
+ SDL_DestroySemaphore(s);
+
+ if (thread == current)
+ {
+ /* Do a graceful exit - perform the longjmp back into the thread
+ function to return */
+ restore_irq(oldlevel);
+ longjmp(thread_jmpbufs[current - threads], 1);
+ }
+
+ SDL_KillThread(t);
+ restore_irq(oldlevel);
+}
+
+void thread_exit(void)
+{
+ remove_thread(THREAD_ID_CURRENT);
+}
+
+void thread_wait(unsigned int thread_id)
+{
+ struct thread_entry *current = cores[CURRENT_CORE].running;
+ struct thread_entry *thread = thread_id_entry(thread_id);
+
+ if (thread_id == THREAD_ID_CURRENT ||
+ (thread->id == thread_id && thread->state != STATE_KILLED))
+ {
+ current->bqp = &thread->queue;
+ block_thread(current);
+ switch_thread();
+ }
+}
+
+int thread_stack_usage(const struct thread_entry *thread)
+{
+ return 50;
+ (void)thread;
+}
+
+/* Return name if one or ID if none */
+void thread_get_name(char *buffer, int size,
+ struct thread_entry *thread)
+{
+ if (size <= 0)
+ return;
+
+ *buffer = '\0';
+
+ if (thread)
+ {
+ /* Display thread name if one or ID if none */
+ bool named = thread->name && *thread->name;
+ const char *fmt = named ? "%s" : "%08lX";
+ intptr_t name = named ?
+ (intptr_t)thread->name : (intptr_t)thread;
+ snprintf(buffer, size, fmt, name);
+ }
+}
diff --git a/firmware/target/hosted/sdl/thread-sdl.h b/firmware/target/hosted/sdl/thread-sdl.h
new file mode 100644
index 0000000000..9384e6060d
--- /dev/null
+++ b/firmware/target/hosted/sdl/thread-sdl.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __THREADSDL_H__
+#define __THREADSDL_H__
+
+/* extra thread functions that only apply when running on hosting platforms */
+void sim_thread_lock(void *me);
+void * sim_thread_unlock(void);
+void sim_thread_exception_wait(void);
+void sim_thread_shutdown(void); /* Shut down all kernel threads gracefully */
+
+#endif /* #ifndef __THREADSDL_H__ */
+
diff --git a/firmware/target/hosted/sdl/timer-sdl.c b/firmware/target/hosted/sdl/timer-sdl.c
new file mode 100644
index 0000000000..369aeab929
--- /dev/null
+++ b/firmware/target/hosted/sdl/timer-sdl.c
@@ -0,0 +1,61 @@
+/***************************************************************************
+* __________ __ ___.
+* Open \______ \ ____ ____ | | _\_ |__ _______ ___
+* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+* \/ \/ \/ \/ \/
+* $Id: timer.h 13806 2007-07-06 21:36:32Z jethead71 $
+*
+* Copyright (C) 2005 Kévin Ferrare
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+* KIND, either express or implied.
+*
+****************************************************************************/
+
+#include "timer.h"
+#include <SDL_timer.h>
+
+static int timer_prio = -1;
+void (*global_timer_callback)(void);
+SDL_TimerID timerId;
+
+Uint32 SDL_timer_callback(Uint32 interval, void *param){
+ (void)param;
+ global_timer_callback();
+ return(interval);
+}
+
+#define cycles_to_miliseconds(cycles) \
+ ((int)((1000*cycles)/TIMER_FREQ))
+
+bool timer_register(int reg_prio, void (*unregister_callback)(void),
+ long cycles, void (*timer_callback)(void))
+{
+ (void)unregister_callback;
+ if (reg_prio <= timer_prio || cycles == 0)
+ return false;
+ timer_prio=reg_prio;
+ global_timer_callback=timer_callback;
+ timerId=SDL_AddTimer(cycles_to_miliseconds(cycles), SDL_timer_callback, 0);
+ return true;
+}
+
+bool timer_set_period(long cycles)
+{
+ SDL_RemoveTimer (timerId);
+ timerId=SDL_AddTimer(cycles_to_miliseconds(cycles), SDL_timer_callback, 0);
+ return true;
+}
+
+void timer_unregister(void)
+{
+ SDL_RemoveTimer (timerId);
+ timer_prio = -1;
+}