summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Jarosch <tomj@simonv.com>2011-02-08 20:05:25 +0000
committerThomas Jarosch <tomj@simonv.com>2011-02-08 20:05:25 +0000
commit5f037ac015e6d76d030a163753db5ff58cdff49b (patch)
treef5eb7dcdc0e0c3e373227e45061c1d99a14a0819
parent4d129044390a087b6193b6ce63e035b2550b3ce4 (diff)
downloadrockbox-5f037ac015e6d76d030a163753db5ff58cdff49b.tar.gz
rockbox-5f037ac015e6d76d030a163753db5ff58cdff49b.zip
Initial maemo platform support
Adds Nokia N900, N810 and N800 support. Features: - Introduce maemo specific platform defines - Play audio in silent mode - Stop playback on incoming calls - Battery level readout - Bluetooth headset support - Save CPU by disabling screen updates if the display is off or the app doesn't have input focus - N900: GStreamer audio backend Kudos to kugel for the code review. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29248 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs.c2
-rw-r--r--apps/main.c4
-rw-r--r--apps/misc.c4
-rw-r--r--firmware/SOURCES11
-rw-r--r--firmware/common/filefuncs.c2
-rw-r--r--firmware/common/rbpaths.c2
-rw-r--r--firmware/drivers/audio/sdl.c6
-rw-r--r--firmware/export/config.h10
-rw-r--r--firmware/export/config/application.h13
-rw-r--r--firmware/export/debug.h2
-rw-r--r--firmware/include/dir_uncached.h2
-rw-r--r--firmware/include/file.h2
-rw-r--r--firmware/target/hosted/maemo/maemo-thread.c220
-rw-r--r--firmware/target/hosted/maemo/maemo-thread.h36
-rw-r--r--firmware/target/hosted/maemo/pcm-gstreamer.c459
-rw-r--r--firmware/target/hosted/sdl/app/button-application.c16
-rw-r--r--firmware/target/hosted/sdl/button-sdl.c27
-rw-r--r--firmware/target/hosted/sdl/button-sdl.h2
-rw-r--r--firmware/target/hosted/sdl/lcd-bitmap.c14
-rw-r--r--firmware/target/hosted/sdl/system-sdl.c50
-rwxr-xr-xtools/configure106
-rw-r--r--uisimulator/common/SOURCES2
22 files changed, 970 insertions, 22 deletions
diff --git a/apps/codecs.c b/apps/codecs.c
index 88478e8566..646d5f289b 100644
--- a/apps/codecs.c
+++ b/apps/codecs.c
@@ -54,7 +54,7 @@
54#define LOGF_ENABLE 54#define LOGF_ENABLE
55#include "logf.h" 55#include "logf.h"
56 56
57#if (CONFIG_PLATFORM & PLATFORM_SDL) 57#if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO))
58#define PREFIX(_x_) sim_ ## _x_ 58#define PREFIX(_x_) sim_ ## _x_
59#else 59#else
60#define PREFIX(_x_) _x_ 60#define PREFIX(_x_) _x_
diff --git a/apps/main.c b/apps/main.c
index 6378833973..3fc48be183 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -125,7 +125,7 @@
125#define MAIN_NORETURN_ATTR 125#define MAIN_NORETURN_ATTR
126#endif 126#endif
127 127
128#if (CONFIG_PLATFORM & PLATFORM_SDL) 128#if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO))
129#include "sim_tasks.h" 129#include "sim_tasks.h"
130#include "system-sdl.h" 130#include "system-sdl.h"
131#define HAVE_ARGV_MAIN 131#define HAVE_ARGV_MAIN
@@ -351,7 +351,7 @@ static void init(void)
351 show_logo(); 351 show_logo();
352 button_init(); 352 button_init();
353 backlight_init(); 353 backlight_init();
354#if (CONFIG_PLATFORM & PLATFORM_SDL) 354#if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO))
355 sim_tasks_init(); 355 sim_tasks_init();
356#endif 356#endif
357#if (CONFIG_PLATFORM & PLATFORM_ANDROID) 357#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
diff --git a/apps/misc.c b/apps/misc.c
index 94b2de4a3f..a08dac3ebf 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -526,7 +526,7 @@ static void unplug_change(bool inserted)
526 526
527long default_event_handler_ex(long event, void (*callback)(void *), void *parameter) 527long default_event_handler_ex(long event, void (*callback)(void *), void *parameter)
528{ 528{
529#if CONFIG_PLATFORM & PLATFORM_ANDROID 529#if CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO)
530 static bool resume = false; 530 static bool resume = false;
531#endif 531#endif
532 532
@@ -619,7 +619,7 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame
619 iap_handlepkt(); 619 iap_handlepkt();
620 return SYS_IAP_HANDLEPKT; 620 return SYS_IAP_HANDLEPKT;
621#endif 621#endif
622#if CONFIG_PLATFORM & PLATFORM_ANDROID 622#if CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO)
623 /* stop playback if we receive a call */ 623 /* stop playback if we receive a call */
624 case SYS_CALL_INCOMING: 624 case SYS_CALL_INCOMING:
625 resume = audio_status() == AUDIO_STATUS_PLAY; 625 resume = audio_status() == AUDIO_STATUS_PLAY;
diff --git a/firmware/SOURCES b/firmware/SOURCES
index ae0c8a4f20..9c9ebf53fc 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -47,6 +47,11 @@ target/hosted/sdl/app/button-application.c
47#endif 47#endif
48#endif 48#endif
49 49
50/* Maemo specific files */
51#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
52target/hosted/maemo/maemo-thread.c
53#endif
54
50/* Standard library */ 55/* Standard library */
51#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(__MINGW32__) || defined(__CYGWIN__) 56#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(__MINGW32__) || defined(__CYGWIN__)
52libc/errno.c 57libc/errno.c
@@ -339,8 +344,12 @@ drivers/audio/cs42l55.c
339#elif defined(HAVE_SDL_AUDIO) 344#elif defined(HAVE_SDL_AUDIO)
340drivers/audio/sdl.c 345drivers/audio/sdl.c
341#if CONFIG_CODEC == SWCODEC 346#if CONFIG_CODEC == SWCODEC
347#if (CONFIG_PLATFORM & PLATFORM_MAEMO5)
348target/hosted/maemo/pcm-gstreamer.c
349#else
342target/hosted/sdl/pcm-sdl.c 350target/hosted/sdl/pcm-sdl.c
343#endif 351#endif /* (CONFIG_PLATFORM & PLATFORM_MAEMO) */
352#endif /* CONFIG_CODEC == SWCODEC */
344#endif /* (CONFIG_PLATFORM & PLATFORM_NATIVE) && !defined(BOOTLOADER) */ 353#endif /* (CONFIG_PLATFORM & PLATFORM_NATIVE) && !defined(BOOTLOADER) */
345 354
346/* USB Stack */ 355/* USB Stack */
diff --git a/firmware/common/filefuncs.c b/firmware/common/filefuncs.c
index c31971779d..3811f06ec9 100644
--- a/firmware/common/filefuncs.c
+++ b/firmware/common/filefuncs.c
@@ -91,7 +91,7 @@ bool dir_exists(const char *path)
91 91
92#endif /* __PCTOOL__ */ 92#endif /* __PCTOOL__ */
93 93
94#if (CONFIG_PLATFORM & (PLATFORM_NATIVE|PLATFORM_SDL)) 94#if (CONFIG_PLATFORM & (PLATFORM_NATIVE|PLATFORM_SDL|PLATFORM_MAEMO))
95struct dirinfo dir_get_info(DIR* parent, struct dirent *entry) 95struct dirinfo dir_get_info(DIR* parent, struct dirent *entry)
96{ 96{
97 (void)parent; 97 (void)parent;
diff --git a/firmware/common/rbpaths.c b/firmware/common/rbpaths.c
index 2d3c1e6603..ddfcff47b7 100644
--- a/firmware/common/rbpaths.c
+++ b/firmware/common/rbpaths.c
@@ -42,7 +42,7 @@
42#define opendir opendir_android 42#define opendir opendir_android
43#define mkdir mkdir_android 43#define mkdir mkdir_android
44#define rmdir rmdir_android 44#define rmdir rmdir_android
45#elif (CONFIG_PLATFORM & PLATFORM_SDL) 45#elif (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO))
46#define open sim_open 46#define open sim_open
47#define remove sim_remove 47#define remove sim_remove
48#define rename sim_rename 48#define rename sim_rename
diff --git a/firmware/drivers/audio/sdl.c b/firmware/drivers/audio/sdl.c
index 7d6d7452df..021a65b9f8 100644
--- a/firmware/drivers/audio/sdl.c
+++ b/firmware/drivers/audio/sdl.c
@@ -34,11 +34,15 @@ extern void pcm_set_mixer_volume(int);
34void audiohw_set_volume(int volume) 34void audiohw_set_volume(int volume)
35{ 35{
36#if CONFIG_CODEC == SWCODEC 36#if CONFIG_CODEC == SWCODEC
37#if (CONFIG_PLATFORM & PLATFORM_MAEMO5)
38 pcm_set_mixer_volume(volume);
39#else
37 pcm_set_mixer_volume( 40 pcm_set_mixer_volume(
38 SDL_MIX_MAXVOLUME * ((volume - VOLUME_MIN) / 10) / (VOLUME_RANGE / 10)); 41 SDL_MIX_MAXVOLUME * ((volume - VOLUME_MIN) / 10) / (VOLUME_RANGE / 10));
42#endif /* (CONFIG_PLATFORM & PLATFORM_MAEMO) */
39#else 43#else
40 (void)volume; 44 (void)volume;
41#endif 45#endif /* CONFIG_CODEC == SWCODEC */
42} 46}
43 47
44const struct sound_settings_info audiohw_settings[] = { 48const struct sound_settings_info audiohw_settings[] = {
diff --git a/firmware/export/config.h b/firmware/export/config.h
index d59b259fb9..3063e1f06d 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -83,6 +83,9 @@
83#define PLATFORM_HOSTED (1<<1) 83#define PLATFORM_HOSTED (1<<1)
84#define PLATFORM_ANDROID (1<<2) 84#define PLATFORM_ANDROID (1<<2)
85#define PLATFORM_SDL (1<<3) 85#define PLATFORM_SDL (1<<3)
86#define PLATFORM_MAEMO4 (1<<4)
87#define PLATFORM_MAEMO5 (1<<5)
88#define PLATFORM_MAEMO (PLATFORM_MAEMO4|PLATFORM_MAEMO5)
86 89
87/* CONFIG_KEYPAD */ 90/* CONFIG_KEYPAD */
88#define PLAYER_PAD 1 91#define PLAYER_PAD 1
@@ -500,7 +503,12 @@ Lyre prototype 1 */
500#endif 503#endif
501 504
502/* define for all cpus from ARM family */ 505/* define for all cpus from ARM family */
503#if (CONFIG_CPU == IMX31L) 506#if (CONFIG_PLATFORM & PLATFORM_MAEMO5) && defined(MAEMO_ARM_BUILD)
507#define CPU_ARM
508#define ARM_ARCH 7 /* ARMv7 */
509
510#elif (CONFIG_CPU == IMX31L) \
511 || ((CONFIG_PLATFORM & PLATFORM_MAEMO4) && defined(MAEMO_ARM_BUILD))
504#define CPU_ARM 512#define CPU_ARM
505#define ARM_ARCH 6 /* ARMv6 */ 513#define ARM_ARCH 6 /* ARMv6 */
506 514
diff --git a/firmware/export/config/application.h b/firmware/export/config/application.h
index b731f0cf76..64ebbf3685 100644
--- a/firmware/export/config/application.h
+++ b/firmware/export/config/application.h
@@ -6,6 +6,10 @@
6/* We don't run on hardware directly */ 6/* We don't run on hardware directly */
7#ifdef ANDROID 7#ifdef ANDROID
8#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID) 8#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID)
9#elif MAEMO5
10#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_MAEMO5)
11#elif MAEMO4
12#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_MAEMO4)
9#else 13#else
10#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_SDL) 14#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_SDL)
11#endif 15#endif
@@ -75,17 +79,20 @@
75/* Define this if you do software codec */ 79/* Define this if you do software codec */
76#define CONFIG_CODEC SWCODEC 80#define CONFIG_CODEC SWCODEC
77 81
82#if (CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO))
83#define HAVE_MULTIMEDIA_KEYS
84#endif
85
78#if (CONFIG_PLATFORM & PLATFORM_ANDROID) 86#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
79#define CONFIG_KEYPAD ANDROID_PAD 87#define CONFIG_KEYPAD ANDROID_PAD
80#define HAVE_MULTIMEDIA_KEYS 88#elif (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO))
81#elif (CONFIG_PLATFORM & PLATFORM_SDL)
82#define HAVE_SCROLLWHEEL 89#define HAVE_SCROLLWHEEL
83#define CONFIG_KEYPAD SDL_PAD 90#define CONFIG_KEYPAD SDL_PAD
84#else 91#else
85#error unknown platform 92#error unknown platform
86#endif 93#endif
87 94
88#if (CONFIG_PLATFORM & PLATFORM_SDL) 95#if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO))
89/* Use SDL audio/pcm in a SDL app build */ 96/* Use SDL audio/pcm in a SDL app build */
90#define HAVE_SDL 97#define HAVE_SDL
91#define HAVE_SDL_AUDIO 98#define HAVE_SDL_AUDIO
diff --git a/firmware/export/debug.h b/firmware/export/debug.h
index 043ec26bbb..99cdf42c05 100644
--- a/firmware/export/debug.h
+++ b/firmware/export/debug.h
@@ -34,7 +34,7 @@ extern void ldebugf(const char* file, int line, const char *fmt, ...)
34 34
35/* */ 35/* */
36#if defined(SIMULATOR) && !defined(__PCTOOL__) \ 36#if defined(SIMULATOR) && !defined(__PCTOOL__) \
37 || ((CONFIG_PLATFORM & PLATFORM_ANDROID) && defined(DEBUG)) 37 || ((CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO)) && defined(DEBUG))
38#define DEBUGF debugf 38#define DEBUGF debugf
39#define LDEBUGF(...) ldebugf(__FILE__, __LINE__, __VA_ARGS__) 39#define LDEBUGF(...) ldebugf(__FILE__, __LINE__, __VA_ARGS__)
40#else 40#else
diff --git a/firmware/include/dir_uncached.h b/firmware/include/dir_uncached.h
index 3bae07177b..c2c7d67505 100644
--- a/firmware/include/dir_uncached.h
+++ b/firmware/include/dir_uncached.h
@@ -33,7 +33,7 @@ struct dirinfo {
33#include <stdbool.h> 33#include <stdbool.h>
34#include "file.h" 34#include "file.h"
35 35
36#if (CONFIG_PLATFORM & PLATFORM_SDL) 36#if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO))
37# define dirent_uncached sim_dirent 37# define dirent_uncached sim_dirent
38# define DIR_UNCACHED SIM_DIR 38# define DIR_UNCACHED SIM_DIR
39# define opendir_uncached sim_opendir 39# define opendir_uncached sim_opendir
diff --git a/firmware/include/file.h b/firmware/include/file.h
index ee52c3f2b7..69ed394828 100644
--- a/firmware/include/file.h
+++ b/firmware/include/file.h
@@ -46,7 +46,7 @@ extern int app_open(const char *name, int o, ...);
46extern int app_creat(const char *name, mode_t mode); 46extern int app_creat(const char *name, mode_t mode);
47extern int app_remove(const char* pathname); 47extern int app_remove(const char* pathname);
48extern int app_rename(const char* path, const char* newname); 48extern int app_rename(const char* path, const char* newname);
49# if (CONFIG_PLATFORM & PLATFORM_SDL) 49# if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO))
50# define filesize(x) sim_filesize(x) 50# define filesize(x) sim_filesize(x)
51# define fsync(x) sim_fsync(x) 51# define fsync(x) sim_fsync(x)
52# define ftruncate(x,y) sim_ftruncate(x,y) 52# define ftruncate(x,y) sim_ftruncate(x,y)
diff --git a/firmware/target/hosted/maemo/maemo-thread.c b/firmware/target/hosted/maemo/maemo-thread.c
new file mode 100644
index 0000000000..f655ed597e
--- /dev/null
+++ b/firmware/target/hosted/maemo/maemo-thread.c
@@ -0,0 +1,220 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 by Thomas Jarosch
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22
23#include <libhal.h>
24#include <libosso.h>
25#include <SDL_thread.h>
26
27#include "config.h"
28#include "system.h"
29#include "kernel.h"
30#include "thread.h"
31#include "power.h"
32#include "debug.h"
33#include "button.h"
34
35/* Battery status information */
36#define BME_UDI "/org/freedesktop/Hal/devices/bme"
37#define BATTERY_PERCENTAGE "battery.charge_level.percentage"
38#define BATTER_REMAINING_TIME "battery.remaining_time"
39
40/* Bluetooth headset support */
41#define BT_HEADSET_UDI "/org/freedesktop/Hal/devices/computer_logicaldev_input_1"
42
43GMainLoop *maemo_main_loop = NULL;
44osso_context_t *maemo_osso_ctx = NULL;
45
46volatile int maemo_display_on = 1;
47volatile int maemo_battery_level = 0;
48volatile int maemo_remaining_time_sec = 0;
49
50extern void send_battery_level_event(void);
51extern int last_sent_battery_level;
52extern int battery_percent;
53
54void display_status_callback(osso_display_state_t state, gpointer data)
55{
56 (void)data;
57
58 if (state == OSSO_DISPLAY_OFF)
59 maemo_display_on = 0;
60 else
61 maemo_display_on = 1;
62}
63
64
65void get_battery_values(LibHalContext *ctx)
66{
67 /* Get initial battery percentage and remaining time */
68 maemo_battery_level = libhal_device_get_property_int(
69 ctx, BME_UDI,
70 BATTERY_PERCENTAGE, NULL);
71
72 maemo_remaining_time_sec = libhal_device_get_property_int(
73 ctx, BME_UDI,
74 BATTER_REMAINING_TIME, NULL);
75
76 DEBUGF("[maemo] Battery percentage: %d, remaining_time_sec: %d\n", maemo_battery_level, maemo_remaining_time_sec);
77}
78
79static void on_battery_changed (LibHalContext *ctx,
80 const char *udi,
81 const char *key,
82 dbus_bool_t is_removed,
83 dbus_bool_t is_added)
84{
85 (void)is_removed;
86 (void)is_added;
87
88 if (!g_str_equal (udi, BME_UDI))
89 return;
90
91 if (!g_str_equal (key, BATTERY_PERCENTAGE) && !g_str_equal (key, BATTER_REMAINING_TIME))
92 return;
93
94 get_battery_values(ctx);
95}
96
97static void on_bt_button_pressed(LibHalContext *ctx,
98 const char *udi,
99 const char *condition_name,
100 const char *condition_detail)
101{
102 (void)ctx;
103
104 if (!g_str_equal (udi, BT_HEADSET_UDI) || !g_str_equal(condition_name, "ButtonPressed"))
105 return;
106
107 sim_enter_irq_handler();
108
109 if (g_str_equal(condition_detail, "play-cd") || g_str_equal(condition_detail, "pause-cd"))
110 queue_post(&button_queue, BUTTON_MULTIMEDIA_PLAYPAUSE, 0);
111 else if (g_str_equal(condition_detail, "stop-cd"))
112 queue_post(&button_queue, BUTTON_MULTIMEDIA_STOP, 0);
113 else if (g_str_equal(condition_detail, "next-song"))
114 queue_post(&button_queue, BUTTON_MULTIMEDIA_NEXT, 0);
115 else if (g_str_equal(condition_detail, "previous-song"))
116 queue_post(&button_queue, BUTTON_MULTIMEDIA_PREV, 0);
117 else if (g_str_equal(condition_detail, "fast-forward"))
118 queue_post(&button_queue, BUTTON_MULTIMEDIA_FFWD, 0);
119 else if (g_str_equal(condition_detail, "rewind"))
120 queue_post(&button_queue, BUTTON_MULTIMEDIA_REW, 0);
121
122 sim_exit_irq_handler();
123}
124
125int maemo_thread_func (void *wait_for_osso_startup)
126{
127 maemo_main_loop = g_main_loop_new (NULL, FALSE);
128
129 /* Register display callback */
130 maemo_osso_ctx = osso_initialize ("rockbox", "666", FALSE, NULL);
131 osso_hw_set_display_event_cb(maemo_osso_ctx, display_status_callback, NULL);
132
133 /* Register battery status callback */
134 LibHalContext *hal_ctx;
135 hal_ctx = libhal_ctx_new();
136
137 DBusConnection *system_bus = (DBusConnection*)osso_get_sys_dbus_connection(maemo_osso_ctx);
138 libhal_ctx_set_dbus_connection(hal_ctx, system_bus);
139
140 libhal_ctx_init(hal_ctx, NULL);
141 libhal_ctx_set_device_property_modified (hal_ctx, on_battery_changed);
142 libhal_device_add_property_watch (hal_ctx, BME_UDI, NULL);
143
144 /* Work around libhal API issue: We need to add a property watch
145 to get the condition change callback working */
146 libhal_device_add_property_watch (hal_ctx, BT_HEADSET_UDI, NULL);
147 libhal_ctx_set_device_condition(hal_ctx, on_bt_button_pressed);
148
149 get_battery_values(hal_ctx);
150
151 /* let system_init proceed */
152 SDL_SemPost((SDL_sem *)wait_for_osso_startup);
153
154 g_main_loop_run (maemo_main_loop);
155
156 /* Cleanup */
157 osso_deinitialize (maemo_osso_ctx);
158 libhal_device_remove_property_watch (hal_ctx, BT_HEADSET_UDI, NULL);
159 libhal_device_remove_property_watch (hal_ctx, BME_UDI, NULL);
160 libhal_ctx_shutdown (hal_ctx, NULL);
161 libhal_ctx_free(hal_ctx);
162
163 return 0;
164}
165
166/** Rockbox battery related functions */
167void battery_status_update(void)
168{
169 battery_percent = maemo_battery_level;
170 send_battery_level_event();
171}
172
173/* Returns true if any power input is connected - charging-capable
174 * or not. */
175bool power_input_present(void)
176{
177 return false;
178}
179
180unsigned battery_voltage(void)
181{
182 return 0;
183}
184
185/* Returns battery level in percent */
186int battery_level(void)
187{
188 battery_status_update();
189 return maemo_battery_level;
190}
191
192/* Return remaining battery time in minutes */
193int battery_time(void)
194{
195 battery_status_update();
196 return maemo_remaining_time_sec / 60;
197}
198
199bool battery_level_safe(void)
200{
201 return battery_level() >= 5;
202}
203
204/** Rockbox stubs */
205void set_poweroff_timeout(int timeout)
206{
207 (void)timeout;
208}
209
210void reset_poweroff_timer(void)
211{
212}
213
214void shutdown_hw(void)
215{
216}
217
218void cancel_shutdown(void)
219{
220}
diff --git a/firmware/target/hosted/maemo/maemo-thread.h b/firmware/target/hosted/maemo/maemo-thread.h
new file mode 100644
index 0000000000..a0996b4945
--- /dev/null
+++ b/firmware/target/hosted/maemo/maemo-thread.h
@@ -0,0 +1,36 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 by Thomas Jarosch
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef __MAEMO_THREAD_H__
22#define __MAEMO_THREAD_H__
23
24#include <glib.h>
25#include <libosso.h>
26
27extern osso_context_t *maemo_osso_ctx;
28extern GMainLoop *maemo_main_loop;
29
30extern volatile int maemo_display_on;
31extern volatile int maemo_has_input_focus;
32
33int maemo_thread_func(void *unused);
34void pcm_shutdown_gstreamer(void);
35
36#endif
diff --git a/firmware/target/hosted/maemo/pcm-gstreamer.c b/firmware/target/hosted/maemo/pcm-gstreamer.c
new file mode 100644
index 0000000000..e3e40f0619
--- /dev/null
+++ b/firmware/target/hosted/maemo/pcm-gstreamer.c
@@ -0,0 +1,459 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 by Thomas Jarosch
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22
23#include "autoconf.h"
24
25#include <stdbool.h>
26#include "config.h"
27#include "debug.h"
28#include "sound.h"
29#include "audiohw.h"
30#include "system.h"
31#include "settings.h"
32#include "debug.h"
33
34#include "playback.h"
35#include "kernel.h"
36
37#include <SDL.h>
38#include <glib.h>
39#include <gst/gst.h>
40#include <gst/app/gstappsrc.h>
41#include <linux/types.h>
42
43/* Maemo5: N900 specific libplayback support */
44#include <libplayback/playback.h>
45#include <dbus/dbus-glib.h>
46#include <dbus/dbus-glib-lowlevel.h>
47#include "maemo-thread.h"
48
49#ifdef HAVE_RECORDING
50#include "audiohw.h"
51#ifdef HAVE_SPDIF_IN
52#include "spdif.h"
53#endif
54#endif
55
56#include "pcm.h"
57#include "pcm_sampr.h"
58
59/*#define LOGF_ENABLE*/
60#include "logf.h"
61
62#ifdef DEBUG
63#include <stdio.h>
64extern bool debug_audio;
65#endif
66
67#if CONFIG_CODEC == SWCODEC
68
69/* Declarations for libplayblack */
70pb_playback_t *playback = NULL;
71void playback_state_req_handler(pb_playback_t *pb,
72 enum pb_state_e req_state,
73 pb_req_t *ext_req,
74 void *data);
75void playback_state_req_callback(pb_playback_t *pb,
76 enum pb_state_e granted_state,
77 const char *reason,
78 pb_req_t *req,
79 void *data);
80bool playback_granted = false;
81
82/* Gstreamer related vars */
83GstCaps *gst_audio_caps = NULL;
84GstElement *gst_pipeline = NULL;
85GstElement *gst_appsrc = NULL;
86GstElement *gst_volume = NULL;
87GstElement *gst_pulsesink = NULL;
88GstBus *gst_bus = NULL;
89static int bus_watch_id = 0;
90GMainLoop *pcm_loop = NULL;
91
92static __u8* pcm_data = NULL;
93static size_t pcm_data_size = 0;
94
95static int inside_feed_data = 0;
96
97void pcm_play_lock(void)
98{
99}
100
101void pcm_play_unlock(void)
102{
103}
104
105void pcm_dma_apply_settings(void)
106{
107}
108
109void pcm_play_dma_start(const void *addr, size_t size)
110{
111 pcm_data = (__u8 *) addr;
112 pcm_data_size = size;
113
114 if (playback_granted)
115 {
116 /* Start playing now */
117 if (!inside_feed_data)
118 gst_element_set_state (GST_ELEMENT(gst_pipeline), GST_STATE_PLAYING);
119 else
120 DEBUGF("ERROR: dma_start called while inside feed_data\n");
121 } else
122 {
123 /* N900: Request change to playing state */
124 pb_playback_req_state (playback,
125 PB_STATE_PLAY,
126 playback_state_req_callback,
127 NULL);
128 }
129}
130
131void pcm_play_dma_stop(void)
132{
133 if (inside_feed_data)
134 g_signal_emit_by_name (gst_appsrc, "end-of-stream", NULL);
135 else
136 gst_element_set_state (GST_ELEMENT(gst_pipeline), GST_STATE_NULL);
137}
138
139void pcm_play_dma_pause(bool pause)
140{
141 if (inside_feed_data)
142 {
143 if (pause)
144 g_signal_emit_by_name (gst_appsrc, "end-of-stream", NULL);
145 else
146 DEBUGF("ERROR: Called dma_pause(0) while inside feed_data\n");
147 } else
148 {
149 if (pause)
150 gst_element_set_state (GST_ELEMENT(gst_pipeline), GST_STATE_NULL);
151 else
152 gst_element_set_state (GST_ELEMENT(gst_pipeline), GST_STATE_PLAYING);
153 }
154}
155
156size_t pcm_get_bytes_waiting(void)
157{
158 return pcm_data_size;
159}
160
161static void feed_data(GstElement * appsrc, guint size_hint, void *unused)
162{
163 (void)size_hint;
164 (void)unused;
165
166 /* Make sure we don't trigger a gst_element_set_state() call
167 from inside gstreamer's stream thread as it will deadlock */
168 inside_feed_data = 1;
169
170 pcm_play_get_more_callback((void **)&pcm_data, &pcm_data_size);
171
172 if (pcm_data_size != 0)
173 {
174 GstBuffer *buffer = gst_buffer_new ();
175 GstFlowReturn ret;
176
177 GST_BUFFER_DATA (buffer) = pcm_data;
178 GST_BUFFER_SIZE (buffer) = pcm_data_size;
179
180 g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
181 gst_buffer_unref (buffer);
182
183 if (ret != 0)
184 DEBUGF("push-buffer error result: %d\n", ret);
185 } else
186 {
187 DEBUGF("feed_data: No Data.\n");
188 g_signal_emit_by_name (appsrc, "end-of-stream", NULL);
189 }
190
191 inside_feed_data = 0;
192}
193
194const void * pcm_play_dma_get_peak_buffer(int *count)
195{
196 uintptr_t addr = (uintptr_t)pcm_data;
197 *count = pcm_data_size / 4;
198 return (void *)((addr + 2) & ~3);
199}
200
201
202static gboolean
203gst_bus_message (GstBus * bus, GstMessage * message, void *unused)
204{
205 (void)bus;
206 (void)unused;
207
208 DEBUGF(" [gst] got BUS message %s\n",
209 gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
210
211 switch (GST_MESSAGE_TYPE (message)) {
212 case GST_MESSAGE_ERROR:
213 {
214 GError *err;
215 gchar *debug;
216 gst_message_parse_error (message, &err, &debug);
217
218 DEBUGF("[gst] Received error: Src: %s, msg: %s\n", GST_MESSAGE_SRC_NAME(message), err->message);
219
220 g_error_free (err);
221 g_free (debug);
222 }
223
224 g_main_loop_quit (pcm_loop);
225 break;
226 case GST_MESSAGE_EOS:
227 gst_element_set_state (GST_ELEMENT(gst_pipeline), GST_STATE_NULL);
228 break;
229 case GST_MESSAGE_STATE_CHANGED:
230 {
231 GstState old_state, new_state;
232
233 gst_message_parse_state_changed (message, &old_state, &new_state, NULL);
234 DEBUGF("[gst] Element %s changed state from %s to %s.\n",
235 GST_MESSAGE_SRC_NAME(message),
236 gst_element_state_get_name (old_state),
237 gst_element_state_get_name (new_state));
238 break;
239 }
240 default:
241 break;
242 }
243
244 return TRUE;
245}
246
247void maemo_configure_appsrc(void)
248{
249 /* Block push-buffer until there is enough room */
250 g_object_set (G_OBJECT(gst_appsrc), "block", TRUE, NULL);
251
252 g_object_set(G_OBJECT(gst_appsrc), "format", GST_FORMAT_BYTES, NULL);
253
254 gst_audio_caps = gst_caps_new_simple("audio/x-raw-int", "width", G_TYPE_INT, (gint)16, "depth", G_TYPE_INT, (gint)16, "channels" ,G_TYPE_INT, (gint)2,
255 "signed",G_TYPE_BOOLEAN,1,
256 "rate",G_TYPE_INT,44100,"endianness",G_TYPE_INT,(gint)1234,NULL);
257
258 g_object_set (G_OBJECT(gst_appsrc), "caps", gst_audio_caps, NULL);
259
260 gst_app_src_set_stream_type(GST_APP_SRC(gst_appsrc),
261 GST_APP_STREAM_TYPE_STREAM);
262
263 /* configure the appsrc, we will push data into the appsrc from the
264 * mainloop. */
265 g_signal_connect (gst_appsrc, "need-data", G_CALLBACK (feed_data), NULL);
266}
267
268/* Init libplayback: Grant access rights to
269 play audio while the phone is in silent mode */
270void maemo_init_libplayback(void)
271{
272 DBusConnection *session_bus_raw = (DBusConnection*)osso_get_dbus_connection(maemo_osso_ctx);
273
274 playback = pb_playback_new_2(session_bus_raw,
275 PB_CLASS_MEDIA,
276 PB_FLAG_AUDIO,
277 PB_STATE_STOP,
278 playback_state_req_handler,
279 NULL);
280
281 pb_playback_set_stream(playback, "Playback Stream");
282}
283
284/**
285 * Gets called by the policy framework if an important
286 * event arrives: Incoming calls etc.
287 */
288void maemo_tell_rockbox_to_stop_audio(void)
289{
290 sim_enter_irq_handler();
291 queue_broadcast(SYS_CALL_INCOMING, 0);
292 sim_exit_irq_handler();
293
294 osso_system_note_infoprint(maemo_osso_ctx, "Stopping rockbox playback", NULL);
295}
296
297void playback_state_req_handler(pb_playback_t *pb,
298 enum pb_state_e req_state,
299 pb_req_t *ext_req,
300 void *data)
301{
302 (void)pb;
303 (void)ext_req;
304 (void)data;
305
306 DEBUGF("External state change request: state: %s, data: %p\n",
307 pb_state_to_string(req_state), data);
308
309 if (req_state == PB_STATE_STOP && playback_granted)
310 {
311 DEBUGF("Stopping playback, might be an incoming call\n");
312
313 playback_granted = false;
314 maemo_tell_rockbox_to_stop_audio();
315 }
316}
317
318/**
319 * Callback for our own state change request.
320 */
321void playback_state_req_callback(pb_playback_t *pb, enum pb_state_e granted_state, const char *reason, pb_req_t *req, void *data)
322{
323 (void)data;
324 (void)reason;
325
326 DEBUGF("State request callback: granted_state: %s, reason: %s\n",
327 pb_state_to_string(granted_state), reason);
328
329 /* We are allowed to play audio */
330 if (granted_state == PB_STATE_PLAY)
331 {
332 DEBUGF("Playback granted. Start playing...\n");
333 playback_granted = true;
334 if (!inside_feed_data)
335 gst_element_set_state (GST_ELEMENT(gst_pipeline), GST_STATE_PLAYING);
336 } else
337 {
338 DEBUGF("Can't start playing. Throwing away play request\n");
339
340 playback_granted = false;
341 maemo_tell_rockbox_to_stop_audio();
342 }
343
344 pb_playback_req_completed(pb, req);
345}
346
347void pcm_play_dma_init(void)
348{
349 maemo_init_libplayback();
350
351 GMainContext *ctx = g_main_loop_get_context(maemo_main_loop);
352 pcm_loop = g_main_loop_new (ctx, true);
353
354 gst_init (NULL, NULL);
355
356 gst_pipeline = gst_pipeline_new ("rockbox");
357
358 gst_appsrc = gst_element_factory_make ("appsrc", NULL);
359 gst_volume = gst_element_factory_make ("volume", NULL);
360 gst_pulsesink = gst_element_factory_make ("pulsesink", NULL);
361
362 /* Connect elements */
363 gst_bin_add_many (GST_BIN (gst_pipeline),
364 gst_appsrc, gst_volume, gst_pulsesink, NULL);
365 gst_element_link_many (gst_appsrc, gst_volume, gst_pulsesink, NULL);
366
367 /* Connect to gstreamer bus of the pipeline */
368 gst_bus = gst_pipeline_get_bus (GST_PIPELINE (gst_pipeline));
369 bus_watch_id = gst_bus_add_watch (gst_bus, (GstBusFunc) gst_bus_message, NULL);
370
371 maemo_configure_appsrc();
372}
373
374void pcm_shutdown_gstreamer(void)
375{
376 /* Try to stop playing */
377 gst_element_set_state (GST_ELEMENT(gst_pipeline), GST_STATE_NULL);
378
379 /* Make sure we are really stopped. This should return almost instantly,
380 so we wait up to ten seconds and just continue otherwise */
381 gst_element_get_state (GST_ELEMENT(gst_pipeline), NULL, NULL, GST_SECOND * 10);
382
383 g_source_remove (bus_watch_id);
384 g_object_unref(gst_bus);
385 gst_bus = NULL;
386
387 gst_object_unref (gst_pipeline);
388 gst_pipeline = NULL;
389
390 /* Shutdown libplayback and gstreamer */
391 pb_playback_destroy (playback);
392 gst_deinit();
393
394 g_main_loop_quit(pcm_loop);
395 g_main_loop_unref (pcm_loop);
396}
397
398void pcm_postinit(void)
399{
400}
401
402void pcm_set_mixer_volume(int volume)
403{
404 /* gstreamer volume range is from 0.00 to 1.00 */
405 gdouble gst_vol = (gdouble)(volume - VOLUME_MIN) / (gdouble)VOLUME_RANGE;
406
407 g_object_set (G_OBJECT(gst_volume), "volume", gst_vol, NULL);
408}
409
410
411#ifdef HAVE_RECORDING
412void pcm_rec_lock(void)
413{
414}
415
416void pcm_rec_unlock(void)
417{
418}
419
420void pcm_rec_dma_init(void)
421{
422}
423
424void pcm_rec_dma_close(void)
425{
426}
427
428void pcm_rec_dma_start(void *start, size_t size)
429{
430 (void)start;
431 (void)size;
432}
433
434void pcm_rec_dma_stop(void)
435{
436}
437
438const void * pcm_rec_dma_get_peak_buffer(void)
439{
440 return NULL;
441}
442
443void audiohw_set_recvol(int left, int right, int type)
444{
445 (void)left;
446 (void)right;
447 (void)type;
448}
449
450#ifdef HAVE_SPDIF_IN
451unsigned long spdif_measure_frequency(void)
452{
453 return 0;
454}
455#endif
456
457#endif /* HAVE_RECORDING */
458
459#endif /* CONFIG_CODEC == SWCODEC */
diff --git a/firmware/target/hosted/sdl/app/button-application.c b/firmware/target/hosted/sdl/app/button-application.c
index 2ad09dc373..72f4a1770d 100644
--- a/firmware/target/hosted/sdl/app/button-application.c
+++ b/firmware/target/hosted/sdl/app/button-application.c
@@ -30,6 +30,9 @@ int key_to_button(int keyboard_key)
30 int new_btn = BUTTON_NONE; 30 int new_btn = BUTTON_NONE;
31 switch (keyboard_key) 31 switch (keyboard_key)
32 { 32 {
33#if (CONFIG_PLATFORM & PLATFORM_MAEMO4)
34 case SDLK_ESCAPE:
35#endif
33 case SDLK_KP7: 36 case SDLK_KP7:
34 new_btn = BUTTON_TOPLEFT; 37 new_btn = BUTTON_TOPLEFT;
35 break; 38 break;
@@ -37,6 +40,9 @@ int key_to_button(int keyboard_key)
37 case SDLK_UP: 40 case SDLK_UP:
38 new_btn = BUTTON_TOPMIDDLE; 41 new_btn = BUTTON_TOPMIDDLE;
39 break; 42 break;
43#if (CONFIG_PLATFORM & PLATFORM_MAEMO4)
44 case SDLK_F7:
45#endif
40 case SDLK_KP9: 46 case SDLK_KP9:
41 new_btn = BUTTON_TOPRIGHT; 47 new_btn = BUTTON_TOPRIGHT;
42 break; 48 break;
@@ -44,6 +50,10 @@ int key_to_button(int keyboard_key)
44 case SDLK_LEFT: 50 case SDLK_LEFT:
45 new_btn = BUTTON_MIDLEFT; 51 new_btn = BUTTON_MIDLEFT;
46 break; 52 break;
53#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
54 case SDLK_RETURN:
55 case SDLK_KP_ENTER:
56#endif
47 case SDLK_KP5: 57 case SDLK_KP5:
48 new_btn = BUTTON_CENTER; 58 new_btn = BUTTON_CENTER;
49 break; 59 break;
@@ -51,6 +61,9 @@ int key_to_button(int keyboard_key)
51 case SDLK_RIGHT: 61 case SDLK_RIGHT:
52 new_btn = BUTTON_MIDRIGHT; 62 new_btn = BUTTON_MIDRIGHT;
53 break; 63 break;
64#if (CONFIG_PLATFORM & PLATFORM_MAEMO4)
65 case SDLK_F6:
66#endif
54 case SDLK_KP1: 67 case SDLK_KP1:
55 new_btn = BUTTON_BOTTOMLEFT; 68 new_btn = BUTTON_BOTTOMLEFT;
56 break; 69 break;
@@ -58,6 +71,9 @@ int key_to_button(int keyboard_key)
58 case SDLK_DOWN: 71 case SDLK_DOWN:
59 new_btn = BUTTON_BOTTOMMIDDLE; 72 new_btn = BUTTON_BOTTOMMIDDLE;
60 break; 73 break;
74#if (CONFIG_PLATFORM & PLATFORM_MAEMO4)
75 case SDLK_F8:
76#endif
61 case SDLK_KP3: 77 case SDLK_KP3:
62 new_btn = BUTTON_BOTTOMRIGHT; 78 new_btn = BUTTON_BOTTOMRIGHT;
63 break; 79 break;
diff --git a/firmware/target/hosted/sdl/button-sdl.c b/firmware/target/hosted/sdl/button-sdl.c
index 3321a01bc6..25dad09341 100644
--- a/firmware/target/hosted/sdl/button-sdl.c
+++ b/firmware/target/hosted/sdl/button-sdl.c
@@ -67,6 +67,8 @@ struct event_queue button_queue;
67 67
68static int btn = 0; /* Hopefully keeps track of currently pressed keys... */ 68static int btn = 0; /* Hopefully keeps track of currently pressed keys... */
69 69
70int sdl_app_has_input_focus = 1;
71
70#ifdef HAS_BUTTON_HOLD 72#ifdef HAS_BUTTON_HOLD
71bool hold_button_state = false; 73bool hold_button_state = false;
72bool button_hold(void) { 74bool button_hold(void) {
@@ -209,11 +211,34 @@ static void mouse_event(SDL_MouseButtonEvent *event, bool button_up)
209 211
210static bool event_handler(SDL_Event *event) 212static bool event_handler(SDL_Event *event)
211{ 213{
214 SDLKey ev_key;
215
212 switch(event->type) 216 switch(event->type)
213 { 217 {
218 case SDL_ACTIVEEVENT:
219 if (event->active.state & SDL_APPINPUTFOCUS)
220 {
221 if (event->active.gain == 1)
222 sdl_app_has_input_focus = 1;
223 else
224 sdl_app_has_input_focus = 0;
225 }
226 break;
214 case SDL_KEYDOWN: 227 case SDL_KEYDOWN:
215 case SDL_KEYUP: 228 case SDL_KEYUP:
216 button_event(event->key.keysym.sym, event->type == SDL_KEYDOWN); 229 ev_key = event->key.keysym.sym;
230#if (CONFIG_PLATFORM & PLATFORM_MAEMO5)
231 /* N900 with shared up/down cursor mapping. Seen on the German,
232 Finnish, Italian, French and Russian version. Probably more. */
233 if (event->key.keysym.mod & KMOD_MODE)
234 {
235 if (ev_key == SDLK_LEFT)
236 ev_key = SDLK_UP;
237 else if (ev_key == SDLK_RIGHT)
238 ev_key = SDLK_DOWN;
239 }
240#endif
241 button_event(ev_key, event->type == SDL_KEYDOWN);
217 break; 242 break;
218#ifdef HAVE_TOUCHSCREEN 243#ifdef HAVE_TOUCHSCREEN
219 case SDL_MOUSEMOTION: 244 case SDL_MOUSEMOTION:
diff --git a/firmware/target/hosted/sdl/button-sdl.h b/firmware/target/hosted/sdl/button-sdl.h
index e6fcb9ea83..6b7f632eaf 100644
--- a/firmware/target/hosted/sdl/button-sdl.h
+++ b/firmware/target/hosted/sdl/button-sdl.h
@@ -26,6 +26,8 @@
26#include <stdbool.h> 26#include <stdbool.h>
27#include "config.h" 27#include "config.h"
28 28
29extern int sdl_app_has_input_focus;
30
29bool button_hold(void); 31bool button_hold(void);
30#undef button_init_device 32#undef button_init_device
31void button_init_device(void); 33void button_init_device(void);
diff --git a/firmware/target/hosted/sdl/lcd-bitmap.c b/firmware/target/hosted/sdl/lcd-bitmap.c
index 7058b26e8c..4c296924af 100644
--- a/firmware/target/hosted/sdl/lcd-bitmap.c
+++ b/firmware/target/hosted/sdl/lcd-bitmap.c
@@ -22,8 +22,12 @@
22#include "debug.h" 22#include "debug.h"
23#include "sim-ui-defines.h" 23#include "sim-ui-defines.h"
24#include "system.h" 24#include "system.h"
25#include "button-sdl.h"
25#include "lcd-sdl.h" 26#include "lcd-sdl.h"
26#include "screendump.h" 27#include "screendump.h"
28#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
29#include "maemo-thread.h"
30#endif
27 31
28SDL_Surface* lcd_surface; 32SDL_Surface* lcd_surface;
29 33
@@ -123,6 +127,16 @@ void lcd_update(void)
123 127
124void lcd_update_rect(int x_start, int y_start, int width, int height) 128void lcd_update_rect(int x_start, int y_start, int width, int height)
125{ 129{
130#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
131 /* Don't update display if not shown */
132 if (!maemo_display_on)
133 return;
134
135 /* Don't update if we don't have the input focus */
136 if (!sdl_app_has_input_focus)
137 return;
138#endif
139
126 sdl_update_rect(lcd_surface, x_start, y_start, width, height, 140 sdl_update_rect(lcd_surface, x_start, y_start, width, height,
127 LCD_WIDTH, LCD_HEIGHT, get_lcd_pixel); 141 LCD_WIDTH, LCD_HEIGHT, get_lcd_pixel);
128 sdl_gui_update(lcd_surface, x_start, y_start, width, 142 sdl_gui_update(lcd_surface, x_start, y_start, width,
diff --git a/firmware/target/hosted/sdl/system-sdl.c b/firmware/target/hosted/sdl/system-sdl.c
index b900d38b43..9ea25c1014 100644
--- a/firmware/target/hosted/sdl/system-sdl.c
+++ b/firmware/target/hosted/sdl/system-sdl.c
@@ -40,6 +40,13 @@
40#include "panic.h" 40#include "panic.h"
41#include "debug.h" 41#include "debug.h"
42 42
43#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
44#include <glib.h>
45#include <glib-object.h>
46#include "maemo-thread.h"
47
48#endif
49
43SDL_Surface *gui_surface; 50SDL_Surface *gui_surface;
44 51
45bool background = true; /* use backgrounds by default */ 52bool background = true; /* use backgrounds by default */
@@ -82,9 +89,13 @@ static int sdl_event_thread(void * param)
82{ 89{
83 SDL_InitSubSystem(SDL_INIT_VIDEO); 90 SDL_InitSubSystem(SDL_INIT_VIDEO);
84 91
92#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
93 SDL_sem *wait_for_maemo_startup;
94#endif
85 SDL_Surface *picture_surface = NULL; 95 SDL_Surface *picture_surface = NULL;
86 int width, height; 96 int width, height;
87 int depth; 97 int depth;
98 Uint32 flags;
88 99
89 /* Try and load the background image. If it fails go without */ 100 /* Try and load the background image. If it fails go without */
90 if (background) { 101 if (background) {
@@ -121,10 +132,21 @@ static int sdl_event_thread(void * param)
121 if (depth < 8) 132 if (depth < 8)
122 depth = 16; 133 depth = 16;
123 134
124 if ((gui_surface = SDL_SetVideoMode(width * display_zoom, height * display_zoom, depth, SDL_HWSURFACE|SDL_DOUBLEBUF)) == NULL) { 135 flags = SDL_HWSURFACE|SDL_DOUBLEBUF;
136#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
137 /* Fullscreen mode for maemo app */
138 flags |= SDL_FULLSCREEN;
139#endif
140
141 if ((gui_surface = SDL_SetVideoMode(width * display_zoom, height * display_zoom, depth, flags)) == NULL) {
125 panicf("%s", SDL_GetError()); 142 panicf("%s", SDL_GetError());
126 } 143 }
127 144
145#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
146 /* Hide mouse cursor on real touchscreen device */
147 SDL_ShowCursor(SDL_DISABLE);
148#endif
149
128 SDL_WM_SetCaption(UI_TITLE, NULL); 150 SDL_WM_SetCaption(UI_TITLE, NULL);
129 151
130 if (background && picture_surface != NULL) 152 if (background && picture_surface != NULL)
@@ -133,10 +155,30 @@ static int sdl_event_thread(void * param)
133 /* let system_init proceed */ 155 /* let system_init proceed */
134 SDL_SemPost((SDL_sem *)param); 156 SDL_SemPost((SDL_sem *)param);
135 157
158#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
159 /* Start maemo thread: Listen to display on/off events and battery monitoring */
160 wait_for_maemo_startup = SDL_CreateSemaphore(0); /* 0-count so it blocks */
161 SDL_Thread *maemo_thread = SDL_CreateThread(maemo_thread_func, wait_for_maemo_startup);
162#endif
163
136 /* 164 /*
137 * finally enter the button loop */ 165 * finally enter the button loop */
138 gui_message_loop(); 166 gui_message_loop();
139 167
168#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
169 /* Ensure maemo thread is up and running */
170 SDL_SemWait(wait_for_maemo_startup);
171 SDL_DestroySemaphore(wait_for_maemo_startup);
172
173#if (CONFIG_PLATFORM & PLATFORM_MAEMO5)
174 pcm_shutdown_gstreamer();
175#endif
176
177 g_main_loop_quit (maemo_main_loop);
178 g_main_loop_unref(maemo_main_loop);
179 SDL_WaitThread(maemo_thread, NULL);
180#endif
181
140 if(picture_surface) 182 if(picture_surface)
141 SDL_FreeSurface(picture_surface); 183 SDL_FreeSurface(picture_surface);
142 184
@@ -161,6 +203,12 @@ void system_init(void)
161{ 203{
162 SDL_sem *s; 204 SDL_sem *s;
163 205
206#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
207 /* Make glib thread safe */
208 g_thread_init(NULL);
209 g_type_init();
210#endif
211
164 if (SDL_Init(SDL_INIT_TIMER)) 212 if (SDL_Init(SDL_INIT_TIMER))
165 panicf("%s", SDL_GetError()); 213 panicf("%s", SDL_GetError());
166 214
diff --git a/tools/configure b/tools/configure
index aa37ef7d71..26425ffe10 100755
--- a/tools/configure
+++ b/tools/configure
@@ -51,7 +51,7 @@ prefixtools () {
51} 51}
52 52
53app_get_platform() { 53app_get_platform() {
54 echo "Select your platform: (S)DL, (A)ndroid (default: Android)" 54 echo "Select your platform: (S)DL, (A)ndroid, (M)aemo (default: Android)"
55 if [ -z "$ARG_PLATFORM" ]; then 55 if [ -z "$ARG_PLATFORM" ]; then
56 choice=`input` 56 choice=`input`
57 else 57 else
@@ -60,6 +60,7 @@ app_get_platform() {
60 60
61 case $choice in 61 case $choice in
62 s|S*) app_platform="sdl" ;; 62 s|S*) app_platform="sdl" ;;
63 m|M*) app_platform="maemo" ;;
63 *|a|A*) app_platform="android" ;; 64 *|a|A*) app_platform="android" ;;
64 esac 65 esac
65 66
@@ -128,6 +129,31 @@ app_get_platform() {
128 libdir="/data/data/org.rockbox/app_rockbox" 129 libdir="/data/data/org.rockbox/app_rockbox"
129 output="librockbox.so" 130 output="librockbox.so"
130 bootoutput="librockbox.so" 131 bootoutput="librockbox.so"
132 elif [ "$app_platform" = "maemo" ]; then
133 if [ -z "$ARG_PREFIX" ]; then
134 # Rockbox is in /opt as there is enough free space for it on the N900.
135 sharedir="/opt/rockbox/share/rockbox"
136 bindir="/opt/rockbox/bin"
137 libdir="/opt/rockbox/lib"
138 else
139 if [ -d "$ARG_PREFIX" ]; then
140 if [ -z `echo $ARG_PREFIX | grep "^/"` ]; then
141 ARG_PREFIX=`realpath $ARG_PREFIX`
142 if [ "0" != "$?" ]; then
143 echo "ERROR: Could not get prefix path (is realpath installed?)."
144 exit
145 fi
146 fi
147 sharedir="$ARG_PREFIX/share/rockbox"
148 bindir="$ARG_PREFIX/bin"
149 libdir="$ARG_PREFIX/lib"
150 else
151 echo "ERROR: PREFIX does not exist"
152 exit
153 fi
154 fi
155 output="rockbox"
156 bootoutput="rockbox"
131 fi 157 fi
132} 158}
133 159
@@ -189,6 +215,9 @@ findsdl(){
189appcc () { 215appcc () {
190 if [ "$1" = "sdl" ]; then 216 if [ "$1" = "sdl" ]; then
191 simcc "sdl-app" 217 simcc "sdl-app"
218 elif [ "$1" = "maemo" ]; then
219 app_type="sdl-app"
220 maemocc
192 elif [ "$1" = "android" ]; then 221 elif [ "$1" = "android" ]; then
193 app_type=$1 222 app_type=$1
194 androidcc 223 androidcc
@@ -477,6 +506,68 @@ mipselcc () {
477 gccchoice="4.1.2" 506 gccchoice="4.1.2"
478} 507}
479 508
509maemocc () {
510 # Scratchbox sets up "gcc" based on the active target
511 prefixtools ""
512
513 GCCOPTS=`echo $CCOPTS | sed -e s/-ffreestanding// -e s/-nostdlib// -e s/-Wundef//`
514 GCCOPTS="$GCCOPTS -fno-builtin -g -I\$(SIMDIR)"
515 GCCOPTIMIZE=''
516 LDOPTS="-lm -ldl $LDOPTS"
517 GLOBAL_LDOPTS="$GLOBAL_LDOPTS -Wl,-z,defs"
518 SHARED_FLAG="-shared"
519 endian="little"
520
521 is_n900=0
522 # Determine maemo version
523 if pkg-config --atleast-version=5 maemo-version; then
524 extradefines="$extradefines -DMAEMO5"
525 echo "Found N900 maemo version"
526 is_n900=1
527 elif pkg-config --atleast-version=4 maemo-version; then
528 extradefines="$extradefines -DMAEMO4"
529 echo "Found N8xx maemo version"
530 else
531 echo "Unable to determine maemo version. Is the maemo-version-dev package installed?"
532 exit 1
533 fi
534
535 # SDL
536 GCCOPTS="$GCCOPTS `pkg-config --cflags sdl`"
537 LDOPTS="$LDOPTS `pkg-config --libs sdl`"
538
539 # glib and libosso support
540 GCCOPTS="$GCCOPTS `pkg-config --cflags libosso glib-2.0 gthread-2.0`"
541 LDOPTS="$LDOPTS `pkg-config --libs libosso glib-2.0 gthread-2.0`"
542
543 # libhal support: Battery monitoring
544 GCCOPTS="$GCCOPTS `pkg-config --cflags hal`"
545 LDOPTS="$LDOPTS `pkg-config --libs hal`"
546
547 GCCOPTS="$GCCOPTS -O2 -fno-strict-aliasing"
548 if [ $is_n900 -eq 1 ]; then
549 # gstreamer support: Audio output.
550 GCCOPTS="$GCCOPTS `pkg-config --cflags gstreamer-base-0.10 gstreamer-plugins-base-0.10 gstreamer-app-0.10`"
551 LDOPTS="$LDOPTS `pkg-config --libs gstreamer-base-0.10 gstreamer-plugins-base-0.10 gstreamer-app-0.10`"
552
553 # N900 specific: libplayback support
554 GCCOPTS="$GCCOPTS `pkg-config --cflags libplayback-1`"
555 LDOPTS="$LDOPTS `pkg-config --libs libplayback-1`"
556
557 # N900 specific: Enable ARMv7 NEON support
558 if sb-conf current |grep ARMEL; then
559 GCCOPTS="$GCCOPTS -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp"
560 extradefines="$extradefines -DMAEMO_ARM_BUILD"
561 fi
562 else
563 # N8xx specific: Enable armv5te instructions
564 if sb-conf current |grep ARMEL; then
565 GCCOPTS="$GCCOPTS -mcpu=arm1136jf-s -mfloat-abi=softfp -mfpu=vfp"
566 extradefines="$extradefines -DMAEMO_ARM_BUILD"
567 fi
568 fi
569}
570
480androidcc () { 571androidcc () {
481 buildhost=`uname | tr [:upper:] [:lower:]` 572 buildhost=`uname | tr [:upper:] [:lower:]`
482 gccchoice="4.4.3" 573 gccchoice="4.4.3"
@@ -3239,9 +3330,14 @@ EOF
3239 3330
3240if test -n "$t_cpu"; then 3331if test -n "$t_cpu"; then
3241 TARGET_INC="-I\$(FIRMDIR)/target/$t_cpu/$t_manufacturer/$t_model" 3332 TARGET_INC="-I\$(FIRMDIR)/target/$t_cpu/$t_manufacturer/$t_model"
3242 if [ "$simulator" = "yes" ]; then # a few more includes for the sim target tree 3333
3243 TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted/sdl/" 3334 if [ "$t_cpu" = "hosted" ] && [ "$t_manufacturer" = "maemo" ]; then
3244 TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted/" 3335 # Maemo needs the SDL port, too
3336 TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted/sdl/app"
3337 TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted/sdl"
3338 elif [ "$simulator" = "yes" ]; then # a few more includes for the sim target tree
3339 TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted/sdl"
3340 TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted"
3245 fi 3341 fi
3246 TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/$t_cpu/$t_manufacturer" 3342 TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/$t_cpu/$t_manufacturer"
3247 TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/$t_cpu" 3343 TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/$t_cpu"
@@ -3282,6 +3378,8 @@ if [ "$app_platform" = "sdl" ]; then
3282 cmdline="$cmdline--platform=S " 3378 cmdline="$cmdline--platform=S "
3283elif [ "$app_platform" = "android" ]; then 3379elif [ "$app_platform" = "android" ]; then
3284 cmdline="$cmdline--platform=A " 3380 cmdline="$cmdline--platform=A "
3381elif [ "$app_platform" = "maemo" ]; then
3382 cmdline="$cmdline--platform=M "
3285fi 3383fi
3286if [ "$modelname" = "application" ]; then 3384if [ "$modelname" = "application" ]; then
3287 cmdline="$cmdline--lcdwidth=$ARG_LCDWIDTH --lcdheight=$ARG_LCDHEIGHT " 3385 cmdline="$cmdline--lcdwidth=$ARG_LCDWIDTH --lcdheight=$ARG_LCDHEIGHT "
diff --git a/uisimulator/common/SOURCES b/uisimulator/common/SOURCES
index fd256c56a4..2c921ed7ad 100644
--- a/uisimulator/common/SOURCES
+++ b/uisimulator/common/SOURCES
@@ -12,5 +12,7 @@ backlight-sim.c
12io.c 12io.c
13sim_tasks.c 13sim_tasks.c
14/* this is still needed for application since it has some stubs */ 14/* this is still needed for application since it has some stubs */
15#if !(CONFIG_PLATFORM & PLATFORM_MAEMO)
15powermgmt-sim.c 16powermgmt-sim.c
17#endif
16stubs.c 18stubs.c