diff options
-rw-r--r-- | Makefile.android | 2 | ||||
-rw-r--r-- | android/main-common.c | 533 | ||||
-rw-r--r-- | android/main-common.h | 43 | ||||
-rw-r--r-- | android/main-ui.c | 465 | ||||
-rw-r--r-- | android/main.c | 477 |
5 files changed, 582 insertions, 938 deletions
diff --git a/Makefile.android b/Makefile.android index 811b58a..5faab57 100644 --- a/Makefile.android +++ b/Makefile.android @@ -879,6 +879,7 @@ VL_SOURCES := framebuffer.c \ android/looper-qemu.c \ android/protocol/ui-commands-qemu.c \ android/protocol/core-commands-qemu.c \ + android/main-common.c \ android/main.c \ # Add common system libraries @@ -1212,6 +1213,7 @@ VL_SOURCES := framebuffer.c \ android/looper-generic.c \ android/snapshot.c \ android/core-connection.c \ + android/main-common.c \ android/main-ui.c \ qemu-timer-ui.c \ vl-android-ui.c \ diff --git a/android/main-common.c b/android/main-common.c new file mode 100644 index 0000000..189f10c --- /dev/null +++ b/android/main-common.c @@ -0,0 +1,533 @@ +/* Copyright (C) 2011 The Android Open Source Project +** +** This software is licensed under the terms of the GNU General Public +** License version 2, as published by the Free Software Foundation, and +** may be copied, distributed, and modified under those terms. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +*/ +#include <signal.h> +#include <unistd.h> +#include <string.h> +#include <sys/time.h> +#include <errno.h> +#include <fcntl.h> +#ifdef _WIN32 +#include <process.h> +#endif + +#include <SDL.h> +#include <SDL_syswm.h> + +#include "console.h" + +#include "android/utils/debug.h" +#include "android/utils/path.h" +#include "android/utils/bufprint.h" +#include "android/main-common.h" +#include "android/globals.h" +#include "android/resource.h" +#include "android/user-config.h" +#include "android/qemulator.h" +#include "android/display.h" +#include "android/skin/image.h" +#include "android/skin/trackball.h" +#include "android/skin/keyboard.h" +#include "android/skin/file.h" +#include "android/skin/window.h" + + + +/***********************************************************************/ +/***********************************************************************/ +/***** *****/ +/***** U T I L I T Y R O U T I N E S *****/ +/***** *****/ +/***********************************************************************/ +/***********************************************************************/ + +#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0) + +/*** CONFIGURATION + ***/ + +static AUserConfig* userConfig; + +void +emulator_config_init( void ) +{ + userConfig = auserConfig_new( android_avdInfo ); +} + +/* only call this function on normal exits, so that ^C doesn't save the configuration */ +void +emulator_config_done( void ) +{ + int win_x, win_y; + + if (!userConfig) { + D("no user configuration?"); + return; + } + + SDL_WM_GetPos( &win_x, &win_y ); + auserConfig_setWindowPos(userConfig, win_x, win_y); + auserConfig_save(userConfig); +} + +void +emulator_config_get_window_pos( int *window_x, int *window_y ) +{ + *window_x = *window_y = 10; + + if (userConfig) + auserConfig_getWindowPos(userConfig, window_x, window_y); +} + +unsigned convertBytesToMB( uint64_t size ) +{ + if (size == 0) + return 0; + + size = (size + ONE_MB-1) >> 20; + if (size > UINT_MAX) + size = UINT_MAX; + + return (unsigned) size; +} + +uint64_t convertMBToBytes( unsigned megaBytes ) +{ + return ((uint64_t)megaBytes << 20); +} + + +/***********************************************************************/ +/***********************************************************************/ +/***** *****/ +/***** K E Y S E T R O U T I N E S *****/ +/***** *****/ +/***********************************************************************/ +/***********************************************************************/ + +#define KEYSET_FILE "default.keyset" + +SkinKeyset* android_keyset = NULL; + +static int +load_keyset(const char* path) +{ + if (path_can_read(path)) { + AConfig* root = aconfig_node("",""); + if (!aconfig_load_file(root, path)) { + android_keyset = skin_keyset_new(root); + if (android_keyset != NULL) { + D( "keyset loaded from: %s", path); + return 0; + } + } + } + return -1; +} + +void +parse_keyset(const char* keyset, AndroidOptions* opts) +{ + char kname[MAX_PATH]; + char temp[MAX_PATH]; + char* p; + char* end; + + /* append .keyset suffix if needed */ + if (strchr(keyset, '.') == NULL) { + p = kname; + end = p + sizeof(kname); + p = bufprint(p, end, "%s.keyset", keyset); + if (p >= end) { + derror( "keyset name too long: '%s'\n", keyset); + exit(1); + } + keyset = kname; + } + + /* look for a the keyset file */ + p = temp; + end = p + sizeof(temp); + p = bufprint_config_file(p, end, keyset); + if (p < end && load_keyset(temp) == 0) + return; + + p = temp; + p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset); + if (p < end && load_keyset(temp) == 0) + return; + + p = temp; + p = bufprint_app_dir(p, end); + p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset); + if (p < end && load_keyset(temp) == 0) + return; + + return; +} + +void +write_default_keyset( void ) +{ + char path[MAX_PATH]; + + bufprint_config_file( path, path+sizeof(path), KEYSET_FILE ); + + /* only write if there is no file here */ + if ( !path_exists(path) ) { + int fd = open( path, O_WRONLY | O_CREAT, 0666 ); + int ret; + const char* ks = skin_keyset_get_default(); + + + D( "writing default keyset file to %s", path ); + + if (fd < 0) { + D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) ); + return; + } + CHECKED(ret, write(fd, ks, strlen(ks))); + close(fd); + } +} + + + +/***********************************************************************/ +/***********************************************************************/ +/***** *****/ +/***** S D L S U P P O R T *****/ +/***** *****/ +/***********************************************************************/ +/***********************************************************************/ + +void *readpng(const unsigned char* base, size_t size, unsigned *_width, unsigned *_height); + +#ifdef CONFIG_DARWIN +# define ANDROID_ICON_PNG "android_icon_256.png" +#else +# define ANDROID_ICON_PNG "android_icon_16.png" +#endif + +static void +sdl_set_window_icon( void ) +{ + static int window_icon_set; + + if (!window_icon_set) + { +#ifdef _WIN32 + HANDLE handle = GetModuleHandle( NULL ); + HICON icon = LoadIcon( handle, MAKEINTRESOURCE(1) ); + SDL_SysWMinfo wminfo; + + SDL_GetWMInfo(&wminfo); + + SetClassLong( wminfo.window, GCL_HICON, (LONG)icon ); +#else /* !_WIN32 */ + unsigned icon_w, icon_h; + size_t icon_bytes; + const unsigned char* icon_data; + void* icon_pixels; + + window_icon_set = 1; + + icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes ); + if ( !icon_data ) + return; + + icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h ); + if ( !icon_pixels ) + return; + + /* the data is loaded into memory as RGBA bytes by libpng. we want to manage + * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending + * on our CPU endianess + */ + { + unsigned* d = icon_pixels; + unsigned* d_end = d + icon_w*icon_h; + + for ( ; d < d_end; d++ ) { + unsigned pix = d[0]; +#if HOST_WORDS_BIGENDIAN + /* R,G,B,A read as RGBA => ARGB */ + pix = ((pix >> 8) & 0xffffff) | (pix << 24); +#else + /* R,G,B,A read as ABGR => ARGB */ + pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16); +#endif + d[0] = pix; + } + } + + SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h ); + if (icon != NULL) { + SDL_WM_SetIcon(icon, NULL); + SDL_FreeSurface(icon); + free( icon_pixels ); + } +#endif /* !_WIN32 */ + } +} + +/***********************************************************************/ +/***********************************************************************/ +/***** *****/ +/***** S K I N S U P P O R T *****/ +/***** *****/ +/***********************************************************************/ +/***********************************************************************/ + +const char* skin_network_speed = NULL; +const char* skin_network_delay = NULL; + + +static void sdl_at_exit(void) +{ + emulator_config_done(); + qemulator_done(qemulator_get()); + SDL_Quit(); +} + + +void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) +{ + QEmulator* emulator = qemulator_get(); + SkinDisplay* disp = skin_layout_get_display(emulator->layout); + int width, height; + char buf[128]; + + if (disp->rotation & 1) { + width = disp->rect.size.h; + height = disp->rect.size.w; + } else { + width = disp->rect.size.w; + height = disp->rect.size.h; + } + + snprintf(buf, sizeof buf, "width=%d,height=%d", width, height); + android_display_init(ds, qframebuffer_fifo_get()); +} + +/* list of skin aliases */ +static const struct { + const char* name; + const char* alias; +} skin_aliases[] = { + { "QVGA-L", "320x240" }, + { "QVGA-P", "240x320" }, + { "HVGA-L", "480x320" }, + { "HVGA-P", "320x480" }, + { "QVGA", "320x240" }, + { "HVGA", "320x480" }, + { NULL, NULL } +}; + +/* this is used by hw/events_device.c to send the charmap name to the system */ +const char* android_skin_keycharmap = NULL; + +void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts) +{ + char tmp[1024]; + AConfig* root; + AConfig* n; + int win_x, win_y, flags; + + signal(SIGINT, SIG_DFL); +#ifndef _WIN32 + signal(SIGQUIT, SIG_DFL); +#endif + + /* we're not a game, so allow the screensaver to run */ + putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1"); + + flags = SDL_INIT_NOPARACHUTE; + if (!opts->no_window) + flags |= SDL_INIT_VIDEO; + + if(SDL_Init(flags)){ + fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() ); + exit(1); + } + + if (!opts->no_window) { + SDL_EnableUNICODE(!opts->raw_keys); + SDL_EnableKeyRepeat(0,0); + + sdl_set_window_icon(); + } + else + { +#ifndef _WIN32 + /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be + * able to run the emulator in the background (e.g. "emulator &"). + * despite the fact that the emulator should not grab input or try to + * write to the output in normal cases, we're stopped on some systems + * (e.g. OS X) + */ + signal(SIGTTIN, SIG_IGN); + signal(SIGTTOU, SIG_IGN); +#endif + } + atexit(sdl_at_exit); + + root = aconfig_node("", ""); + + if(name) { + /* Support skin aliases like QVGA-H QVGA-P, etc... + But first we check if it's a directory that exist before applying + the alias */ + int checkAlias = 1; + + if (path != NULL) { + bufprint(tmp, tmp+sizeof(tmp), "%s/%s", path, name); + if (path_exists(tmp)) { + checkAlias = 0; + } else { + D("there is no '%s' skin in '%s'", name, path); + } + } + + if (checkAlias) { + int nn; + + for (nn = 0; ; nn++ ) { + const char* skin_name = skin_aliases[nn].name; + const char* skin_alias = skin_aliases[nn].alias; + + if ( !skin_name ) + break; + + if ( !strcasecmp( skin_name, name ) ) { + D("skin name '%s' aliased to '%s'", name, skin_alias); + name = skin_alias; + break; + } + } + } + + /* Magically support skins like "320x240" or "320x240x16" */ + if(isdigit(name[0])) { + char *x = strchr(name, 'x'); + if(x && isdigit(x[1])) { + int width = atoi(name); + int height = atoi(x+1); + int bpp = 16; + char* y = strchr(x+1, 'x'); + if (y && isdigit(y[1])) { + bpp = atoi(y+1); + } + sprintf(tmp,"display {\n width %d\n height %d\n bpp %d}\n", + width, height,bpp); + aconfig_load(root, strdup(tmp)); + path = ":"; + goto found_a_skin; + } + } + + if (path == NULL) { + derror("unknown skin name '%s'", name); + exit(1); + } + + sprintf(tmp, "%s/%s/layout", path, name); + D("trying to load skin file '%s'", tmp); + + if(aconfig_load_file(root, tmp) >= 0) { + sprintf(tmp, "%s/%s/", path, name); + path = tmp; + goto found_a_skin; + } else { + dwarning("could not load skin file '%s', using built-in one\n", + tmp); + } + } + + { + const unsigned char* layout_base; + size_t layout_size; + + name = "<builtin>"; + + layout_base = android_resource_find( "layout", &layout_size ); + if (layout_base != NULL) { + char* base = malloc( layout_size+1 ); + memcpy( base, layout_base, layout_size ); + base[layout_size] = 0; + + D("parsing built-in skin layout file (size=%d)", (int)layout_size); + aconfig_load(root, base); + path = ":"; + } else { + fprintf(stderr, "Couldn't load builtin skin\n"); + exit(1); + } + } + +found_a_skin: + emulator_config_get_window_pos(&win_x, &win_y); + + if ( qemulator_init(qemulator_get(), root, path, win_x, win_y, opts ) < 0 ) { + fprintf(stderr, "### Error: could not load emulator skin '%s'\n", name); + exit(1); + } + + android_skin_keycharmap = skin_keyboard_charmap_name(qemulator_get()->keyboard); + + /* the default network speed and latency can now be specified by the device skin */ + n = aconfig_find(root, "network"); + if (n != NULL) { + skin_network_speed = aconfig_str(n, "speed", 0); + skin_network_delay = aconfig_str(n, "delay", 0); + } + +#if 0 + /* create a trackball if needed */ + n = aconfig_find(root, "trackball"); + if (n != NULL) { + SkinTrackBallParameters params; + + params.x = aconfig_unsigned(n, "x", 0); + params.y = aconfig_unsigned(n, "y", 0); + params.diameter = aconfig_unsigned(n, "diameter", 20); + params.ring = aconfig_unsigned(n, "ring", 1); + + params.ball_color = aconfig_unsigned(n, "ball-color", 0xffe0e0e0); + params.dot_color = aconfig_unsigned(n, "dot-color", 0xff202020 ); + params.ring_color = aconfig_unsigned(n, "ring-color", 0xff000000 ); + + qemu_disp->trackball = skin_trackball_create( ¶ms ); + skin_trackball_refresh( qemu_disp->trackball ); + } +#endif + + /* add an onion overlay image if needed */ + if (opts->onion) { + SkinImage* onion = skin_image_find_simple( opts->onion ); + int alpha, rotate; + + if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) { + alpha = (256*alpha)/100; + } else + alpha = 128; + + if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) { + rotate &= 3; + } else + rotate = SKIN_ROTATION_0; + + qemulator_get()->onion = onion; + qemulator_get()->onion_alpha = alpha; + qemulator_get()->onion_rotation = rotate; + } +} + diff --git a/android/main-common.h b/android/main-common.h new file mode 100644 index 0000000..0adc4a2 --- /dev/null +++ b/android/main-common.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2011 The Android Open Source Project +** +** This software is licensed under the terms of the GNU General Public +** License version 2, as published by the Free Software Foundation, and +** may be copied, distributed, and modified under those terms. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +*/ +#ifndef ANDROID_MAIN_COMMON_H +#define ANDROID_MAIN_COMMON_H + +#include <stdint.h> +#include "android/cmdline-option.h" +#include "android/skin/keyset.h" + +/* Common routines used by both android/main.c and android/main-ui.c */ + +/** Emulator user configuration (e.g. last window position) + **/ + +void emulator_config_init( void ); +void emulator_config_done( void ); + +void emulator_config_get_window_pos( int *window_x, int *window_y ); + +#define ONE_MB (1024*1024) + +unsigned convertBytesToMB( uint64_t size ); +uint64_t convertMBToBytes( unsigned megaBytes ); + +extern SkinKeyset* android_keyset; +void parse_keyset(const char* keyset, AndroidOptions* opts); +void write_default_keyset( void ); + +extern const char* skin_network_speed; +extern const char* skin_network_delay; + +void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts); + +#endif /* ANDROID_MAIN_COMMON_H */ diff --git a/android/main-ui.c b/android/main-ui.c index 541d83b..fdd1d58 100644 --- a/android/main-ui.c +++ b/android/main-ui.c @@ -50,7 +50,7 @@ #include "android/utils/path.h" #include "android/utils/tempfile.h" -#include "android/cmdline-option.h" +#include "android/main-common.h" #include "android/help.h" #include "hw/goldfish_nand.h" @@ -111,387 +111,9 @@ char* core_ui_settings = ""; /* Emulator's core port. */ int android_base_port = 0; -/***********************************************************************/ -/***********************************************************************/ -/***** *****/ -/***** U T I L I T Y R O U T I N E S *****/ -/***** *****/ -/***********************************************************************/ -/***********************************************************************/ - -/*** CONFIGURATION - ***/ - -static AUserConfig* userConfig; - -void -emulator_config_init( void ) -{ - userConfig = auserConfig_new( android_avdInfo ); -} - -/* only call this function on normal exits, so that ^C doesn't save the configuration */ -void -emulator_config_done( void ) -{ - int win_x, win_y; - - if (!userConfig) { - D("no user configuration?"); - return; - } - - SDL_WM_GetPos( &win_x, &win_y ); - auserConfig_setWindowPos(userConfig, win_x, win_y); - auserConfig_save(userConfig); -} - -void *loadpng(const char *fn, unsigned *_width, unsigned *_height); -void *readpng(const unsigned char* base, size_t size, unsigned *_width, unsigned *_height); - -#ifdef CONFIG_DARWIN -# define ANDROID_ICON_PNG "android_icon_256.png" -#else -# define ANDROID_ICON_PNG "android_icon_16.png" -#endif - -static void -sdl_set_window_icon( void ) -{ - static int window_icon_set; - - if (!window_icon_set) - { -#ifdef _WIN32 - HANDLE handle = GetModuleHandle( NULL ); - HICON icon = LoadIcon( handle, MAKEINTRESOURCE(1) ); - SDL_SysWMinfo wminfo; - - SDL_GetWMInfo(&wminfo); - - SetClassLong( wminfo.window, GCL_HICON, (LONG)icon ); -#else /* !_WIN32 */ - unsigned icon_w, icon_h; - size_t icon_bytes; - const unsigned char* icon_data; - void* icon_pixels; - - window_icon_set = 1; - - icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes ); - if ( !icon_data ) - return; - - icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h ); - if ( !icon_pixels ) - return; - - /* the data is loaded into memory as RGBA bytes by libpng. we want to manage - * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending - * on our CPU endianess - */ - { - unsigned* d = icon_pixels; - unsigned* d_end = d + icon_w*icon_h; - - for ( ; d < d_end; d++ ) { - unsigned pix = d[0]; -#if HOST_WORDS_BIGENDIAN - /* R,G,B,A read as RGBA => ARGB */ - pix = ((pix >> 8) & 0xffffff) | (pix << 24); -#else - /* R,G,B,A read as ABGR => ARGB */ - pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16); -#endif - d[0] = pix; - } - } - - SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h ); - if (icon != NULL) { - SDL_WM_SetIcon(icon, NULL); - SDL_FreeSurface(icon); - free( icon_pixels ); - } -#endif /* !_WIN32 */ - } -} - -#define ONE_MB (1024*1024) - -unsigned convertBytesToMB( uint64_t size ) -{ - if (size == 0) - return 0; - - size = (size + ONE_MB-1) >> 20; - if (size > UINT_MAX) - size = UINT_MAX; - - return (unsigned) size; -} - -uint64_t convertMBToBytes( unsigned megaBytes ) -{ - return ((uint64_t)megaBytes << 20); -} - -/***********************************************************************/ -/***********************************************************************/ -/***** *****/ -/***** S K I N I M A G E S *****/ -/***** *****/ -/***********************************************************************/ -/***********************************************************************/ -static void sdl_at_exit(void) -{ - emulator_config_done(); - qemulator_done(qemulator_get()); - SDL_Quit(); -} - - -void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) -{ - QEmulator* emulator = qemulator_get(); - SkinDisplay* disp = skin_layout_get_display(emulator->layout); - int width, height; - char buf[128]; - - if (disp->rotation & 1) { - width = disp->rect.size.h; - height = disp->rect.size.w; - } else { - width = disp->rect.size.w; - height = disp->rect.size.h; - } - - snprintf(buf, sizeof buf, "width=%d,height=%d", width, height); - android_display_init(ds, qframebuffer_fifo_get()); -} - - -static const char* skin_network_speed = NULL; -static const char* skin_network_delay = NULL; - -/* list of skin aliases */ -static const struct { - const char* name; - const char* alias; -} skin_aliases[] = { - { "QVGA-L", "320x240" }, - { "QVGA-P", "240x320" }, - { "HVGA-L", "480x320" }, - { "HVGA-P", "320x480" }, - { "QVGA", "320x240" }, - { "HVGA", "320x480" }, - { NULL, NULL } -}; - /* this is used by hw/events_device.c to send the charmap name to the system */ -const char* android_skin_keycharmap = NULL; - -void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts) -{ - char tmp[1024]; - AConfig* root; - AConfig* n; - int win_x, win_y, flags; - - signal(SIGINT, SIG_DFL); -#ifndef _WIN32 - signal(SIGQUIT, SIG_DFL); -#endif - - /* we're not a game, so allow the screensaver to run */ - putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1"); +extern const char* android_skin_keycharmap; - flags = SDL_INIT_NOPARACHUTE; - if (!opts->no_window) - flags |= SDL_INIT_VIDEO; - - if(SDL_Init(flags)){ - fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() ); - exit(1); - } - - if (!opts->no_window) { - SDL_EnableUNICODE(!opts->raw_keys); - SDL_EnableKeyRepeat(0,0); - - sdl_set_window_icon(); - } - else - { -#ifndef _WIN32 - /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be - * able to run the emulator in the background (e.g. "emulator &"). - * despite the fact that the emulator should not grab input or try to - * write to the output in normal cases, we're stopped on some systems - * (e.g. OS X) - */ - signal(SIGTTIN, SIG_IGN); - signal(SIGTTOU, SIG_IGN); -#endif - } - atexit(sdl_at_exit); - - root = aconfig_node("", ""); - - if(name) { - /* Support skin aliases like QVGA-H QVGA-P, etc... - But first we check if it's a directory that exist before applying - the alias */ - int checkAlias = 1; - - if (path != NULL) { - bufprint(tmp, tmp+sizeof(tmp), "%s/%s", path, name); - if (path_exists(tmp)) { - checkAlias = 0; - } else { - D("there is no '%s' skin in '%s'", name, path); - } - } - - if (checkAlias) { - int nn; - - for (nn = 0; ; nn++ ) { - const char* skin_name = skin_aliases[nn].name; - const char* skin_alias = skin_aliases[nn].alias; - - if ( !skin_name ) - break; - - if ( !strcasecmp( skin_name, name ) ) { - D("skin name '%s' aliased to '%s'", name, skin_alias); - name = skin_alias; - break; - } - } - } - - /* Magically support skins like "320x240" */ - if(isdigit(name[0])) { - char *x = strchr(name, 'x'); - if(x && isdigit(x[1])) { - int width = atoi(name); - int height = atoi(x + 1); - int bpp = 16; - char* y = strchr(x+1, 'x'); - if (y && isdigit(y[1])) { - bpp = atoi(y+1); - } - sprintf(tmp,"display {\n width %d\n height %d\n bpp %d}\n", - width, height,bpp); - aconfig_load(root, strdup(tmp)); - path = ":"; - goto found_a_skin; - } - } - - if (path == NULL) { - derror("unknown skin name '%s'", name); - exit(1); - } - - sprintf(tmp, "%s/%s/layout", path, name); - D("trying to load skin file '%s'", tmp); - - if(aconfig_load_file(root, tmp) >= 0) { - sprintf(tmp, "%s/%s/", path, name); - path = tmp; - goto found_a_skin; - } else { - dwarning("could not load skin file '%s', using built-in one\n", - tmp); - } - } - - { - const unsigned char* layout_base; - size_t layout_size; - - name = "<builtin>"; - - layout_base = android_resource_find( "layout", &layout_size ); - if (layout_base != NULL) { - char* base = malloc( layout_size+1 ); - memcpy( base, layout_base, layout_size ); - base[layout_size] = 0; - - D("parsing built-in skin layout file (size=%d)", (int)layout_size); - aconfig_load(root, base); - path = ":"; - } else { - fprintf(stderr, "Couldn't load builtin skin\n"); - exit(1); - } - } - -found_a_skin: - { - win_x = 10; - win_y = 10; - - if (userConfig) - auserConfig_getWindowPos(userConfig, &win_x, &win_y); - } - - if ( qemulator_init(qemulator_get(), root, path, win_x, win_y, opts ) < 0 ) { - fprintf(stderr, "### Error: could not load emulator skin '%s'\n", name); - exit(1); - } - - android_skin_keycharmap = skin_keyboard_charmap_name(qemulator_get()->keyboard); - - /* the default network speed and latency can now be specified by the device skin */ - n = aconfig_find(root, "network"); - if (n != NULL) { - skin_network_speed = aconfig_str(n, "speed", 0); - skin_network_delay = aconfig_str(n, "delay", 0); - } - -#if 0 - /* create a trackball if needed */ - n = aconfig_find(root, "trackball"); - if (n != NULL) { - SkinTrackBallParameters params; - - params.x = aconfig_unsigned(n, "x", 0); - params.y = aconfig_unsigned(n, "y", 0); - params.diameter = aconfig_unsigned(n, "diameter", 20); - params.ring = aconfig_unsigned(n, "ring", 1); - - params.ball_color = aconfig_unsigned(n, "ball-color", 0xffe0e0e0); - params.dot_color = aconfig_unsigned(n, "dot-color", 0xff202020 ); - params.ring_color = aconfig_unsigned(n, "ring-color", 0xff000000 ); - - qemu_disp->trackball = skin_trackball_create( ¶ms ); - skin_trackball_refresh( qemu_disp->trackball ); - } -#endif - - /* add an onion overlay image if needed */ - if (opts->onion) { - SkinImage* onion = skin_image_find_simple( opts->onion ); - int alpha, rotate; - - if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) { - alpha = (256*alpha)/100; - } else - alpha = 128; - - if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) { - rotate &= 3; - } else - rotate = SKIN_ROTATION_0; - - qemulator_get()->onion = onion; - qemulator_get()->onion_alpha = alpha; - qemulator_get()->onion_rotation = rotate; - } -} int qemu_main(int argc, char **argv); @@ -508,88 +130,6 @@ verbose_options[] = { { 0, 0, 0 } }; -static int -load_keyset(const char* path) -{ - if (path_can_read(path)) { - AConfig* root = aconfig_node("",""); - if (!aconfig_load_file(root, path)) { - android_keyset = skin_keyset_new(root); - if (android_keyset != NULL) { - D( "keyset loaded from: %s", path); - return 0; - } - } - } - return -1; -} - -static void -parse_keyset(const char* keyset, AndroidOptions* opts) -{ - char kname[MAX_PATH]; - char temp[MAX_PATH]; - char* p; - char* end; - - /* append .keyset suffix if needed */ - if (strchr(keyset, '.') == NULL) { - p = kname; - end = p + sizeof(kname); - p = bufprint(p, end, "%s.keyset", keyset); - if (p >= end) { - derror( "keyset name too long: '%s'\n", keyset); - exit(1); - } - keyset = kname; - } - - /* look for a the keyset file */ - p = temp; - end = p + sizeof(temp); - p = bufprint_config_file(p, end, keyset); - if (p < end && load_keyset(temp) == 0) - return; - - p = temp; - p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset); - if (p < end && load_keyset(temp) == 0) - return; - - p = temp; - p = bufprint_app_dir(p, end); - p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset); - if (p < end && load_keyset(temp) == 0) - return; - - return; -} - -static void -write_default_keyset( void ) -{ - char path[MAX_PATH]; - - bufprint_config_file( path, path+sizeof(path), KEYSET_FILE ); - - /* only write if there is no file here */ - if ( !path_exists(path) ) { - int fd = open( path, O_WRONLY | O_CREAT, 0666 ); - int ret; - const char* ks = skin_keyset_get_default(); - - - D( "writing default keyset file to %s", path ); - - if (fd < 0) { - D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) ); - return; - } - CHECKED(ret, write(fd, ks, strlen(ks))); - close(fd); - } -} - void emulator_help( void ) { STRALLOC_DEFINE(out); @@ -1654,6 +1194,7 @@ int main(int argc, char **argv) } else if (opts->no_snapshot) { D("ignoring redundant option '-no-snapshot' implied by '-no-snapstorage'"); } + if (opts->snapshot_list) { snapshot_print_and_exit(opts->snapstorage); } diff --git a/android/main.c b/android/main.c index d6c2d8d..078cfbb 100644 --- a/android/main.c +++ b/android/main.c @@ -33,17 +33,9 @@ #include "android/charmap.h" #include "android/utils/debug.h" -#include "android/resource.h" #include "android/config.h" #include "android/config/config.h" -#include "android/skin/image.h" -#include "android/skin/trackball.h" -#include "android/skin/keyboard.h" -#include "android/skin/file.h" -#include "android/skin/window.h" -#include "android/skin/keyset.h" - #include "android/user-config.h" #include "android/utils/bufprint.h" #include "android/utils/dirscanner.h" @@ -51,7 +43,7 @@ #include "android/utils/timezone.h" #include "android/utils/tempfile.h" -#include "android/cmdline-option.h" +#include "android/main-common.h" #include "android/help.h" #include "hw/goldfish_nand.h" @@ -76,9 +68,6 @@ AndroidRotation android_framebuffer_rotation; # define VERSION_STRING "standalone" #endif -#define KEYSET_FILE "default.keyset" -SkinKeyset* android_keyset; - #define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0) extern int control_console_start( int port ); /* in control.c */ @@ -100,388 +89,6 @@ extern void stop_tracing(void); unsigned long android_verbose; -/***********************************************************************/ -/***********************************************************************/ -/***** *****/ -/***** U T I L I T Y R O U T I N E S *****/ -/***** *****/ -/***********************************************************************/ -/***********************************************************************/ - -/*** CONFIGURATION - ***/ - -static AUserConfig* userConfig; - -void -emulator_config_init( void ) -{ - userConfig = auserConfig_new( android_avdInfo ); -} - -/* only call this function on normal exits, so that ^C doesn't save the configuration */ -void -emulator_config_done( void ) -{ - int win_x, win_y; - - if (!userConfig) { - D("no user configuration?"); - return; - } - - SDL_WM_GetPos( &win_x, &win_y ); - auserConfig_setWindowPos(userConfig, win_x, win_y); - auserConfig_save(userConfig); -} - -void *loadpng(const char *fn, unsigned *_width, unsigned *_height); -void *readpng(const unsigned char* base, size_t size, unsigned *_width, unsigned *_height); - -#ifdef CONFIG_DARWIN -# define ANDROID_ICON_PNG "android_icon_256.png" -#else -# define ANDROID_ICON_PNG "android_icon_16.png" -#endif - -static void -sdl_set_window_icon( void ) -{ - static int window_icon_set; - - if (!window_icon_set) - { -#ifdef _WIN32 - HANDLE handle = GetModuleHandle( NULL ); - HICON icon = LoadIcon( handle, MAKEINTRESOURCE(1) ); - SDL_SysWMinfo wminfo; - - SDL_GetWMInfo(&wminfo); - - SetClassLong( wminfo.window, GCL_HICON, (LONG)icon ); -#else /* !_WIN32 */ - unsigned icon_w, icon_h; - size_t icon_bytes; - const unsigned char* icon_data; - void* icon_pixels; - - window_icon_set = 1; - - icon_data = android_icon_find( ANDROID_ICON_PNG, &icon_bytes ); - if ( !icon_data ) - return; - - icon_pixels = readpng( icon_data, icon_bytes, &icon_w, &icon_h ); - if ( !icon_pixels ) - return; - - /* the data is loaded into memory as RGBA bytes by libpng. we want to manage - * the values as 32-bit ARGB pixels, so swap the bytes accordingly depending - * on our CPU endianess - */ - { - unsigned* d = icon_pixels; - unsigned* d_end = d + icon_w*icon_h; - - for ( ; d < d_end; d++ ) { - unsigned pix = d[0]; -#if HOST_WORDS_BIGENDIAN - /* R,G,B,A read as RGBA => ARGB */ - pix = ((pix >> 8) & 0xffffff) | (pix << 24); -#else - /* R,G,B,A read as ABGR => ARGB */ - pix = (pix & 0xff00ff00) | ((pix >> 16) & 0xff) | ((pix & 0xff) << 16); -#endif - d[0] = pix; - } - } - - SDL_Surface* icon = sdl_surface_from_argb32( icon_pixels, icon_w, icon_h ); - if (icon != NULL) { - SDL_WM_SetIcon(icon, NULL); - SDL_FreeSurface(icon); - free( icon_pixels ); - } -#endif /* !_WIN32 */ - } -} - -#define ONE_MB (1024*1024) - -unsigned convertBytesToMB( uint64_t size ) -{ - if (size == 0) - return 0; - - size = (size + ONE_MB-1) >> 20; - if (size > UINT_MAX) - size = UINT_MAX; - - return (unsigned) size; -} - -uint64_t convertMBToBytes( unsigned megaBytes ) -{ - return ((uint64_t)megaBytes << 20); -} - -/***********************************************************************/ -/***********************************************************************/ -/***** *****/ -/***** S K I N I M A G E S *****/ -/***** *****/ -/***********************************************************************/ -/***********************************************************************/ -static void sdl_at_exit(void) -{ - emulator_config_done(); - qemulator_done(qemulator_get()); - SDL_Quit(); -} - - -void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) -{ - QEmulator* emulator = qemulator_get(); - SkinDisplay* disp = skin_layout_get_display(emulator->layout); - int width, height; - char buf[128]; - - if (disp->rotation & 1) { - width = disp->rect.size.h; - height = disp->rect.size.w; - } else { - width = disp->rect.size.w; - height = disp->rect.size.h; - } - - snprintf(buf, sizeof buf, "width=%d,height=%d", width, height); - android_display_init(ds, qframebuffer_fifo_get()); -} - - -static const char* skin_network_speed = NULL; -static const char* skin_network_delay = NULL; - -/* list of skin aliases */ -static const struct { - const char* name; - const char* alias; -} skin_aliases[] = { - { "QVGA-L", "320x240" }, - { "QVGA-P", "240x320" }, - { "HVGA-L", "480x320" }, - { "HVGA-P", "320x480" }, - { "QVGA", "320x240" }, - { "HVGA", "320x480" }, - { NULL, NULL } -}; - -/* this is used by hw/events_device.c to send the charmap name to the system */ -const char* android_skin_keycharmap = NULL; - -void init_skinned_ui(const char *path, const char *name, AndroidOptions* opts) -{ - char tmp[1024]; - AConfig* root; - AConfig* n; - int win_x, win_y, flags; - - signal(SIGINT, SIG_DFL); -#ifndef _WIN32 - signal(SIGQUIT, SIG_DFL); -#endif - - /* we're not a game, so allow the screensaver to run */ - putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1"); - - flags = SDL_INIT_NOPARACHUTE; - if (!opts->no_window) - flags |= SDL_INIT_VIDEO; - - if(SDL_Init(flags)){ - fprintf(stderr, "SDL init failure, reason is: %s\n", SDL_GetError() ); - exit(1); - } - - if (!opts->no_window) { - SDL_EnableUNICODE(!opts->raw_keys); - SDL_EnableKeyRepeat(0,0); - - sdl_set_window_icon(); - } - else - { -#ifndef _WIN32 - /* prevent SIGTTIN and SIGTTOUT from stopping us. this is necessary to be - * able to run the emulator in the background (e.g. "emulator &"). - * despite the fact that the emulator should not grab input or try to - * write to the output in normal cases, we're stopped on some systems - * (e.g. OS X) - */ - signal(SIGTTIN, SIG_IGN); - signal(SIGTTOU, SIG_IGN); -#endif - } - atexit(sdl_at_exit); - - root = aconfig_node("", ""); - - if(name) { - /* Support skin aliases like QVGA-H QVGA-P, etc... - But first we check if it's a directory that exist before applying - the alias */ - int checkAlias = 1; - - if (path != NULL) { - bufprint(tmp, tmp+sizeof(tmp), "%s/%s", path, name); - if (path_exists(tmp)) { - checkAlias = 0; - } else { - D("there is no '%s' skin in '%s'", name, path); - } - } - - if (checkAlias) { - int nn; - - for (nn = 0; ; nn++ ) { - const char* skin_name = skin_aliases[nn].name; - const char* skin_alias = skin_aliases[nn].alias; - - if ( !skin_name ) - break; - - if ( !strcasecmp( skin_name, name ) ) { - D("skin name '%s' aliased to '%s'", name, skin_alias); - name = skin_alias; - break; - } - } - } - - /* Magically support skins like "320x240" or "320x240x16" */ - if(isdigit(name[0])) { - char *x = strchr(name, 'x'); - if(x && isdigit(x[1])) { - int width = atoi(name); - int height = atoi(x+1); - int bpp = 16; - char* y = strchr(x+1, 'x'); - if (y && isdigit(y[1])) { - bpp = atoi(y+1); - } - sprintf(tmp,"display {\n width %d\n height %d\n bpp %d}\n", - width, height,bpp); - aconfig_load(root, strdup(tmp)); - path = ":"; - goto found_a_skin; - } - } - - if (path == NULL) { - derror("unknown skin name '%s'", name); - exit(1); - } - - sprintf(tmp, "%s/%s/layout", path, name); - D("trying to load skin file '%s'", tmp); - - if(aconfig_load_file(root, tmp) >= 0) { - sprintf(tmp, "%s/%s/", path, name); - path = tmp; - goto found_a_skin; - } else { - dwarning("could not load skin file '%s', using built-in one\n", - tmp); - } - } - - { - const unsigned char* layout_base; - size_t layout_size; - - name = "<builtin>"; - - layout_base = android_resource_find( "layout", &layout_size ); - if (layout_base != NULL) { - char* base = malloc( layout_size+1 ); - memcpy( base, layout_base, layout_size ); - base[layout_size] = 0; - - D("parsing built-in skin layout file (size=%d)", (int)layout_size); - aconfig_load(root, base); - path = ":"; - } else { - fprintf(stderr, "Couldn't load builtin skin\n"); - exit(1); - } - } - -found_a_skin: - { - win_x = 10; - win_y = 10; - - if (userConfig) - auserConfig_getWindowPos(userConfig, &win_x, &win_y); - } - - if ( qemulator_init(qemulator_get(), root, path, win_x, win_y, opts ) < 0 ) { - fprintf(stderr, "### Error: could not load emulator skin '%s'\n", name); - exit(1); - } - - android_skin_keycharmap = skin_keyboard_charmap_name(qemulator_get()->keyboard); - - /* the default network speed and latency can now be specified by the device skin */ - n = aconfig_find(root, "network"); - if (n != NULL) { - skin_network_speed = aconfig_str(n, "speed", 0); - skin_network_delay = aconfig_str(n, "delay", 0); - } - -#if 0 - /* create a trackball if needed */ - n = aconfig_find(root, "trackball"); - if (n != NULL) { - SkinTrackBallParameters params; - - params.x = aconfig_unsigned(n, "x", 0); - params.y = aconfig_unsigned(n, "y", 0); - params.diameter = aconfig_unsigned(n, "diameter", 20); - params.ring = aconfig_unsigned(n, "ring", 1); - - params.ball_color = aconfig_unsigned(n, "ball-color", 0xffe0e0e0); - params.dot_color = aconfig_unsigned(n, "dot-color", 0xff202020 ); - params.ring_color = aconfig_unsigned(n, "ring-color", 0xff000000 ); - - qemu_disp->trackball = skin_trackball_create( ¶ms ); - skin_trackball_refresh( qemu_disp->trackball ); - } -#endif - - /* add an onion overlay image if needed */ - if (opts->onion) { - SkinImage* onion = skin_image_find_simple( opts->onion ); - int alpha, rotate; - - if ( opts->onion_alpha && 1 == sscanf( opts->onion_alpha, "%d", &alpha ) ) { - alpha = (256*alpha)/100; - } else - alpha = 128; - - if ( opts->onion_rotation && 1 == sscanf( opts->onion_rotation, "%d", &rotate ) ) { - rotate &= 3; - } else - rotate = SKIN_ROTATION_0; - - qemulator_get()->onion = onion; - qemulator_get()->onion_alpha = alpha; - qemulator_get()->onion_rotation = rotate; - } -} - int qemu_main(int argc, char **argv); /* this function dumps the QEMU help */ @@ -497,88 +104,6 @@ verbose_options[] = { { 0, 0, 0 } }; -static int -load_keyset(const char* path) -{ - if (path_can_read(path)) { - AConfig* root = aconfig_node("",""); - if (!aconfig_load_file(root, path)) { - android_keyset = skin_keyset_new(root); - if (android_keyset != NULL) { - D( "keyset loaded from: %s", path); - return 0; - } - } - } - return -1; -} - -static void -parse_keyset(const char* keyset, AndroidOptions* opts) -{ - char kname[MAX_PATH]; - char temp[MAX_PATH]; - char* p; - char* end; - - /* append .keyset suffix if needed */ - if (strchr(keyset, '.') == NULL) { - p = kname; - end = p + sizeof(kname); - p = bufprint(p, end, "%s.keyset", keyset); - if (p >= end) { - derror( "keyset name too long: '%s'\n", keyset); - exit(1); - } - keyset = kname; - } - - /* look for a the keyset file */ - p = temp; - end = p + sizeof(temp); - p = bufprint_config_file(p, end, keyset); - if (p < end && load_keyset(temp) == 0) - return; - - p = temp; - p = bufprint(p, end, "%s" PATH_SEP "keysets" PATH_SEP "%s", opts->sysdir, keyset); - if (p < end && load_keyset(temp) == 0) - return; - - p = temp; - p = bufprint_app_dir(p, end); - p = bufprint(p, end, PATH_SEP "keysets" PATH_SEP "%s", keyset); - if (p < end && load_keyset(temp) == 0) - return; - - return; -} - -static void -write_default_keyset( void ) -{ - char path[MAX_PATH]; - - bufprint_config_file( path, path+sizeof(path), KEYSET_FILE ); - - /* only write if there is no file here */ - if ( !path_exists(path) ) { - int fd = open( path, O_WRONLY | O_CREAT, 0666 ); - int ret; - const char* ks = skin_keyset_get_default(); - - - D( "writing default keyset file to %s", path ); - - if (fd < 0) { - D( "%s: could not create file: %s", __FUNCTION__, strerror(errno) ); - return; - } - CHECKED(ret, write(fd, ks, strlen(ks))); - close(fd); - } -} - void emulator_help( void ) { STRALLOC_DEFINE(out); |