From 537c7546f946d266e55fdbce03558352a3342908 Mon Sep 17 00:00:00 2001 From: Linus Nielsen Feltzing Date: Tue, 26 Sep 2006 10:03:56 +0000 Subject: Patch #4899 by Robert Keevil - Automatic pause on iPod when removing the headphones git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11057 a1c6a512-1295-4272-9138-f99709370657 --- apps/codecs.c | 1 + apps/codecs.h | 1 + apps/lang/english.lang | 56 ++++++++++++++++++++++++++++++++++++++ apps/misc.c | 36 ++++++++++++++++++++++++ apps/settings.c | 6 ++++ apps/settings.h | 6 ++++ apps/settings_menu.c | 56 +++++++++++++++++++++++++++++++++++++- apps/tree.c | 15 +++++++++- firmware/drivers/button.c | 28 +++++++++++++++++++ firmware/export/button.h | 3 ++ firmware/export/config-ipod4g.h | 3 ++ firmware/export/config-ipodcolor.h | 3 ++ firmware/export/config-ipodnano.h | 3 ++ firmware/export/config-ipodvideo.h | 3 ++ firmware/export/kernel.h | 2 ++ 15 files changed, 220 insertions(+), 2 deletions(-) diff --git a/apps/codecs.c b/apps/codecs.c index b4b8c9833a..d9bda6b0a6 100644 --- a/apps/codecs.c +++ b/apps/codecs.c @@ -218,6 +218,7 @@ struct codec_api ci = { enc_wavbuf_near_empty, enc_get_wav_data, &enc_set_header_callback, + 44100, #endif /* new stuff at the end, sort into place next time diff --git a/apps/codecs.h b/apps/codecs.h index 96804a889b..7cd48f65e2 100644 --- a/apps/codecs.h +++ b/apps/codecs.h @@ -303,6 +303,7 @@ struct codec_api { char* (*enc_get_wav_data)(int size); void (**enc_set_header_callback)(void *head_buffer, int head_size, int num_samples, bool is_file_header); + int sample_rate; #endif /* new stuff at the end, sort into place next time diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 9e6a809dac..4dfbff7ad5 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -9806,3 +9806,59 @@ *: "" + + id: LANG_UNPLUG + desc: in settings_menu. + user: + + *: "Pause on headphone unplug" + + + *: "Pause on headphone unplug" + + + *: "Pause on headphone unplug" + + + + id: LANG_UNPLUG_RESUME + desc: in pause_phones_menu. + user: + + *: "Pause and Resume" + + + *: "Pause and Resume" + + + *: "Pause and Resume" + + + + id: LANG_UNPLUG_RW + desc: in pause_phones_menu. + user: + + *: "Duration to rewind" + + + *: "Duration to rewind" + + + *: "Duration to rewind" + + + + id: LANG_UNPLUG_DISABLE_AUTORESUME + desc: in pause_phones_menu. + user: + + *: "Disable auto-resume if phones not present" + + + *: "Disable auto-resume if phones not present" + + + *: "Disable auto-resume if phones not present" + + diff --git a/apps/misc.c b/apps/misc.c index e95c5e5650..806f5ff63e 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -580,6 +580,33 @@ void car_adapter_mode_init(void) } #endif +#ifdef HAVE_HEADPHONE_DETECTION +void unplug_change(bool inserted) +{ + if (global_settings.unplug_mode) + { + if (inserted) + { + if ( global_settings.unplug_mode > 1 ) + audio_resume(); + backlight_on(); + } else { + audio_pause(); + + if (global_settings.unplug_rw) + { + if ( audio_current_track()->elapsed > + (unsigned long)(global_settings.unplug_rw*1000)) + audio_ff_rewind(audio_current_track()->elapsed - + (global_settings.unplug_rw*1000)); + else + audio_ff_rewind(0); + } + } + } +} +#endif + long default_event_handler_ex(long event, void (*callback)(void *), void *parameter) { switch(event) @@ -608,6 +635,15 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame case SYS_CHARGER_DISCONNECTED: car_adapter_mode_processing(false); return SYS_CHARGER_DISCONNECTED; +#endif +#ifdef HAVE_HEADPHONE_DETECTION + case SYS_PHONE_PLUGGED: + unplug_change(true); + return SYS_PHONE_PLUGGED; + + case SYS_PHONE_UNPLUGGED: + unplug_change(false); + return SYS_PHONE_UNPLUGGED; #endif } return 0; diff --git a/apps/settings.c b/apps/settings.c index 3dc4ee1530..4746c22c87 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -655,6 +655,12 @@ static const struct bit_entry hd_bits[] = #endif #endif +#ifdef HAVE_HEADPHONE_DETECTION + {2, S_O(unplug_mode), 0, "pause on headphone unplug", NULL}, + {4, S_O(unplug_rw), 0, "rewind duration on pause", NULL}, + {1, S_O(unplug_autoresume), 0, "disable autoresume if phones not present", off_on }, +#endif + /* If values are just added to the end, no need to bump the version. */ /* new stuff to be added at the end */ diff --git a/apps/settings.h b/apps/settings.h index 561dc59375..9f8372415a 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -486,6 +486,12 @@ struct user_settings #endif bool hold_lr_for_scroll_in_list; /* hold L/R scrolls the list left/right */ int show_path_in_browser; /* 0=off, 1=current directory, 2=full path */ + +#ifdef HAVE_HEADPHONE_DETECTION + int unplug_mode; /* pause on headphone unplug */ + int unplug_rw; /* time in s to rewind when pausing */ + bool unplug_autoresume; /* disable auto-resume if no phones */ +#endif }; enum optiontype { INT, BOOL }; diff --git a/apps/settings_menu.c b/apps/settings_menu.c index 8f9fbe1c62..36615cfc6a 100644 --- a/apps/settings_menu.c +++ b/apps/settings_menu.c @@ -1664,6 +1664,57 @@ static bool tagcache_settings_menu(void) return result; } +#ifdef HAVE_HEADPHONE_DETECTION +static bool unplug_mode(void) +{ + static const struct opt_items names[] = { + { STR(LANG_OFF) }, + { STR(LANG_PAUSE) }, + { STR(LANG_UNPLUG_RESUME) }, + }; + bool ret; + ret=set_option( str(LANG_UNPLUG), + &global_settings.unplug_mode, INT, names, 3, NULL); + + return ret; +} + +static bool unplug_rw(void) +{ + bool ret; + + ret = set_int(str(LANG_UNPLUG_RW), "s", UNIT_SEC, + &global_settings.unplug_rw, + NULL, 1, 0, 15, NULL ); + audio_set_crossfade(global_settings.unplug_rw); + return ret; +} + +static bool unplug_autoresume(void) +{ + return set_bool( str(LANG_UNPLUG_DISABLE_AUTORESUME), + &global_settings.unplug_autoresume ); +} + +static bool unplug_menu(void) +{ + int m; + bool result; + + static const struct menu_item items[] = { + { ID2P(LANG_UNPLUG), unplug_mode }, + { ID2P(LANG_UNPLUG_RW), unplug_rw }, + { ID2P(LANG_UNPLUG_DISABLE_AUTORESUME), unplug_autoresume }, + }; + + m=menu_init( items, sizeof(items) / sizeof(*items), NULL, + NULL, NULL, NULL); + result = menu_run(m); + menu_exit(m); + return result; +} +#endif + static bool playback_settings_menu(void) { int m; @@ -1687,7 +1738,10 @@ static bool playback_settings_menu(void) { ID2P(LANG_SPDIF_ENABLE), spdif }, #endif { ID2P(LANG_ID3_ORDER), id3_order }, - { ID2P(LANG_NEXT_FOLDER), next_folder } + { ID2P(LANG_NEXT_FOLDER), next_folder }, +#ifdef HAVE_HEADPHONE_DETECTION + { ID2P(LANG_UNPLUG), unplug_menu } +#endif }; bool old_shuffle = global_settings.playlist_shuffle; diff --git a/apps/tree.c b/apps/tree.c index 3ee3061540..0e2dcb6c87 100644 --- a/apps/tree.c +++ b/apps/tree.c @@ -466,7 +466,20 @@ static void start_resume(bool just_powered_on) /* always resume? */ if ( global_settings.resume || ! just_powered_on) - do_resume = true; +#ifdef HAVE_HEADPHONE_DETECTION + { + if ( just_powered_on ) + { + if ( !global_settings.unplug_autoresume + || headphones_inserted() ) + do_resume = true; + } + else + do_resume = true; + } +#else + do_resume = true; +#endif if (! do_resume) return; diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 5add6cb817..0042d9b8eb 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c @@ -92,6 +92,10 @@ static bool remote_button_hold_only(void); int int_btn = BUTTON_NONE; #endif +#ifdef HAVE_HEADPHONE_DETECTION +bool phones_present = false; +#endif + #if (CONFIG_KEYPAD == IPOD_4G_PAD) && !defined(IPOD_MINI) static void opto_i2c_init(void) { @@ -433,6 +437,23 @@ static void button_tick(void) } #endif +#ifdef HAVE_HEADPHONE_DETECTION + if ( headphones_inserted() ) + { + if (! phones_present ) + { + queue_post(&button_queue, SYS_PHONE_PLUGGED, NULL); + phones_present = true; + } + } else { + if ( phones_present ) + { + queue_post(&button_queue, SYS_PHONE_UNPLUGGED, NULL); + phones_present = false; + } + } +#endif + btn = button_read(); /* Find out if a key has been released */ @@ -1327,3 +1348,10 @@ void button_clear_queue(void) queue_clear(&button_queue); } +#ifdef HAVE_HEADPHONE_DETECTION +bool headphones_inserted(void) +{ + return (GPIOA_INPUT_VAL & 0x80)?true:false; +} +#endif + diff --git a/firmware/export/button.h b/firmware/export/button.h index 0e11da9da5..39dfbff6fa 100644 --- a/firmware/export/button.h +++ b/firmware/export/button.h @@ -54,6 +54,9 @@ bool button_hold(void); #ifdef HAS_REMOTE_BUTTON_HOLD bool remote_button_hold(void); #endif +#ifdef HAVE_HEADPHONE_DETECTION +bool headphones_inserted(void); +#endif #define BUTTON_NONE 0x00000000 diff --git a/firmware/export/config-ipod4g.h b/firmware/export/config-ipod4g.h index a5f186782f..2e8c4dcc33 100644 --- a/firmware/export/config-ipod4g.h +++ b/firmware/export/config-ipod4g.h @@ -109,6 +109,9 @@ /* Define this if you have adjustable CPU frequency */ #define HAVE_ADJUSTABLE_CPU_FREQ +/* Define this if you can detect headphones */ +#define HAVE_HEADPHONE_DETECTION + #define BOOTFILE_EXT "ipod" #define BOOTFILE "rockbox." BOOTFILE_EXT diff --git a/firmware/export/config-ipodcolor.h b/firmware/export/config-ipodcolor.h index 3366baa8ea..964f103214 100644 --- a/firmware/export/config-ipodcolor.h +++ b/firmware/export/config-ipodcolor.h @@ -105,6 +105,9 @@ /* Define this if you have adjustable CPU frequency */ #define HAVE_ADJUSTABLE_CPU_FREQ +/* Define this if you can detect headphones */ +#define HAVE_HEADPHONE_DETECTION + #define BOOTFILE_EXT "ipod" #define BOOTFILE "rockbox." BOOTFILE_EXT diff --git a/firmware/export/config-ipodnano.h b/firmware/export/config-ipodnano.h index c077c381f8..03f5b8c753 100644 --- a/firmware/export/config-ipodnano.h +++ b/firmware/export/config-ipodnano.h @@ -110,6 +110,9 @@ /* Define this if you have adjustable CPU frequency */ #define HAVE_ADJUSTABLE_CPU_FREQ +/* Define this if you can detect headphones */ +#define HAVE_HEADPHONE_DETECTION + #define BOOTFILE_EXT "ipod" #define BOOTFILE "rockbox." BOOTFILE_EXT diff --git a/firmware/export/config-ipodvideo.h b/firmware/export/config-ipodvideo.h index 5cea64deb4..4781a2c887 100644 --- a/firmware/export/config-ipodvideo.h +++ b/firmware/export/config-ipodvideo.h @@ -110,6 +110,9 @@ /* Define this if you have adjustable CPU frequency */ #define HAVE_ADJUSTABLE_CPU_FREQ +/* Define this if you can detect headphones */ +#define HAVE_HEADPHONE_DETECTION + #define BOOTFILE_EXT "ipod" #define BOOTFILE "rockbox." BOOTFILE_EXT diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h index 482516b9dc..fcab2d923c 100644 --- a/firmware/export/kernel.h +++ b/firmware/export/kernel.h @@ -46,6 +46,8 @@ #define SYS_FS_CHANGED ((SYS_EVENT | ((long)9 << 27))) #define SYS_CHARGER_CONNECTED ((SYS_EVENT | ((long)10 << 27))) #define SYS_CHARGER_DISCONNECTED ((SYS_EVENT | ((long)11 << 27))) +#define SYS_PHONE_PLUGGED ((SYS_EVENT | ((long)12 << 27))) +#define SYS_PHONE_UNPLUGGED ((SYS_EVENT | ((long)13 << 27))) struct event { -- cgit v1.2.3