diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 27323f78..7953e77f 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2,8 +2,8 @@ + a:versionCode="21" + a:versionName="1.1.0.17" > diff --git a/gen/com/thejoshwa/ultrasonic/androidapp/R.java b/gen/com/thejoshwa/ultrasonic/androidapp/R.java index 7adeb426..c1845fee 100644 --- a/gen/com/thejoshwa/ultrasonic/androidapp/R.java +++ b/gen/com/thejoshwa/ultrasonic/androidapp/R.java @@ -783,6 +783,11 @@ or to a theme attribute in the form "?[package:][type:]na public static final int song_artist=0x7f0600a2; public static final int song_check=0x7f06009e; public static final int song_duration=0x7f0600a3; + public static final int song_menu_pin=0x7f0600ca; + public static final int song_menu_play_last=0x7f0600c9; + public static final int song_menu_play_next=0x7f0600c8; + public static final int song_menu_play_now=0x7f0600c7; + public static final int song_menu_unpin=0x7f0600cb; public static final int song_star=0x7f0600a4; public static final int song_status=0x7f0600a1; public static final int song_title=0x7f0600a0; @@ -849,6 +854,7 @@ or to a theme attribute in the form "?[package:][type:]na public static final int select_artist_context=0x7f0e0005; public static final int select_playlist_context=0x7f0e0006; public static final int select_playlist_context_offline=0x7f0e0007; + public static final int select_song_context=0x7f0e0008; } public static final class plurals { public static final int select_album_donate_dialog_n_trial_days_left=0x7f0d0005; @@ -859,17 +865,17 @@ or to a theme attribute in the form "?[package:][type:]na public static final int select_album_n_songs_unpinned=0x7f0d0002; } public static final class string { - public static final int background_task_loading=0x7f08011f; - public static final int background_task_network_error=0x7f080121; - public static final int background_task_no_network=0x7f080120; - public static final int background_task_not_found=0x7f080122; - public static final int background_task_parse_error=0x7f080123; - public static final int background_task_wait=0x7f08011e; - public static final int button_bar_browse=0x7f080019; - public static final int button_bar_home=0x7f080018; - public static final int button_bar_now_playing=0x7f08001c; - public static final int button_bar_playlists=0x7f08001b; - public static final int button_bar_search=0x7f08001a; + public static final int background_task_loading=0x7f080122; + public static final int background_task_network_error=0x7f080124; + public static final int background_task_no_network=0x7f080123; + public static final int background_task_not_found=0x7f080125; + public static final int background_task_parse_error=0x7f080126; + public static final int background_task_wait=0x7f080121; + public static final int button_bar_browse=0x7f08001a; + public static final int button_bar_home=0x7f080019; + public static final int button_bar_now_playing=0x7f08001d; + public static final int button_bar_playlists=0x7f08001c; + public static final int button_bar_search=0x7f08001b; public static final int common_appname=0x7f080006; public static final int common_cancel=0x7f080009; public static final int common_comment=0x7f080016; @@ -886,105 +892,106 @@ or to a theme attribute in the form "?[package:][type:]na public static final int common_play_shuffled=0x7f080013; public static final int common_public=0x7f080017; public static final int common_save=0x7f080008; + public static final int common_show_artist=0x7f080018; public static final int common_unpin=0x7f08000e; public static final int common_various_artists=0x7f080010; - public static final int delete_playlist=0x7f08008d; - public static final int download_empty=0x7f080069; - public static final int download_jukebox_not_authorized=0x7f080088; - public static final int download_jukebox_off=0x7f080084; - public static final int download_jukebox_offline=0x7f080087; - public static final int download_jukebox_on=0x7f080083; - public static final int download_jukebox_server_too_old=0x7f080086; - public static final int download_jukebox_volume=0x7f080085; - public static final int download_menu_equalizer=0x7f080075; - public static final int download_menu_jukebox=0x7f080077; - public static final int download_menu_lyrics=0x7f08006e; - public static final int download_menu_remove=0x7f08006f; - public static final int download_menu_remove_all=0x7f080070; - public static final int download_menu_save=0x7f080074; - public static final int download_menu_screen_off=0x7f080072; - public static final int download_menu_screen_on=0x7f080071; - public static final int download_menu_show_album=0x7f08006d; - public static final int download_menu_shuffle=0x7f080073; - public static final int download_menu_shuffle_notification=0x7f080078; - public static final int download_menu_visualizer=0x7f080076; - public static final int download_playerstate_buffering=0x7f08006b; - public static final int download_playerstate_downloading=0x7f08006a; - public static final int download_playerstate_playing_shuffle=0x7f08006c; - public static final int download_playlist_done=0x7f08007c; - public static final int download_playlist_error=0x7f08007d; - public static final int download_playlist_name=0x7f08007a; - public static final int download_playlist_saving=0x7f08007b; - public static final int download_playlist_title=0x7f080079; - public static final int download_repeat_all=0x7f08007f; - public static final int download_repeat_off=0x7f08007e; - public static final int download_repeat_single=0x7f080080; - public static final int download_visualizer_off=0x7f080082; - public static final int download_visualizer_on=0x7f080081; - public static final int equalizer_enabled=0x7f080130; - public static final int equalizer_label=0x7f08012f; - public static final int equalizer_preset=0x7f080131; - public static final int error_label=0x7f080091; - public static final int help_back=0x7f080046; - public static final int help_close=0x7f080047; - public static final int help_label=0x7f080044; - public static final int help_loading=0x7f080049; - public static final int help_title=0x7f080045; - public static final int help_url=0x7f080048; - public static final int lyrics_nomatch=0x7f080090; - public static final int main_albums_alphaByArtist=0x7f08002f; - public static final int main_albums_alphaByName=0x7f08002e; - public static final int main_albums_frequent=0x7f08002a; - public static final int main_albums_highest=0x7f08002b; - public static final int main_albums_newest=0x7f080028; - public static final int main_albums_random=0x7f08002c; - public static final int main_albums_recent=0x7f080029; - public static final int main_albums_starred=0x7f08002d; - public static final int main_albums_title=0x7f080027; - public static final int main_artists_title=0x7f080025; - public static final int main_genres_title=0x7f080026; - public static final int main_music=0x7f080034; - public static final int main_offline=0x7f080023; - public static final int main_select_all_genres=0x7f080021; - public static final int main_select_genre=0x7f080020; - public static final int main_select_server=0x7f08001f; - public static final int main_settings=0x7f080024; - public static final int main_shuffle=0x7f080022; - public static final int main_songs_genre=0x7f080033; - public static final int main_songs_random=0x7f080032; - public static final int main_songs_starred=0x7f080031; - public static final int main_songs_title=0x7f080030; - public static final int main_welcome_text=0x7f08001e; - public static final int main_welcome_title=0x7f08001d; - public static final int menu_about=0x7f080038; - public static final int menu_add_playlist=0x7f08003c; - public static final int menu_common=0x7f08003b; - public static final int menu_deleted_playlist=0x7f08003e; - public static final int menu_deleted_playlist_error=0x7f08003f; - public static final int menu_exit=0x7f080035; - public static final int menu_help=0x7f080037; - public static final int menu_navigation=0x7f08003a; - public static final int menu_remove_playlist=0x7f08003d; - public static final int menu_search=0x7f080039; - public static final int menu_settings=0x7f080036; - public static final int music_library_label=0x7f080055; - public static final int music_library_label_offline=0x7f080056; - public static final int music_service_retry=0x7f08011d; - public static final int parser_artist_count=0x7f08012b; - public static final int parser_not_authenticated=0x7f080129; - public static final int parser_not_authorized=0x7f08012a; - public static final int parser_reading=0x7f080125; - public static final int parser_reading_done=0x7f080126; - public static final int parser_upgrade_client=0x7f080127; - public static final int parser_upgrade_server=0x7f080128; - public static final int play_video_loading=0x7f08004a; - public static final int play_video_noplugin=0x7f08004b; - public static final int playlist_label=0x7f080040; - public static final int playlist_update_info=0x7f080041; - public static final int playlist_updated_info=0x7f080042; - public static final int playlist_updated_info_error=0x7f080043; - public static final int playlist_error=0x7f080089; - public static final int progress_wait=0x7f080054; + public static final int delete_playlist=0x7f08008e; + public static final int download_empty=0x7f08006a; + public static final int download_jukebox_not_authorized=0x7f080089; + public static final int download_jukebox_off=0x7f080085; + public static final int download_jukebox_offline=0x7f080088; + public static final int download_jukebox_on=0x7f080084; + public static final int download_jukebox_server_too_old=0x7f080087; + public static final int download_jukebox_volume=0x7f080086; + public static final int download_menu_equalizer=0x7f080076; + public static final int download_menu_jukebox=0x7f080078; + public static final int download_menu_lyrics=0x7f08006f; + public static final int download_menu_remove=0x7f080070; + public static final int download_menu_remove_all=0x7f080071; + public static final int download_menu_save=0x7f080075; + public static final int download_menu_screen_off=0x7f080073; + public static final int download_menu_screen_on=0x7f080072; + public static final int download_menu_show_album=0x7f08006e; + public static final int download_menu_shuffle=0x7f080074; + public static final int download_menu_shuffle_notification=0x7f080079; + public static final int download_menu_visualizer=0x7f080077; + public static final int download_playerstate_buffering=0x7f08006c; + public static final int download_playerstate_downloading=0x7f08006b; + public static final int download_playerstate_playing_shuffle=0x7f08006d; + public static final int download_playlist_done=0x7f08007d; + public static final int download_playlist_error=0x7f08007e; + public static final int download_playlist_name=0x7f08007b; + public static final int download_playlist_saving=0x7f08007c; + public static final int download_playlist_title=0x7f08007a; + public static final int download_repeat_all=0x7f080080; + public static final int download_repeat_off=0x7f08007f; + public static final int download_repeat_single=0x7f080081; + public static final int download_visualizer_off=0x7f080083; + public static final int download_visualizer_on=0x7f080082; + public static final int equalizer_enabled=0x7f080133; + public static final int equalizer_label=0x7f080132; + public static final int equalizer_preset=0x7f080134; + public static final int error_label=0x7f080092; + public static final int help_back=0x7f080047; + public static final int help_close=0x7f080048; + public static final int help_label=0x7f080045; + public static final int help_loading=0x7f08004a; + public static final int help_title=0x7f080046; + public static final int help_url=0x7f080049; + public static final int lyrics_nomatch=0x7f080091; + public static final int main_albums_alphaByArtist=0x7f080030; + public static final int main_albums_alphaByName=0x7f08002f; + public static final int main_albums_frequent=0x7f08002b; + public static final int main_albums_highest=0x7f08002c; + public static final int main_albums_newest=0x7f080029; + public static final int main_albums_random=0x7f08002d; + public static final int main_albums_recent=0x7f08002a; + public static final int main_albums_starred=0x7f08002e; + public static final int main_albums_title=0x7f080028; + public static final int main_artists_title=0x7f080026; + public static final int main_genres_title=0x7f080027; + public static final int main_music=0x7f080035; + public static final int main_offline=0x7f080024; + public static final int main_select_all_genres=0x7f080022; + public static final int main_select_genre=0x7f080021; + public static final int main_select_server=0x7f080020; + public static final int main_settings=0x7f080025; + public static final int main_shuffle=0x7f080023; + public static final int main_songs_genre=0x7f080034; + public static final int main_songs_random=0x7f080033; + public static final int main_songs_starred=0x7f080032; + public static final int main_songs_title=0x7f080031; + public static final int main_welcome_text=0x7f08001f; + public static final int main_welcome_title=0x7f08001e; + public static final int menu_about=0x7f080039; + public static final int menu_add_playlist=0x7f08003d; + public static final int menu_common=0x7f08003c; + public static final int menu_deleted_playlist=0x7f08003f; + public static final int menu_deleted_playlist_error=0x7f080040; + public static final int menu_exit=0x7f080036; + public static final int menu_help=0x7f080038; + public static final int menu_navigation=0x7f08003b; + public static final int menu_remove_playlist=0x7f08003e; + public static final int menu_search=0x7f08003a; + public static final int menu_settings=0x7f080037; + public static final int music_library_label=0x7f080056; + public static final int music_library_label_offline=0x7f080057; + public static final int music_service_retry=0x7f080120; + public static final int parser_artist_count=0x7f08012e; + public static final int parser_not_authenticated=0x7f08012c; + public static final int parser_not_authorized=0x7f08012d; + public static final int parser_reading=0x7f080128; + public static final int parser_reading_done=0x7f080129; + public static final int parser_upgrade_client=0x7f08012a; + public static final int parser_upgrade_server=0x7f08012b; + public static final int play_video_loading=0x7f08004b; + public static final int play_video_noplugin=0x7f08004c; + public static final int playlist_label=0x7f080041; + public static final int playlist_update_info=0x7f080042; + public static final int playlist_updated_info=0x7f080043; + public static final int playlist_updated_info_error=0x7f080044; + public static final int playlist_error=0x7f08008a; + public static final int progress_wait=0x7f080055; /** Just use standard Pull Down String when pulling up. These can be set for languages which require it Just use standard Pull Down String when pulling up. These can be set for languages which require it */ @@ -994,189 +1001,191 @@ or to a theme attribute in the form "?[package:][type:]na public static final int pull_to_refresh_pull_label=0x7f080000; public static final int pull_to_refresh_refreshing_label=0x7f080002; public static final int pull_to_refresh_release_label=0x7f080001; - public static final int removed_playlist=0x7f08008c; - public static final int search_albums=0x7f080051; - public static final int search_artists=0x7f080050; - public static final int search_label=0x7f08004c; - public static final int search_more=0x7f080053; - public static final int search_no_match=0x7f08004f; - public static final int search_search=0x7f08004e; - public static final int search_songs=0x7f080052; - public static final int search_title=0x7f08004d; - public static final int select_album_donate_dialog_0_trial_days_left=0x7f080065; - public static final int select_album_donate_dialog_later=0x7f080064; - public static final int select_album_donate_dialog_message=0x7f080062; - public static final int select_album_donate_dialog_now=0x7f080063; - public static final int select_album_empty=0x7f080057; - public static final int select_album_more=0x7f08005b; - public static final int select_album_n_selected=0x7f080059; - public static final int select_album_n_unselected=0x7f08005a; - public static final int select_album_no_network=0x7f080060; - public static final int select_album_no_sdcard=0x7f08005f; - public static final int select_album_not_licensed=0x7f080061; - public static final int select_album_offline=0x7f08005c; - public static final int select_album_play_all=0x7f08005e; - public static final int select_album_searching=0x7f08005d; - public static final int select_album_select=0x7f080058; - public static final int select_artist_all_folders=0x7f08012e; - public static final int select_artist_empty=0x7f080066; - public static final int select_artist_folder=0x7f08012d; - public static final int select_artist_refresh=0x7f08012c; - public static final int select_genre_empty=0x7f080067; - public static final int select_playlist_empty=0x7f080068; - public static final int service_connecting=0x7f080124; - public static final int settings_appearance_title=0x7f0800ab; - public static final int settings_buffer_length=0x7f0800e4; - public static final int settings_buffer_length_1=0x7f0800e6; - public static final int settings_buffer_length_10=0x7f0800ea; - public static final int settings_buffer_length_12=0x7f0800eb; - public static final int settings_buffer_length_15=0x7f0800ec; - public static final int settings_buffer_length_2=0x7f0800e7; - public static final int settings_buffer_length_20=0x7f0800ed; - public static final int settings_buffer_length_30=0x7f0800ee; - public static final int settings_buffer_length_5=0x7f0800e8; - public static final int settings_buffer_length_8=0x7f0800e9; - public static final int settings_cache_location=0x7f0800a3; - public static final int settings_cache_location_error=0x7f0800a4; - public static final int settings_cache_size=0x7f0800a2; - public static final int settings_cache_size_100=0x7f0800cb; - public static final int settings_cache_size_1000=0x7f0800ce; - public static final int settings_cache_size_10000=0x7f0800d1; - public static final int settings_cache_size_200=0x7f0800cc; - public static final int settings_cache_size_2000=0x7f0800cf; - public static final int settings_cache_size_20000=0x7f0800d2; - public static final int settings_cache_size_500=0x7f0800cd; - public static final int settings_cache_size_5000=0x7f0800d0; - public static final int settings_cache_size_unlimited=0x7f0800d3; - public static final int settings_cache_title=0x7f0800a0; - public static final int settings_clear_search_history=0x7f0800d4; - public static final int settings_connection_failure=0x7f0800a8; - public static final int settings_default_albums=0x7f080117; - public static final int settings_default_artists=0x7f080116; - public static final int settings_default_songs=0x7f080118; - public static final int settings_display_bitrate=0x7f0800bf; - public static final int settings_display_bitrate_summary=0x7f0800c0; - public static final int settings_download_transition=0x7f0800ff; - public static final int settings_download_transition_summary=0x7f080100; - public static final int settings_gapless_playback=0x7f080101; - public static final int settings_gapless_playback_summary=0x7f080102; - public static final int settings_hide_media_summary=0x7f0800de; - public static final int settings_hide_media_title=0x7f0800dd; - public static final int settings_hide_media_toast=0x7f0800df; - public static final int settings_increment_time=0x7f080119; - public static final int settings_invalid_url=0x7f0800a9; - public static final int settings_invalid_username=0x7f0800aa; - public static final int settings_max_albums=0x7f080105; - public static final int settings_max_artists=0x7f080114; - public static final int settings_max_bitrate_112=0x7f0800b6; - public static final int settings_max_bitrate_128=0x7f0800b7; - public static final int settings_max_bitrate_160=0x7f0800b8; - public static final int settings_max_bitrate_192=0x7f0800b9; - public static final int settings_max_bitrate_256=0x7f0800ba; - public static final int settings_max_bitrate_32=0x7f0800b2; - public static final int settings_max_bitrate_320=0x7f0800bb; - public static final int settings_max_bitrate_64=0x7f0800b3; - public static final int settings_max_bitrate_80=0x7f0800b4; - public static final int settings_max_bitrate_96=0x7f0800b5; - public static final int settings_max_bitrate_mobile=0x7f0800b1; - public static final int settings_max_bitrate_unlimited=0x7f0800bc; - public static final int settings_max_bitrate_wifi=0x7f0800b0; - public static final int settings_max_songs=0x7f080115; - public static final int settings_media_button_summary=0x7f0800e1; - public static final int settings_media_button_title=0x7f0800e0; - public static final int settings_network_timeout=0x7f0800e5; - public static final int settings_network_timeout_105000=0x7f0800f5; - public static final int settings_network_timeout_120000=0x7f0800f6; - public static final int settings_network_timeout_15000=0x7f0800ef; - public static final int settings_network_timeout_30000=0x7f0800f0; - public static final int settings_network_timeout_45000=0x7f0800f1; - public static final int settings_network_timeout_60000=0x7f0800f2; - public static final int settings_network_timeout_75000=0x7f0800f3; - public static final int settings_network_timeout_90000=0x7f0800f4; - public static final int settings_network_title=0x7f0800af; - public static final int settings_other_title=0x7f0800d6; - public static final int settings_playback_control_title=0x7f0800d8; - public static final int settings_preload=0x7f0800a1; - public static final int settings_preload_1=0x7f0800c5; - public static final int settings_preload_10=0x7f0800c9; - public static final int settings_preload_2=0x7f0800c6; - public static final int settings_preload_3=0x7f0800c7; - public static final int settings_preload_5=0x7f0800c8; - public static final int settings_preload_unlimited=0x7f0800ca; - public static final int settings_screen_lit_summary=0x7f0800e3; - public static final int settings_screen_lit_title=0x7f0800e2; - public static final int settings_scrobble_summary=0x7f0800da; - public static final int settings_scrobble_title=0x7f0800d9; - public static final int settings_search_1=0x7f080106; - public static final int settings_search_10=0x7f080109; - public static final int settings_search_100=0x7f080111; - public static final int settings_search_15=0x7f08010a; - public static final int settings_search_20=0x7f08010b; - public static final int settings_search_25=0x7f08010c; - public static final int settings_search_250=0x7f080112; - public static final int settings_search_3=0x7f080107; - public static final int settings_search_30=0x7f08010d; - public static final int settings_search_40=0x7f08010e; - public static final int settings_search_5=0x7f080108; - public static final int settings_search_50=0x7f08010f; - public static final int settings_search_500=0x7f080113; - public static final int settings_search_75=0x7f080110; - public static final int settings_search_history_cleared=0x7f0800d5; - public static final int settings_search_title=0x7f0800d7; - public static final int settings_server_add_server=0x7f08009a; - public static final int settings_server_address=0x7f08009d; - public static final int settings_server_name=0x7f080099; - public static final int settings_server_number=0x7f08009b; - public static final int settings_server_password=0x7f08009f; - public static final int settings_server_remove_server=0x7f08009c; - public static final int settings_server_scaling_summary=0x7f0800dc; - public static final int settings_server_scaling_title=0x7f0800db; - public static final int settings_server_unused=0x7f080095; - public static final int settings_server_unused1=0x7f080096; - public static final int settings_server_unused2=0x7f080097; - public static final int settings_server_unused3=0x7f080098; - public static final int settings_server_username=0x7f08009e; - public static final int settings_servers_title=0x7f080094; - public static final int settings_show_lockscreen_controls=0x7f0800fb; - public static final int settings_show_lockscreen_controls_summary=0x7f0800fc; - public static final int settings_show_notification=0x7f0800f7; - public static final int settings_show_notification_always=0x7f0800f9; - public static final int settings_show_notification_always_summary=0x7f0800fa; - public static final int settings_show_notification_summary=0x7f0800f8; - public static final int settings_show_now_playing=0x7f080103; - public static final int settings_show_now_playing_summary=0x7f080104; - public static final int settings_show_track_number=0x7f0800c3; - public static final int settings_show_track_number_summary=0x7f0800c4; - public static final int settings_test_connection_title=0x7f080093; - public static final int settings_testing_connection=0x7f0800a5; - public static final int settings_testing_ok=0x7f0800a6; - public static final int settings_testing_unlicensed=0x7f0800a7; - public static final int settings_theme_dark=0x7f0800ae; - public static final int settings_theme_light=0x7f0800ad; - public static final int settings_theme_title=0x7f0800ac; - public static final int settings_title=0x7f080092; - public static final int settings_use_folder_for_album_artist=0x7f0800c1; - public static final int settings_use_folder_for_album_artist_summary=0x7f0800c2; - public static final int settings_use_stream_proxy=0x7f0800fd; - public static final int settings_use_stream_proxy_summary=0x7f0800fe; - public static final int settings_wifi_required_summary=0x7f0800be; - public static final int settings_wifi_required_title=0x7f0800bd; - public static final int shuffle_endYear=0x7f08011b; - public static final int shuffle_genre=0x7f08011c; - public static final int shuffle_startYear=0x7f08011a; - public static final int song_details_all=0x7f08008e; - public static final int song_details_kbps=0x7f08008f; - public static final int updated_playlist=0x7f08008a; - public static final int updated_playlist_error=0x7f08008b; - public static final int util_bytes_format_byte=0x7f080138; - public static final int util_bytes_format_gigabyte=0x7f080135; - public static final int util_bytes_format_kilobyte=0x7f080137; - public static final int util_bytes_format_megabyte=0x7f080136; - public static final int util_no_time=0x7f080139; - public static final int util_zero_time=0x7f08013a; - public static final int widget_initial_text=0x7f080132; - public static final int widget_sdcard_busy=0x7f080133; - public static final int widget_sdcard_missing=0x7f080134; + public static final int removed_playlist=0x7f08008d; + public static final int search_albums=0x7f080052; + public static final int search_artists=0x7f080051; + public static final int search_label=0x7f08004d; + public static final int search_more=0x7f080054; + public static final int search_no_match=0x7f080050; + public static final int search_search=0x7f08004f; + public static final int search_songs=0x7f080053; + public static final int search_title=0x7f08004e; + public static final int select_album_donate_dialog_0_trial_days_left=0x7f080066; + public static final int select_album_donate_dialog_later=0x7f080065; + public static final int select_album_donate_dialog_message=0x7f080063; + public static final int select_album_donate_dialog_now=0x7f080064; + public static final int select_album_empty=0x7f080058; + public static final int select_album_more=0x7f08005c; + public static final int select_album_n_selected=0x7f08005a; + public static final int select_album_n_unselected=0x7f08005b; + public static final int select_album_no_network=0x7f080061; + public static final int select_album_no_sdcard=0x7f080060; + public static final int select_album_not_licensed=0x7f080062; + public static final int select_album_offline=0x7f08005d; + public static final int select_album_play_all=0x7f08005f; + public static final int select_album_searching=0x7f08005e; + public static final int select_album_select=0x7f080059; + public static final int select_artist_all_folders=0x7f080131; + public static final int select_artist_empty=0x7f080067; + public static final int select_artist_folder=0x7f080130; + public static final int select_artist_refresh=0x7f08012f; + public static final int select_genre_empty=0x7f080068; + public static final int select_playlist_empty=0x7f080069; + public static final int service_connecting=0x7f080127; + public static final int settings_appearance_title=0x7f0800ac; + public static final int settings_buffer_length=0x7f0800e5; + public static final int settings_buffer_length_1=0x7f0800e7; + public static final int settings_buffer_length_10=0x7f0800eb; + public static final int settings_buffer_length_12=0x7f0800ec; + public static final int settings_buffer_length_15=0x7f0800ed; + public static final int settings_buffer_length_2=0x7f0800e8; + public static final int settings_buffer_length_20=0x7f0800ee; + public static final int settings_buffer_length_30=0x7f0800ef; + public static final int settings_buffer_length_5=0x7f0800e9; + public static final int settings_buffer_length_8=0x7f0800ea; + public static final int settings_cache_location=0x7f0800a4; + public static final int settings_cache_location_error=0x7f0800a5; + public static final int settings_cache_size=0x7f0800a3; + public static final int settings_cache_size_100=0x7f0800cc; + public static final int settings_cache_size_1000=0x7f0800cf; + public static final int settings_cache_size_10000=0x7f0800d2; + public static final int settings_cache_size_200=0x7f0800cd; + public static final int settings_cache_size_2000=0x7f0800d0; + public static final int settings_cache_size_20000=0x7f0800d3; + public static final int settings_cache_size_500=0x7f0800ce; + public static final int settings_cache_size_5000=0x7f0800d1; + public static final int settings_cache_size_unlimited=0x7f0800d4; + public static final int settings_cache_title=0x7f0800a1; + public static final int settings_clear_search_history=0x7f0800d5; + public static final int settings_connection_failure=0x7f0800a9; + public static final int settings_default_albums=0x7f080118; + public static final int settings_default_artists=0x7f080117; + public static final int settings_default_songs=0x7f080119; + public static final int settings_display_bitrate=0x7f0800c0; + public static final int settings_display_bitrate_summary=0x7f0800c1; + public static final int settings_download_transition=0x7f080100; + public static final int settings_download_transition_summary=0x7f080101; + public static final int settings_gapless_playback=0x7f080102; + public static final int settings_gapless_playback_summary=0x7f080103; + public static final int settings_hide_media_summary=0x7f0800df; + public static final int settings_hide_media_title=0x7f0800de; + public static final int settings_hide_media_toast=0x7f0800e0; + public static final int settings_increment_time=0x7f08011a; + public static final int settings_invalid_url=0x7f0800aa; + public static final int settings_invalid_username=0x7f0800ab; + public static final int settings_max_albums=0x7f080106; + public static final int settings_max_artists=0x7f080115; + public static final int settings_max_bitrate_112=0x7f0800b7; + public static final int settings_max_bitrate_128=0x7f0800b8; + public static final int settings_max_bitrate_160=0x7f0800b9; + public static final int settings_max_bitrate_192=0x7f0800ba; + public static final int settings_max_bitrate_256=0x7f0800bb; + public static final int settings_max_bitrate_32=0x7f0800b3; + public static final int settings_max_bitrate_320=0x7f0800bc; + public static final int settings_max_bitrate_64=0x7f0800b4; + public static final int settings_max_bitrate_80=0x7f0800b5; + public static final int settings_max_bitrate_96=0x7f0800b6; + public static final int settings_max_bitrate_mobile=0x7f0800b2; + public static final int settings_max_bitrate_unlimited=0x7f0800bd; + public static final int settings_max_bitrate_wifi=0x7f0800b1; + public static final int settings_max_songs=0x7f080116; + public static final int settings_media_button_summary=0x7f0800e2; + public static final int settings_media_button_title=0x7f0800e1; + public static final int settings_network_timeout=0x7f0800e6; + public static final int settings_network_timeout_105000=0x7f0800f6; + public static final int settings_network_timeout_120000=0x7f0800f7; + public static final int settings_network_timeout_15000=0x7f0800f0; + public static final int settings_network_timeout_30000=0x7f0800f1; + public static final int settings_network_timeout_45000=0x7f0800f2; + public static final int settings_network_timeout_60000=0x7f0800f3; + public static final int settings_network_timeout_75000=0x7f0800f4; + public static final int settings_network_timeout_90000=0x7f0800f5; + public static final int settings_network_title=0x7f0800b0; + public static final int settings_other_title=0x7f0800d7; + public static final int settings_playback_control_title=0x7f0800d9; + public static final int settings_preload=0x7f0800a2; + public static final int settings_preload_1=0x7f0800c6; + public static final int settings_preload_10=0x7f0800ca; + public static final int settings_preload_2=0x7f0800c7; + public static final int settings_preload_3=0x7f0800c8; + public static final int settings_preload_5=0x7f0800c9; + public static final int settings_preload_unlimited=0x7f0800cb; + public static final int settings_screen_lit_summary=0x7f0800e4; + public static final int settings_screen_lit_title=0x7f0800e3; + public static final int settings_scrobble_summary=0x7f0800db; + public static final int settings_scrobble_title=0x7f0800da; + public static final int settings_search_1=0x7f080107; + public static final int settings_search_10=0x7f08010a; + public static final int settings_search_100=0x7f080112; + public static final int settings_search_15=0x7f08010b; + public static final int settings_search_20=0x7f08010c; + public static final int settings_search_25=0x7f08010d; + public static final int settings_search_250=0x7f080113; + public static final int settings_search_3=0x7f080108; + public static final int settings_search_30=0x7f08010e; + public static final int settings_search_40=0x7f08010f; + public static final int settings_search_5=0x7f080109; + public static final int settings_search_50=0x7f080110; + public static final int settings_search_500=0x7f080114; + public static final int settings_search_75=0x7f080111; + public static final int settings_search_history_cleared=0x7f0800d6; + public static final int settings_search_title=0x7f0800d8; + public static final int settings_server_add_server=0x7f08009b; + public static final int settings_server_address=0x7f08009e; + public static final int settings_server_name=0x7f08009a; + public static final int settings_server_number=0x7f08009c; + public static final int settings_server_password=0x7f0800a0; + public static final int settings_server_remove_server=0x7f08009d; + public static final int settings_server_scaling_summary=0x7f0800dd; + public static final int settings_server_scaling_title=0x7f0800dc; + public static final int settings_server_unused=0x7f080096; + public static final int settings_server_unused1=0x7f080097; + public static final int settings_server_unused2=0x7f080098; + public static final int settings_server_unused3=0x7f080099; + public static final int settings_server_username=0x7f08009f; + public static final int settings_servers_title=0x7f080095; + public static final int settings_show_lockscreen_controls=0x7f0800fc; + public static final int settings_show_lockscreen_controls_summary=0x7f0800fd; + public static final int settings_show_notification=0x7f0800f8; + public static final int settings_show_notification_always=0x7f0800fa; + public static final int settings_show_notification_always_summary=0x7f0800fb; + public static final int settings_show_notification_summary=0x7f0800f9; + public static final int settings_show_now_playing=0x7f080104; + public static final int settings_show_now_playing_summary=0x7f080105; + public static final int settings_show_track_number=0x7f0800c4; + public static final int settings_show_track_number_summary=0x7f0800c5; + public static final int settings_test_connection_title=0x7f080094; + public static final int settings_testing_connection=0x7f0800a6; + public static final int settings_testing_ok=0x7f0800a7; + public static final int settings_testing_unlicensed=0x7f0800a8; + public static final int settings_theme_dark=0x7f0800af; + public static final int settings_theme_light=0x7f0800ae; + public static final int settings_theme_title=0x7f0800ad; + public static final int settings_title=0x7f080093; + public static final int settings_use_folder_for_album_artist=0x7f0800c2; + public static final int settings_use_folder_for_album_artist_summary=0x7f0800c3; + public static final int settings_use_id3=0x7f08011b; + public static final int settings_use_id3_summary=0x7f08011c; + public static final int settings_use_stream_proxy=0x7f0800fe; + public static final int settings_use_stream_proxy_summary=0x7f0800ff; + public static final int settings_wifi_required_summary=0x7f0800bf; + public static final int settings_wifi_required_title=0x7f0800be; + public static final int shuffle_endYear=0x7f08011e; + public static final int shuffle_genre=0x7f08011f; + public static final int shuffle_startYear=0x7f08011d; + public static final int song_details_all=0x7f08008f; + public static final int song_details_kbps=0x7f080090; + public static final int updated_playlist=0x7f08008b; + public static final int updated_playlist_error=0x7f08008c; + public static final int util_bytes_format_byte=0x7f08013b; + public static final int util_bytes_format_gigabyte=0x7f080138; + public static final int util_bytes_format_kilobyte=0x7f08013a; + public static final int util_bytes_format_megabyte=0x7f080139; + public static final int util_no_time=0x7f08013c; + public static final int util_zero_time=0x7f08013d; + public static final int widget_initial_text=0x7f080135; + public static final int widget_sdcard_busy=0x7f080136; + public static final int widget_sdcard_missing=0x7f080137; } public static final class style { public static final int MenuDrawer=0x7f0a0005; diff --git a/res/menu/select_song_context.xml b/res/menu/select_song_context.xml new file mode 100644 index 00000000..17b36400 --- /dev/null +++ b/res/menu/select_song_context.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index 2d2efe68..2e6a6099 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -12,17 +12,23 @@ Törlés Különféle előadók Többféle műfaj + Részletek + Véletlen sorrendű lejátszás + Jóváhagy + Név + Megjegyzés + Nyilvános UltraSonic főoldal Médiakönyvtár Keresés - Lejátszólisták + Lejátszási listák Lejátszó Üdvözlet! Üdvözli az UltraSonic! Az alkalmazás még nincs beállítva. Miután konfigurálta saját kiszolgálóját (elérhető: subsonic.org), húzza jobbra a képernyőt, lépjen be a Beállítások menüpontba, és adja meg csatlakozási adatokat! Kiszolgáló kiválasztása Műfaj kiválasztása Összes műfaj - Véletlenszerű sorrend + Véletlen sorrendű Kapcsolat nélküli Beállítások Előadók @@ -48,7 +54,14 @@ Keresés Navigáció Általános - Lejátszólisták + Hozzáadás a lejátszási listához + Törlés a lejátszási listáról + Törölt lejátszási lista %s + Lejátszási lista törlése sikertelen %s + Lejátszási listák + Információk frissítése + Frissített lejátszási lista információ %s + Lejátszási lista információinak frissítése sikertelen %s Súgó Üdvözli az UltraSonic! Vissza @@ -58,8 +71,8 @@ Video betöltése… Kérjük, telepítse az Adobe Flash Player-t a Play Áruházból. Keresés - Kereses - Kattintson a kereséshez + Keresés + Érintse meg a kereséshez Nincs találat, próbálja újra! Előadók Albumok @@ -68,7 +81,7 @@ Kérem várjon… Mediakönyvtár Kapcsolat nélküli médiák - Nem található média + Nem található média! Összes kijelölése %d műsorszám kijelölve. %d műsorszám visszavonva. @@ -76,37 +89,37 @@ Kapcsolat nélküli Keresés… Összes lejátszása - Hiba: SD kártya nem áll rendelkezésre. - Figyelem: Hálózat nem áll rendelkezésre. + Hiba: SD kártya nem áll rendelkezésre! + Figyelem: Hálózat nem áll rendelkezésre! A kiszolgálónak nincs licence! %d próba nap van hátra! Korlátlan letöltéshez juthat a Subsonic támogatásával. Most Később A próba időszak lejárt! - Nincsenek előadók - Nincsenek műfajok - Nincs mentett lejátszólista a kiszolgálón - A lejátszólista üres + Előadók nem találhatók! + Műfajok nem találhatók! + Nincs mentett lejátszási lista a kiszolgálón. + A lejátszási lista üres! Letöltés - %s Pufferelés - Véletlenszerű sorrend + Véletlen sorrendű Album megjelenítése Dalszövegek Dal eltávolítása Összes eltávolítása Kijelző Be Kijelző Ki - Véletlenszerű sorrend - Lejátszólista mentése + Véletlen sorrendű + Lejátszási lista mentése Equalizer Visualizer Jukebox - Véletlenszerű lejátszólista sorrend - Lejátszólista mentése - Lejátszólista neve: - Lejátszólista mentése \"%s\"… - Lejátszólista mentése sikeres. - Lejátszólista mentése sikertelen, próbálja később! + Véletlen sorrendű lejátszás + Lejátszási lista mentése + Lejátszási lista neve: + Lejátszási lista mentése \"%s\"… + Lejátszási lista mentése sikeres. + Lejátszási lista mentése sikertelen, próbálja később! Ismétlés ki Összes ismétlése Dal ismétlése @@ -118,17 +131,26 @@ A távvezérlés nem támogatott. Kérjük, frissítse a Subsonic kiszolgálót! A távvezérlés nem lehetséges kapcsolat nélküli módban! A távvezérlés nem áll rendelkezésre. Kérjük, engedélyezze a Jukebox módot a Felhasználók > Beállítások menüpontban, az Ön Subsonic kiszolgálóján! + Nem sikerült elérni a lejátszási lista adatait! + %1$s dal hozzáadva: \"%2$s\" + Frissítés sikertelen: \"%s\", próbálja később! + %1$s eltávolítva: \"%2$s\" + Biztos, hogy törölni akarja: %1$s %1$s%2$s %d kbps - Dalszöveg nem található - Hiba + Dalszöveg nem található! + Hiba! UltraSonic beállításai Kapcsolat tesztelése Kiszolgálók + Nem használt Nem használt 1 Nem használt 2 Nem használt 3 Név + Kiszolgáló hozzáadása + Kiszolgálók száma + Kiszolgáló eltávolítása Kiszolgáló címe Felhasználónév Jelszó @@ -136,7 +158,7 @@ Dalok előolvasása Gyorsítótár mérete Gyorsítótár helye - Hibás gyorsítótár hely. Az alapértelmezett használata. + Hibás gyorsítótár hely! Az alapértelmezett használata. Kapcsolat tesztelése… Kapcsolat OK Kapcsolat OK. A kiszolgálónak nincs licence! @@ -185,15 +207,15 @@ 20 GB Korlátlan Keresési előzmények törlése - Keresési előzmények törölve. + Keresési előzmények törölve Egyéb beállítások Keresés beállításai Lejátszás-vezérlés beállításai Továbbítás Last.fm-re (Scrobbling) A Last.fm felhasználónevet és jelszót be kell állítani a Subsonic kiszolgálón! Albumborító átméretezés (Kiszolgáló-oldali) - A teljes méretű helyett, átméretezett képek letöltése a kiszolgálóról (sávszélesség-takarékos). - Elrejtés más elől + A teljes méretű helyett átméretezett képek letöltése a kiszolgálóról (sávszélesség-takarékos). + Elrejtés Zenefájlok elrejtése egyéb alkalmazások elől. A következő alkalomtól lép életbe, amikor az Android zenefájlokat keres a telefonon. Média vezérlőgombok @@ -222,13 +244,17 @@ Értesítések megjelenítése Lejátszás jelzése az értesítési sávon. Állandó kijelzés - Lejátszás jelzése az értesítési sávon, míg a lejászólista aktív. + Lejátszás jelzése az értesítési sávon, míg a lejátszási lista aktív. Képernyőzár kezelése Lejátszó-kezelőpanel megjelenítése a képernyőzáron. Stream Proxy használata Média lejátszása stream proxy-n keresztül (akadozások elkerülése érdekében). - Lejátszás alatt - A lejátszás alatt álló dal mutatása minden oldalon. + Letöltés megjelenítése + Letöltési aktivitás megjelenítése a lejátszás indításakor. + Egybefüggő lejátszás + Kihagyás (dalszünet) nélküli egybefüggő lejátszás (Gapless). + Lejátszó-kezelőpanel + Lejátszó-kezelőpanel megjelenítése minden oldalon. Max. albumok 1 3 @@ -249,6 +275,12 @@ Alapértelmezett előadók Alapértelmezett albumok Alapértelmezett dalok + Ugrás időtartama + Böngésszen ID3 tag + Használja ID3 tag módszerek helyett a fájlrendszer alapú módszerek + Első év: + Utolsó év: + Műfaj: Hálózati hiba történt! Újrapróbálkozás %1$d - %2$d. Kérem várjon… Betöltés. @@ -286,24 +318,24 @@ %d dal - 1 dal kiválasztva kell csapolni. - %d dal kiválasztva kell csapolni. - + 1 dal megjelölve. + %d dal megjelölve. + - 1 dal kiválasztva a leválasztani. - %d dal kiválasztva a leválasztani. - + 1 dal megjelölése visszavonva. + %d dal megjelölése visszavonva. + - 1 dal bekerül a nap végére sor. - %d dal bekerül a nap végére sor. + 1 dal hozzáadva a lejátszási sorhoz. + %d dal hozzáadva a lejátszási sorhoz. - 1 dal egészül aktuális dalt. - %d dal egészül aktuális dalt. - + 1 dal hozzáadva következőként. + %d dal hozzáadva következőként. + 1 nap van hátra a próba időszakból. %d nap van hátra a próba időszakból. - \ No newline at end of file + diff --git a/res/values/strings.xml b/res/values/strings.xml index 020fdd69..28562516 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -17,7 +17,8 @@ Confirm Name Comment - Public + Public + Show Artist UltraSonic Main Media Library Search @@ -276,6 +277,8 @@ Default Albums Default Songs Skip Interval + Browse Using ID3 Tags + Use ID3 tag methods instead of file system based methods Start Year: End Year: Genre: diff --git a/res/xml/settings.xml b/res/xml/settings.xml index e89482f6..f584f419 100644 --- a/res/xml/settings.xml +++ b/res/xml/settings.xml @@ -37,6 +37,11 @@ a:key="showNowPlaying" a:summary="@string/settings.show_now_playing_summary" a:title="@string/settings.show_now_playing" /> + songs = new ArrayList(1); switch (menuItem.getItemId()) { case R.id.album_menu_play_now: @@ -201,6 +203,41 @@ public class SearchActivity extends SubsonicTabActivity { case R.id.album_menu_pin: downloadRecursively(id, true, true, false, false, false, false); break; + case R.id.song_menu_play_now: + if (entry != null) { + songs = new ArrayList(1); + songs.add(entry); + download(false, false, true, false, false, songs); + } + break; + case R.id.song_menu_play_next: + if (entry != null) { + songs = new ArrayList(1); + songs.add(entry); + download(true, false, false, true, false, songs); + } + break; + case R.id.song_menu_play_last: + if (entry != null) { + songs = new ArrayList(1); + songs.add(entry); + download(true, false, false, false, false, songs); + } + break; + case R.id.song_menu_pin: + if (entry != null) { + songs.add(entry); + Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size())); + downloadBackground(true, songs); + } + break; + case R.id.song_menu_unpin: + if (entry != null) { + songs.add(entry); + Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_unpinned, songs.size(), songs.size())); + getDownloadService().unpin(songs); + } + break; default: return super.onContextItemSelected(menuItem); } @@ -208,6 +245,24 @@ public class SearchActivity extends SubsonicTabActivity { return true; } + private void downloadBackground(final boolean save, final List songs) { + if (getDownloadService() == null) { + return; + } + + Runnable onValid = new Runnable() { + @Override + public void run() { + warnIfNetworkOrStorageUnavailable(); + getDownloadService().downloadBackground(songs, save); + + Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size())); + } + }; + + checkLicenseAndTrialPeriod(onValid); + } + private void search(final String query, final boolean autoplay) { final int maxArtists = Util.getMaxArtists(this); final int maxAlbums = Util.getMaxAlbums(this); @@ -218,13 +273,16 @@ public class SearchActivity extends SubsonicTabActivity { protected SearchResult doInBackground() throws Throwable { SearchCritera criteria = new SearchCritera(query, maxArtists, maxAlbums, maxSongs); MusicService service = MusicServiceFactory.getMusicService(SearchActivity.this); + licenseValid = service.isLicenseValid(SearchActivity.this, this); return service.search(criteria, SearchActivity.this, this); } @Override protected void done(SearchResult result) { searchResult = result; + populateList(); + if (autoplay) { autoplay(); } @@ -281,9 +339,11 @@ public class SearchActivity extends SubsonicTabActivity { private void expandArtists() { artistAdapter.clear(); + for (Artist artist : searchResult.getArtists()) { artistAdapter.add(artist); } + artistAdapter.notifyDataSetChanged(); mergeAdapter.removeAdapter(moreArtistsAdapter); mergeAdapter.notifyDataSetChanged(); @@ -291,9 +351,11 @@ public class SearchActivity extends SubsonicTabActivity { private void expandAlbums() { albumAdapter.clear(); + for (MusicDirectory.Entry album : searchResult.getAlbums()) { albumAdapter.add(album); } + albumAdapter.notifyDataSetChanged(); mergeAdapter.removeAdapter(moreAlbumsAdapter); mergeAdapter.notifyDataSetChanged(); @@ -301,9 +363,11 @@ public class SearchActivity extends SubsonicTabActivity { private void expandSongs() { songAdapter.clear(); + for (MusicDirectory.Entry song : searchResult.getSongs()) { songAdapter.add(song); } + songAdapter.notifyDataSetChanged(); mergeAdapter.removeAdapter(moreSongsAdapter); mergeAdapter.notifyDataSetChanged(); @@ -320,6 +384,7 @@ public class SearchActivity extends SubsonicTabActivity { Intent intent = new Intent(SearchActivity.this, SelectAlbumActivity.class); intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, album.getId()); intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle()); + intent.putExtra(Constants.INTENT_EXTRA_NAME_IS_ALBUM, album.isDirectory()); intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, autoplay); Util.startActivityWithoutTransition(SearchActivity.this, intent); } @@ -330,7 +395,9 @@ public class SearchActivity extends SubsonicTabActivity { if (!append) { downloadService.clear(); } + downloadService.download(Arrays.asList(song), save, false, playNext, false); + if (autoplay) { downloadService.play(downloadService.size() - 1); } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectAlbumActivity.java b/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectAlbumActivity.java index 237fe8da..1b14308b 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectAlbumActivity.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectAlbumActivity.java @@ -37,6 +37,7 @@ import android.widget.ListView; import android.widget.TextView; import com.thejoshwa.ultrasonic.androidapp.R; +import com.thejoshwa.ultrasonic.androidapp.domain.Artist; import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory; import com.thejoshwa.ultrasonic.androidapp.service.DownloadFile; import com.thejoshwa.ultrasonic.androidapp.service.MusicService; @@ -77,7 +78,6 @@ public class SelectAlbumActivity extends SubsonicTabActivity { private ImageView unpinButton; private ImageView deleteButton; private ImageView moreButton; - private boolean licenseValid; private boolean playAllButtonVisible; private MenuItem playAllButton; private boolean showHeader = true; @@ -114,6 +114,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity { if (entry.isDirectory()) { Intent intent = new Intent(SelectAlbumActivity.this, SelectAlbumActivity.class); intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, entry.getId()); + intent.putExtra(Constants.INTENT_EXTRA_NAME_IS_ALBUM, entry.isDirectory()); intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle()); Util.startActivityWithoutTransition(SelectAlbumActivity.this, intent); } else if (entry.isVideo()) { @@ -150,7 +151,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity { playNextButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - download(true, false, false, true, false); + download(true, false, false, true, false, getSelectedSongs(albumListView)); selectAll(false, false); } }); @@ -187,6 +188,8 @@ public class SelectAlbumActivity extends SubsonicTabActivity { enableButtons(); String id = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID); + boolean isAlbum = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_IS_ALBUM, false); + String name = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_NAME); String playlistId = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID); String playlistName = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME); @@ -212,7 +215,15 @@ public class SelectAlbumActivity extends SubsonicTabActivity { } else if (getRandomTracks != 0) { getRandom(albumListSize); } else { - getMusicDirectory(id, name); + if (!Util.isOffline(SelectAlbumActivity.this) && Util.getShouldUseId3Tags(SelectAlbumActivity.this)) { + if (isAlbum) { + getAlbum(id, name); + } else { + getArtist(id, name); + } + } else { + getMusicDirectory(id, name); + } } } @@ -235,8 +246,8 @@ public class SelectAlbumActivity extends SubsonicTabActivity { } private void playNow(final boolean shuffle, final boolean append) { - if(getSelectedSongs().size() > 0) { - download(append, false, !append, false, shuffle); + if(getSelectedSongs(albumListView).size() > 0) { + download(append, false, !append, false, shuffle, getSelectedSongs(albumListView)); selectAll(false, false); } else { @@ -263,10 +274,25 @@ public class SelectAlbumActivity extends SubsonicTabActivity { downloadRecursively(id, false, append, !append, shuffle, false, false); } else { selectAll(true, false); - download(append, false, !append, false, shuffle); + download(append, false, !append, false, shuffle, getSelectedSongs(albumListView)); selectAll(false, false); } } + + private List getSelectedSongs(ListView albumListView) { + List songs = new ArrayList(10); + + if (albumListView != null) { + int count = albumListView.getCount(); + for (int i = 0; i < count; i++) { + if (albumListView.isItemChecked(i)) { + songs.add((MusicDirectory.Entry) albumListView.getItemAtPosition(i)); + } + } + } + + return songs; + } private void refresh() { finish(); @@ -282,6 +308,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity { MusicDirectory.Entry entry = (MusicDirectory.Entry) albumListView.getItemAtPosition(info.position); + if (entry.isDirectory()) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.select_album_context, menu); @@ -292,14 +319,13 @@ public class SelectAlbumActivity extends SubsonicTabActivity { public boolean onContextItemSelected(MenuItem menuItem) { AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo(); MusicDirectory.Entry entry = (MusicDirectory.Entry) albumListView.getItemAtPosition(info.position); - List songs = new ArrayList(10); - songs.add((MusicDirectory.Entry) albumListView.getItemAtPosition(info.position)); + switch (menuItem.getItemId()) { case R.id.album_menu_play_now: downloadRecursively(entry.getId(), false, false, true, false, false, false); break; case R.id.album_menu_play_next: - downloadRecursively(entry.getId(), false, false, true, true, false, true); + downloadRecursively(entry.getId(), false, false, true, false, false, true); break; case R.id.album_menu_play_last: downloadRecursively(entry.getId(), false, true, false, false, false, false); @@ -347,6 +373,30 @@ public class SelectAlbumActivity extends SubsonicTabActivity { }.execute(); } + private void getArtist(final String id, final String name) { + getActionBar().setSubtitle(name); + + new LoadTask() { + @Override + protected MusicDirectory load(MusicService service) throws Exception { + boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false); + return service.getArtist(id, name, refresh, SelectAlbumActivity.this, this); + } + }.execute(); + } + + private void getAlbum(final String id, final String name) { + getActionBar().setSubtitle(name); + + new LoadTask() { + @Override + protected MusicDirectory load(MusicService service) throws Exception { + boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false); + return service.getAlbum(id, name, refresh, SelectAlbumActivity.this, this); + } + }.execute(); + } + private void getSongsForGenre(final String genre, final int count, final int offset) { getActionBar().setSubtitle(genre); @@ -391,7 +441,11 @@ public class SelectAlbumActivity extends SubsonicTabActivity { new LoadTask() { @Override protected MusicDirectory load(MusicService service) throws Exception { - return Util.getSongsFromSearchResult(service.getStarred(SelectAlbumActivity.this, this)); + if (Util.getShouldUseId3Tags(SelectAlbumActivity.this)) { + return Util.getSongsFromSearchResult(service.getStarred(SelectAlbumActivity.this, this)); + } else { + return Util.getSongsFromSearchResult(service.getStarred(SelectAlbumActivity.this, this)); + } } }.execute(); } @@ -426,7 +480,11 @@ public class SelectAlbumActivity extends SubsonicTabActivity { new LoadTask() { @Override protected MusicDirectory load(MusicService service) throws Exception { - return service.getAlbumList(albumListType, size, offset, SelectAlbumActivity.this, this); + if (Util.getShouldUseId3Tags(SelectAlbumActivity.this)) { + return service.getAlbumList2(albumListType, size, offset, SelectAlbumActivity.this, this); + } else { + return service.getAlbumList(albumListType, size, offset, SelectAlbumActivity.this, this); + } } @Override @@ -505,7 +563,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity { return; } - List selection = getSelectedSongs(); + List selection = getSelectedSongs(albumListView); boolean enabled = !selection.isEmpty(); boolean unpinEnabled = false; boolean deleteEnabled = false; @@ -530,62 +588,15 @@ public class SelectAlbumActivity extends SubsonicTabActivity { deleteButton.setVisibility(deleteEnabled ? View.VISIBLE : View.GONE); } - private List getSelectedSongs() { - List songs = new ArrayList(10); - int count = albumListView.getCount(); - for (int i = 0; i < count; i++) { - if (albumListView.isItemChecked(i)) { - songs.add((MusicDirectory.Entry) albumListView.getItemAtPosition(i)); - } - } - return songs; - } - - private void download(final boolean append, final boolean save, final boolean autoplay, final boolean playNext, final boolean shuffle) { - if (getDownloadService() == null) { - return; - } - - final List songs = getSelectedSongs(); - Runnable onValid = new Runnable() { - @Override - public void run() { - if (!append) { - getDownloadService().clear(); - } - - warnIfNetworkOrStorageUnavailable(); - getDownloadService().download(songs, save, autoplay, playNext, shuffle); - String playlistName = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME); - if (playlistName != null) { - getDownloadService().setSuggestedPlaylistName(playlistName); - } - - if (autoplay) { - if (Util.getShouldTransitionOnPlaybackPreference(SelectAlbumActivity.this)) { - Util.startActivityWithoutTransition(SelectAlbumActivity.this, DownloadActivity.class); - } - } else if (save) { - Util.toast(SelectAlbumActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size())); - } else if (playNext) { - Util.toast(SelectAlbumActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_play_next, songs.size(), songs.size())); - } else if (append) { - Util.toast(SelectAlbumActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_added, songs.size(), songs.size())); - } - } - }; - - checkLicenseAndTrialPeriod(onValid); - } - private void downloadBackground(final boolean save) { - List songs = getSelectedSongs(); + List songs = getSelectedSongs(albumListView); if(songs.isEmpty()) { selectAll(true, false); - songs = getSelectedSongs(); + songs = getSelectedSongs(albumListView); } downloadBackground(save, songs); } + private void downloadBackground(final boolean save, final List songs) { if (getDownloadService() == null) { return; @@ -606,10 +617,10 @@ public class SelectAlbumActivity extends SubsonicTabActivity { } private void delete() { - List songs = getSelectedSongs(); + List songs = getSelectedSongs(albumListView); if(songs.isEmpty()) { selectAll(true, false); - songs = getSelectedSongs(); + songs = getSelectedSongs(albumListView); } if (getDownloadService() != null) { getDownloadService().delete(songs); @@ -618,7 +629,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity { private void unpin() { if (getDownloadService() != null) { - List songs = getSelectedSongs(); + List songs = getSelectedSongs(albumListView); Util.toast(SelectAlbumActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_unpinned, songs.size(), songs.size())); getDownloadService().unpin(songs); } @@ -640,61 +651,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity { refresh(); } } - - private void checkLicenseAndTrialPeriod(Runnable onValid) { - if (licenseValid) { - onValid.run(); - return; - } - - int trialDaysLeft = Util.getRemainingTrialDays(this); - Log.i(TAG, trialDaysLeft + " trial days left."); - - if (trialDaysLeft == 0) { - showDonationDialog(trialDaysLeft, null); - } else if (trialDaysLeft < Constants.FREE_TRIAL_DAYS / 2) { - showDonationDialog(trialDaysLeft, onValid); - } else { - Util.toast(this, getResources().getString(R.string.select_album_not_licensed, trialDaysLeft)); - onValid.run(); - } - } - - private void showDonationDialog(int trialDaysLeft, final Runnable onValid) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setIcon(android.R.drawable.ic_dialog_info); - - if (trialDaysLeft == 0) { - builder.setTitle(R.string.select_album_donate_dialog_0_trial_days_left); - } else { - builder.setTitle(getResources().getQuantityString(R.plurals.select_album_donate_dialog_n_trial_days_left, - trialDaysLeft, trialDaysLeft)); - } - - builder.setMessage(R.string.select_album_donate_dialog_message); - - builder.setPositiveButton(R.string.select_album_donate_dialog_now, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.DONATION_URL))); - } - }); - - builder.setNegativeButton(R.string.select_album_donate_dialog_later, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - dialogInterface.dismiss(); - if (onValid != null) { - onValid.run(); - } - } - }); - - builder.create().show(); - } - + private abstract class LoadTask extends TabActivityBackgroundTask> { public LoadTask() { @@ -791,7 +748,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity { boolean playAll = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false); if (playAll && songCount > 0) { - playAll(); + playAll(getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, false), false); } } @@ -811,13 +768,10 @@ public class SelectAlbumActivity extends SubsonicTabActivity { for (MusicDirectory.Entry entry : entries) { if (!entry.isDirectory()) { if (Util.shouldUseFolderForArtistName(getBaseContext())) { - // Find the top level folder, assume it is the album artist - String path = entry.getPath(); - if (path != null) { - int slashIndex = path.indexOf("/"); - if (slashIndex != 0) { - grandParents.add(path.substring(0, slashIndex)); - } + String grandParent = Util.getGrandparent(entry.getPath()); + + if (grandParent != null) { + grandParents.add(grandParent); } } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectArtistActivity.java b/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectArtistActivity.java index 56e7c692..e9dd58d9 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectArtistActivity.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/activity/SelectArtistActivity.java @@ -128,11 +128,20 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter protected Indexes doInBackground() throws Throwable { boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false); MusicService musicService = MusicServiceFactory.getMusicService(SelectArtistActivity.this); - if (!Util.isOffline(SelectArtistActivity.this)) { + boolean isOffline = Util.isOffline(SelectArtistActivity.this); + boolean useId3Tags = Util.getShouldUseId3Tags(SelectArtistActivity.this); + + if (!isOffline && !useId3Tags) { musicFolders = musicService.getMusicFolders(refresh, SelectArtistActivity.this, this); } + String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this); - return musicService.getIndexes(musicFolderId, refresh, SelectArtistActivity.this, this); + + if (!isOffline && useId3Tags) { + return musicService.getArtists(refresh, SelectArtistActivity.this, this); + } else { + return musicService.getIndexes(musicFolderId, refresh, SelectArtistActivity.this, this); + } } @Override diff --git a/src/com/thejoshwa/ultrasonic/androidapp/activity/SubsonicTabActivity.java b/src/com/thejoshwa/ultrasonic/androidapp/activity/SubsonicTabActivity.java index 6236c4db..785587f7 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/activity/SubsonicTabActivity.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/activity/SubsonicTabActivity.java @@ -33,6 +33,7 @@ import android.content.pm.PackageInfo; import android.graphics.Bitmap; import android.graphics.PixelFormat; import android.media.AudioManager; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; @@ -46,6 +47,7 @@ import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.Window; import android.widget.ImageView; +import android.widget.ListView; import android.widget.TextView; import com.thejoshwa.ultrasonic.androidapp.R; import com.thejoshwa.ultrasonic.androidapp.domain.MusicDirectory; @@ -93,6 +95,7 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{ View playlistsMenuItem = null; View menuMain = null; public static boolean nowPlayingHidden = false; + boolean licenseValid; @Override protected void onCreate(Bundle bundle) { @@ -322,7 +325,15 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{ @Override public void onClick(View view) { Intent intent = new Intent(SubsonicTabActivity.this, SelectAlbumActivity.class); - intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, song.getParent()); + + if (Util.getShouldUseId3Tags(SubsonicTabActivity.this)) { + intent.putExtra(Constants.INTENT_EXTRA_NAME_IS_ALBUM, true); + intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, song.getAlbumId()); + } else { + intent.putExtra(Constants.INTENT_EXTRA_NAME_IS_ALBUM, false); + intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, song.getParent()); + } + intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, song.getAlbum()); Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent); } @@ -417,6 +428,43 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{ } return IMAGE_LOADER; } + + void download(final boolean append, final boolean save, final boolean autoplay, final boolean playNext, final boolean shuffle, final List songs) { + if (getDownloadService() == null) { + return; + } + + Runnable onValid = new Runnable() { + @Override + public void run() { + if (!append) { + getDownloadService().clear(); + } + + warnIfNetworkOrStorageUnavailable(); + getDownloadService().download(songs, save, autoplay, playNext, shuffle); + String playlistName = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME); + if (playlistName != null) { + getDownloadService().setSuggestedPlaylistName(playlistName); + } + + if (autoplay) { + if (Util.getShouldTransitionOnPlaybackPreference(SubsonicTabActivity.this)) { + Util.startActivityWithoutTransition(SubsonicTabActivity.this, DownloadActivity.class); + } + } else if (save) { + Util.toast(SubsonicTabActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size())); + } else if (playNext) { + Util.toast(SubsonicTabActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_play_next, songs.size(), songs.size())); + } else if (append) { + Util.toast(SubsonicTabActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_added, songs.size(), songs.size())); + } + } + }; + + checkLicenseAndTrialPeriod(onValid); + } + protected void downloadRecursively(final String id, final boolean save, final boolean append, final boolean autoplay, final boolean shuffle, final boolean background, final boolean playNext) { downloadRecursively(id, "", true, save, append, autoplay, shuffle, background, playNext); @@ -432,10 +480,17 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{ protected List doInBackground() throws Throwable { MusicService musicService = MusicServiceFactory.getMusicService(SubsonicTabActivity.this); MusicDirectory root; - if(isDirectory) - root = musicService.getMusicDirectory(id, name, false, SubsonicTabActivity.this, this); - else + + if(isDirectory) { + if (Util.getShouldUseId3Tags(SubsonicTabActivity.this)) { + root = musicService.getAlbum(id, name, false, SubsonicTabActivity.this, this); + } else { + root = musicService.getMusicDirectory(id, name, false, SubsonicTabActivity.this, this); + } + } else { root = musicService.getPlaylist(id, name, SubsonicTabActivity.this, this); + } + List songs = new LinkedList(); getSongsRecursively(root, songs); return songs; @@ -451,9 +506,18 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{ songs.add(song); } } + for (MusicDirectory.Entry dir : parent.getChildren(true, false)) { MusicService musicService = MusicServiceFactory.getMusicService(SubsonicTabActivity.this); - getSongsRecursively(musicService.getMusicDirectory(dir.getId(), dir.getTitle(), false, SubsonicTabActivity.this, this), songs); + MusicDirectory root; + + if (Util.getShouldUseId3Tags(SubsonicTabActivity.this)) { + root = musicService.getAlbum(dir.getId(), dir.getTitle(), false, SubsonicTabActivity.this, this); + } else { + root = musicService.getMusicDirectory(dir.getId(), dir.getTitle(), false, SubsonicTabActivity.this, this); + } + + getSongsRecursively(root, songs); } } @@ -531,7 +595,7 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{ @Override protected Void doInBackground() throws Throwable { MusicService musicService = MusicServiceFactory.getMusicService(SubsonicTabActivity.this); - musicService.addToPlaylist(playlist.getId(), songs, SubsonicTabActivity.this, null); + musicService.updatePlaylist(playlist.getId(), songs, SubsonicTabActivity.this, null); return null; } @@ -553,6 +617,61 @@ public class SubsonicTabActivity extends Activity implements OnClickListener{ } }.execute(); } + + protected void checkLicenseAndTrialPeriod(Runnable onValid) { + if (licenseValid) { + onValid.run(); + return; + } + + int trialDaysLeft = Util.getRemainingTrialDays(this); + Log.i(TAG, trialDaysLeft + " trial days left."); + + if (trialDaysLeft == 0) { + showDonationDialog(trialDaysLeft, null); + } else if (trialDaysLeft < Constants.FREE_TRIAL_DAYS / 2) { + showDonationDialog(trialDaysLeft, onValid); + } else { + Util.toast(this, getResources().getString(R.string.select_album_not_licensed, trialDaysLeft)); + onValid.run(); + } + } + + private void showDonationDialog(int trialDaysLeft, final Runnable onValid) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setIcon(android.R.drawable.ic_dialog_info); + + if (trialDaysLeft == 0) { + builder.setTitle(R.string.select_album_donate_dialog_0_trial_days_left); + } else { + builder.setTitle(getResources().getQuantityString(R.plurals.select_album_donate_dialog_n_trial_days_left, + trialDaysLeft, trialDaysLeft)); + } + + builder.setMessage(R.string.select_album_donate_dialog_message); + + builder.setPositiveButton(R.string.select_album_donate_dialog_now, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.DONATION_URL))); + } + }); + + builder.setNegativeButton(R.string.select_album_donate_dialog_later, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dialogInterface.dismiss(); + if (onValid != null) { + onValid.run(); + } + } + }); + + builder.create().show(); + } + private void setUncaughtExceptionHandler() { Thread.UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler(); diff --git a/src/com/thejoshwa/ultrasonic/androidapp/domain/Artist.java b/src/com/thejoshwa/ultrasonic/androidapp/domain/Artist.java index 879e3e89..a47765c1 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/domain/Artist.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/domain/Artist.java @@ -32,6 +32,8 @@ public class Artist implements Serializable { private String id; private String name; private String index; + private String coverArt; + private Long albumCount; private int closeness; public String getId() { @@ -58,6 +60,22 @@ public class Artist implements Serializable { this.index = index; } + public String getCoverArt() { + return coverArt; + } + + public void setCoverArt(String coverArt) { + this.coverArt = coverArt; + } + + public long getAlbumCount() { + return albumCount; + } + + public void setAlbumCount(Long albumCount) { + this.albumCount = albumCount; + } + public int getCloseness() { return closeness; } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/domain/MusicDirectory.java b/src/com/thejoshwa/ultrasonic/androidapp/domain/MusicDirectory.java index facdd579..68883772 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/domain/MusicDirectory.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/domain/MusicDirectory.java @@ -18,8 +18,12 @@ */ package com.thejoshwa.ultrasonic.androidapp.domain; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; +import java.util.Locale; import java.io.Serializable; /** @@ -70,10 +74,12 @@ public class MusicDirectory { */ private String id; private String parent; - private boolean directory; + private boolean isDirectory; private String title; private String album; + private String albumId; private String artist; + private String artistId; private Integer track; private Integer year; private String genre; @@ -83,12 +89,15 @@ public class MusicDirectory { private String transcodedSuffix; private String coverArt; private Long size; + private Long songCount; private Integer duration; private Integer bitRate; private String path; - private boolean video; - private boolean starred; + private boolean isVideo; + private boolean isStarred; private Integer discNumber; + private String type; + private Date created; private int closeness; public Integer getDiscNumber() { @@ -100,11 +109,11 @@ public class MusicDirectory { } public boolean getStarred() { - return starred; + return isStarred; } public void setStarred(boolean starred) { - this.starred = starred; + this.isStarred = starred; } public String getId() { @@ -124,11 +133,11 @@ public class MusicDirectory { } public boolean isDirectory() { - return directory; + return isDirectory; } - public void setDirectory(boolean directory) { - this.directory = directory; + public void setIsDirectory(boolean directory) { + this.isDirectory = directory; } public String getTitle() { @@ -146,6 +155,14 @@ public class MusicDirectory { public void setAlbum(String album) { this.album = album; } + + public String getAlbumId() { + return albumId; + } + + public void setAlbumId(String albumId) { + this.albumId = albumId; + } public String getArtist() { return artist; @@ -154,6 +171,14 @@ public class MusicDirectory { public void setArtist(String artist) { this.artist = artist; } + + public String getArtistId() { + return artistId; + } + + public void setArtistId(String artistId) { + this.artistId = artistId; + } public Integer getTrack() { return track == null ? 0 : track; @@ -162,6 +187,14 @@ public class MusicDirectory { public void setTrack(Integer track) { this.track = track; } + + public Long getSongcount() { + return songCount; + } + + public void setSongCount(Long songCount) { + this.songCount = songCount; + } public Integer getYear() { return year == null ? 0 : year; @@ -256,11 +289,35 @@ public class MusicDirectory { } public boolean isVideo() { - return video; + return isVideo; } - public void setVideo(boolean video) { - this.video = video; + public void setIsVideo(boolean video) { + this.isVideo = video; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Date getCreated() { + return created; + } + + public void setCreated(String created) { + if (created != null) { + try { + this.created = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(created); + } catch (ParseException e) { + this.created = null; + } + } else { + this.created = null; + } } public int getCloseness() { diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/CachedMusicService.java b/src/com/thejoshwa/ultrasonic/androidapp/service/CachedMusicService.java index 6d62e76f..02a453a5 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/CachedMusicService.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/CachedMusicService.java @@ -52,8 +52,11 @@ public class CachedMusicService implements MusicService { private final MusicService musicService; private final LRUCache> cachedMusicDirectories; + private final LRUCache> cachedArtist; + private final LRUCache> cachedAlbum; private final TimeLimitedCache cachedLicenseValid = new TimeLimitedCache(120, TimeUnit.SECONDS); private final TimeLimitedCache cachedIndexes = new TimeLimitedCache(60 * 60, TimeUnit.SECONDS); + private final TimeLimitedCache cachedArtists = new TimeLimitedCache(60 * 60, TimeUnit.SECONDS); private final TimeLimitedCache> cachedPlaylists = new TimeLimitedCache>(3600, TimeUnit.SECONDS); private final TimeLimitedCache> cachedMusicFolders = new TimeLimitedCache>(10 * 3600, TimeUnit.SECONDS); private final TimeLimitedCache> cachedGenres = new TimeLimitedCache>(10 * 3600, TimeUnit.SECONDS); @@ -62,6 +65,8 @@ public class CachedMusicService implements MusicService { public CachedMusicService(MusicService musicService) { this.musicService = musicService; cachedMusicDirectories = new LRUCache>(MUSIC_DIR_CACHE_SIZE); + cachedArtist = new LRUCache>(MUSIC_DIR_CACHE_SIZE); + cachedAlbum = new LRUCache>(MUSIC_DIR_CACHE_SIZE); } @Override @@ -110,6 +115,20 @@ public class CachedMusicService implements MusicService { } return result; } + + @Override + public Indexes getArtists(boolean refresh, Context context, ProgressListener progressListener) throws Exception { + checkSettingsChanged(context); + if (refresh) { + cachedArtists.clear(); + } + Indexes result = cachedArtists.get(); + if (result == null) { + result = musicService.getArtists(refresh, context, progressListener); + cachedArtists.set(result); + } + return result; + } @Override public MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception { @@ -124,6 +143,34 @@ public class CachedMusicService implements MusicService { } return dir; } + + @Override + public MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception { + checkSettingsChanged(context); + TimeLimitedCache cache = refresh ? null : cachedArtist.get(id); + MusicDirectory dir = cache == null ? null : cache.get(); + if (dir == null) { + dir = musicService.getArtist(id, name, refresh, context, progressListener); + cache = new TimeLimitedCache(TTL_MUSIC_DIR, TimeUnit.SECONDS); + cache.set(dir); + cachedArtist.put(id, cache); + } + return dir; + } + + @Override + public MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception { + checkSettingsChanged(context); + TimeLimitedCache cache = refresh ? null : cachedAlbum.get(id); + MusicDirectory dir = cache == null ? null : cache.get(); + if (dir == null) { + dir = musicService.getAlbum(id, name, refresh, context, progressListener); + cache = new TimeLimitedCache(TTL_MUSIC_DIR, TimeUnit.SECONDS); + cache.set(dir); + cachedAlbum.put(id, cache); + } + return dir; + } @Override public SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception { @@ -158,8 +205,8 @@ public class CachedMusicService implements MusicService { } @Override - public void addToPlaylist(String id, List toAdd, Context context, ProgressListener progressListener) throws Exception { - musicService.addToPlaylist(id, toAdd, context, progressListener); + public void updatePlaylist(String id, List toAdd, Context context, ProgressListener progressListener) throws Exception { + musicService.updatePlaylist(id, toAdd, context, progressListener); } @Override @@ -186,6 +233,11 @@ public class CachedMusicService implements MusicService { public MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception { return musicService.getAlbumList(type, size, offset, context, progressListener); } + + @Override + public MusicDirectory getAlbumList2(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception { + return musicService.getAlbumList2(type, size, offset, context, progressListener); + } @Override public MusicDirectory getRandomSongs(int size, Context context, ProgressListener progressListener) throws Exception { @@ -196,6 +248,11 @@ public class CachedMusicService implements MusicService { public SearchResult getStarred(Context context, ProgressListener progressListener) throws Exception { return musicService.getStarred(context, progressListener); } + + @Override + public SearchResult getStarred2(Context context, ProgressListener progressListener) throws Exception { + return musicService.getStarred2(context, progressListener); + } @Override public Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, ProgressListener progressListener) throws Exception { @@ -270,14 +327,14 @@ public class CachedMusicService implements MusicService { } @Override - public void star(String id, Context context, ProgressListener progressListener) throws Exception { - musicService.star(id, context, progressListener); + public void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception { + musicService.star(id, albumId, artistId, context, progressListener); } @Override - public void unstar(String id, Context context, ProgressListener progressListener) throws Exception { - musicService.unstar(id, context, progressListener); + public void unstar(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception { + musicService.unstar(id, albumId, artistId, context, progressListener); } @Override diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/MusicService.java b/src/com/thejoshwa/ultrasonic/androidapp/service/MusicService.java index afd3cbc5..6576a48e 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/MusicService.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/MusicService.java @@ -49,15 +49,21 @@ public interface MusicService { List getGenres(Context context, ProgressListener progressListener) throws Exception; - void star(String id, Context context, ProgressListener progressListener) throws Exception; + void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception; - void unstar(String id, Context context, ProgressListener progressListener) throws Exception; + void unstar(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception; List getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception; Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception; + + Indexes getArtists(boolean refresh, Context context, ProgressListener progressListener) throws Exception; MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception; + + MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception; + + MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception; SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception; @@ -69,7 +75,7 @@ public interface MusicService { void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception; - void addToPlaylist(String id, List toAdd, Context context, ProgressListener progressListener) throws Exception; + void updatePlaylist(String id, List toAdd, Context context, ProgressListener progressListener) throws Exception; void removeFromPlaylist(String id, List toRemove, Context context, ProgressListener progressListener) throws Exception; @@ -80,12 +86,16 @@ public interface MusicService { void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception; MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception; + + MusicDirectory getAlbumList2(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception; MusicDirectory getRandomSongs(int size, Context context, ProgressListener progressListener) throws Exception; MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception; SearchResult getStarred(Context context, ProgressListener progressListener) throws Exception; + + SearchResult getStarred2(Context context, ProgressListener progressListener) throws Exception; Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, boolean saveToFile, ProgressListener progressListener) throws Exception; diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/OfflineMusicService.java b/src/com/thejoshwa/ultrasonic/androidapp/service/OfflineMusicService.java index 0e3a5c23..b9592c99 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/OfflineMusicService.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/OfflineMusicService.java @@ -124,7 +124,7 @@ public class OfflineMusicService extends RESTMusicService { private MusicDirectory.Entry createEntry(Context context, File file, String name) { MusicDirectory.Entry entry = new MusicDirectory.Entry(); - entry.setDirectory(file.isDirectory()); + entry.setIsDirectory(file.isDirectory()); entry.setId(file.getPath()); entry.setParent(file.getParent()); entry.setSize(file.length()); @@ -168,7 +168,7 @@ public class OfflineMusicService extends RESTMusicService { entry.setTitle(title); } - entry.setVideo(hasVideo != null); + entry.setIsVideo(hasVideo != null); Log.i("OfflineMusicService", "Offline Stuff: " + track); @@ -266,12 +266,12 @@ public class OfflineMusicService extends RESTMusicService { } @Override - public void star(String id, Context context, ProgressListener progressListener) throws Exception { + public void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception { throw new OfflineException("Star not available in offline mode"); } @Override - public void unstar(String id, Context context, ProgressListener progressListener) throws Exception { + public void unstar(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception { throw new OfflineException("UnStar not available in offline mode"); } @@ -467,7 +467,7 @@ public class OfflineMusicService extends RESTMusicService { } @Override - public void addToPlaylist(String id, List toAdd, Context context, ProgressListener progressListener) throws Exception { + public void updatePlaylist(String id, List toAdd, Context context, ProgressListener progressListener) throws Exception { throw new OfflineException("Updating playlist not available in offline mode"); } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/RESTMusicService.java b/src/com/thejoshwa/ultrasonic/androidapp/service/RESTMusicService.java index 64da1577..3f11c0d8 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/RESTMusicService.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/RESTMusicService.java @@ -61,8 +61,6 @@ import org.apache.http.params.HttpParams; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.ExecutionContext; import org.apache.http.protocol.HttpContext; -import org.xmlpull.v1.XmlPullParser; - import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageInfo; @@ -71,7 +69,6 @@ import android.graphics.BitmapFactory; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.util.Log; -import android.util.Xml; import com.thejoshwa.ultrasonic.androidapp.R; import com.thejoshwa.ultrasonic.androidapp.domain.Genre; import com.thejoshwa.ultrasonic.androidapp.domain.Indexes; @@ -263,6 +260,47 @@ public class RESTMusicService implements MusicService { return "indexes-" + Math.abs(s.hashCode()) + ".ser"; } + @Override + public Indexes getArtists(boolean refresh, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.8", "Artists by ID3 tag not supported."); + + Indexes cachedArtists = readCachedArtists(context); + if (cachedArtists != null && !refresh) { + return cachedArtists; + } + + Reader reader = getReader(context, progressListener, "getArtists", null); + try { + Indexes indexes = new IndexesParser(context).parse(reader, progressListener); + if (indexes != null) { + writeCachedArtists(context, indexes); + return indexes; + } + if(cachedArtists != null) { + return cachedArtists; + } else { + return new Indexes(0, new ArrayList(), new ArrayList()); + } + } finally { + Util.close(reader); + } + } + + private Indexes readCachedArtists(Context context) { + String filename = getCachedArtistsFilename(context); + return FileUtil.deserialize(context, filename); + } + + private void writeCachedArtists(Context context, Indexes artists) { + String filename = getCachedArtistsFilename(context); + FileUtil.serialize(context, artists, filename); + } + + private String getCachedArtistsFilename(Context context) { + String s = Util.getRestUrl(context, null); + return "indexes-" + Math.abs(s.hashCode()) + ".ser"; + } + private ArrayList readCachedMusicFolders(Context context) { String filename = getCachedMusicFoldersFilename(context); return FileUtil.deserialize(context, filename); @@ -278,8 +316,28 @@ public class RESTMusicService implements MusicService { return "musicFolders-" + Math.abs(s.hashCode()) + ".ser"; } - public void star(String id, Context context, ProgressListener progressListener) throws Exception { - Reader reader = getReader(context, progressListener, "star", null, "id", id); + public void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.8", "Starring not supported."); + + List parameterNames = new LinkedList(); + List parameterValues = new LinkedList(); + + if (id != null) { + parameterNames.add("id"); + parameterValues.add(id); + } + + if (albumId != null) { + parameterNames.add("albumId"); + parameterValues.add(albumId); + } + + if (artistId != null) { + parameterNames.add("artistId"); + parameterValues.add(artistId); + } + + Reader reader = getReader(context, progressListener, "star", null, parameterNames, parameterValues); try { new ErrorParser(context).parse(reader); } finally { @@ -287,8 +345,29 @@ public class RESTMusicService implements MusicService { } } - public void unstar(String id, Context context, ProgressListener progressListener) throws Exception { - Reader reader = getReader(context, progressListener, "unstar", null, "id", id); + public void unstar(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.8", "Unstarring not supported."); + + List parameterNames = new LinkedList(); + List parameterValues = new LinkedList(); + + if (id != null) { + parameterNames.add("id"); + parameterValues.add(id); + } + + if (albumId != null) { + parameterNames.add("albumId"); + parameterValues.add(albumId); + } + + if (artistId != null) { + parameterNames.add("artistId"); + parameterValues.add(artistId); + } + + + Reader reader = getReader(context, progressListener, "unstar", null, parameterNames, parameterValues); try { new ErrorParser(context).parse(reader); } finally { @@ -300,7 +379,31 @@ public class RESTMusicService implements MusicService { public MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception { Reader reader = getReader(context, progressListener, "getMusicDirectory", null, "id", id); try { - return new MusicDirectoryParser(context).parse(name, reader, progressListener); + return new MusicDirectoryParser(context).parse(name, reader, progressListener, false); + } finally { + Util.close(reader); + } + } + + @Override + public MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.8", "Artist by ID3 tag not supported."); + + Reader reader = getReader(context, progressListener, "getArtist", null, "id", id); + try { + return new MusicDirectoryParser(context).parse(name, reader, progressListener, false); + } finally { + Util.close(reader); + } + } + + @Override + public MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.8", "Album by ID3 tag not supported."); + + Reader reader = getReader(context, progressListener, "getAlbum", null, "id", id); + try { + return new MusicDirectoryParser(context).parse(name, reader, progressListener, true); } finally { Util.close(reader); } @@ -309,7 +412,11 @@ public class RESTMusicService implements MusicService { @Override public SearchResult search(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception { try { - return searchNew(critera, context, progressListener); + if (!Util.isOffline(context) && Util.getShouldUseId3Tags(context)) { + return search3(critera, context, progressListener); + } else { + return search2(critera, context, progressListener); + } } catch (ServerTooOldException x) { // Ensure backward compatibility with REST 1.3. return searchOld(critera, context, progressListener); @@ -333,15 +440,29 @@ public class RESTMusicService implements MusicService { /** * Search using the "search2" REST method, available in 1.4.0 and later. */ - private SearchResult searchNew(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception { - checkServerVersion(context, "1.4", null); + private SearchResult search2(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.4", "Search2 not supported."); List parameterNames = Arrays.asList("query", "artistCount", "albumCount", "songCount"); List parameterValues = Arrays.asList(critera.getQuery(), critera.getArtistCount(), critera.getAlbumCount(), critera.getSongCount()); Reader reader = getReader(context, progressListener, "search2", null, parameterNames, parameterValues); try { - return new SearchResult2Parser(context).parse(reader, progressListener); + return new SearchResult2Parser(context).parse(reader, progressListener, false); + } finally { + Util.close(reader); + } + } + + private SearchResult search3(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.8", "Searching by ID3 tag not supported."); + + List parameterNames = Arrays.asList("query", "artistCount", "albumCount", "songCount"); + List parameterValues = Arrays.asList(critera.getQuery(), critera.getArtistCount(), + critera.getAlbumCount(), critera.getSongCount()); + Reader reader = getReader(context, progressListener, "search3", null, parameterNames, parameterValues); + try { + return new SearchResult2Parser(context).parse(reader, progressListener, true); } finally { Util.close(reader); } @@ -395,6 +516,8 @@ public class RESTMusicService implements MusicService { @Override public void createPlaylist(String id, String name, List entries, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.2", "Creating playlist not supported."); + List parameterNames = new LinkedList(); List parameterValues = new LinkedList(); @@ -420,7 +543,9 @@ public class RESTMusicService implements MusicService { } @Override - public void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception { + public void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.2", "Deleting playlist not supported."); + Reader reader = getReader(context, progressListener, "deletePlaylist", null, "id", id); try { new ErrorParser(context).parse(reader); @@ -430,8 +555,9 @@ public class RESTMusicService implements MusicService { } @Override - public void addToPlaylist(String id, List toAdd, Context context, ProgressListener progressListener) throws Exception { - checkServerVersion(context, "1.8", "Updating playlists is not supported."); + public void updatePlaylist(String id, List toAdd, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.8", "Updating playlist not supported."); + List names = new ArrayList(); List values = new ArrayList(); names.add("playlistId"); @@ -450,7 +576,8 @@ public class RESTMusicService implements MusicService { @Override public void removeFromPlaylist(String id, List toRemove, Context context, ProgressListener progressListener) throws Exception { - checkServerVersion(context, "1.8", "Updating playlists is not supported."); + checkServerVersion(context, "1.8", "Removing from playlist not supported."); + List names = new ArrayList(); List values = new ArrayList(); names.add("playlistId"); @@ -469,7 +596,7 @@ public class RESTMusicService implements MusicService { @Override public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception { - checkServerVersion(context, "1.8", "Updating playlists is not supported."); + checkServerVersion(context, "1.8", "Updating playlist not supported."); Reader reader = getReader(context, progressListener, "updatePlaylist", null, Arrays.asList("playlistId", "name", "comment", "public"), Arrays.asList(id, name, comment, pub)); try { new ErrorParser(context).parse(reader); @@ -480,6 +607,8 @@ public class RESTMusicService implements MusicService { @Override public Lyrics getLyrics(String artist, String title, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.2", "Lyrics not supported."); + Reader reader = getReader(context, progressListener, "getLyrics", null, Arrays.asList("artist", "title"), Arrays.asList(artist, title)); try { return new LyricsParser(context).parse(reader, progressListener); @@ -491,6 +620,7 @@ public class RESTMusicService implements MusicService { @Override public void scrobble(String id, boolean submission, Context context, ProgressListener progressListener) throws Exception { checkServerVersion(context, "1.5", "Scrobbling not supported."); + Reader reader = getReader(context, progressListener, "scrobble", null, Arrays.asList("id", "submission"), Arrays.asList(id, submission)); try { new ErrorParser(context).parse(reader); @@ -501,10 +631,25 @@ public class RESTMusicService implements MusicService { @Override public MusicDirectory getAlbumList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.2", "Album list not supported."); + Reader reader = getReader(context, progressListener, "getAlbumList", null, Arrays.asList("type", "size", "offset"), Arrays.asList(type, size, offset)); try { - return new AlbumListParser(context).parse(reader, progressListener); + return new AlbumListParser(context).parse(reader, progressListener, false); + } finally { + Util.close(reader); + } + } + + @Override + public MusicDirectory getAlbumList2(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.8", "Album list by ID3 tag not supported."); + + Reader reader = getReader(context, progressListener, "getAlbumList2", + null, Arrays.asList("type", "size", "offset"), Arrays.asList(type, size, offset)); + try { + return new AlbumListParser(context).parse(reader, progressListener, true); } finally { Util.close(reader); } @@ -512,6 +657,8 @@ public class RESTMusicService implements MusicService { @Override public MusicDirectory getRandomSongs(int size, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.2", "Random songs not supported."); + HttpParams params = new BasicHttpParams(); HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_RANDOM_SONGS); @@ -531,9 +678,23 @@ public class RESTMusicService implements MusicService { @Override public SearchResult getStarred(Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.8", "Starred albums not supported."); + Reader reader = getReader(context, progressListener, "getStarred", null); try { - return new SearchResult2Parser(context).parse(reader, progressListener); + return new SearchResult2Parser(context).parse(reader, progressListener, false); + } finally { + Util.close(reader); + } + } + + @Override + public SearchResult getStarred2(Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.8", "Starred albums by ID3 tag not supported."); + + Reader reader = getReader(context, progressListener, "getStarred2", null); + try { + return new SearchResult2Parser(context).parse(reader, progressListener, true); } finally { Util.close(reader); } @@ -948,6 +1109,7 @@ public class RESTMusicService implements MusicService { @Override public List getGenres(Context context, ProgressListener progressListener) throws Exception { checkServerVersion(context, "1.9", "Genres not supported."); + Reader reader = getReader(context, progressListener, "getGenres", null); try { return new GenreParser(context).parse(reader, progressListener); @@ -959,6 +1121,7 @@ public class RESTMusicService implements MusicService { @Override public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception { checkServerVersion(context, "1.9", "Genres not supported."); + HttpParams params = new BasicHttpParams(); HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_RANDOM_SONGS); diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/AlbumListParser.java b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/AlbumListParser.java index 871aafd3..1a968cfc 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/AlbumListParser.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/AlbumListParser.java @@ -35,7 +35,7 @@ public class AlbumListParser extends MusicDirectoryEntryParser { super(context); } - public MusicDirectory parse(Reader reader, ProgressListener progressListener) throws Exception { + public MusicDirectory parse(Reader reader, ProgressListener progressListener, boolean useId3) throws Exception { updateProgress(progressListener, R.string.parser_reading); init(reader); @@ -47,7 +47,7 @@ public class AlbumListParser extends MusicDirectoryEntryParser { if (eventType == XmlPullParser.START_TAG) { String name = getElementName(); if ("album".equals(name)) { - dir.addChild(parseEntry("")); + dir.addChild(parseEntry("", useId3)); } else if ("error".equals(name)) { handleError(); } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/IndexesParser.java b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/IndexesParser.java index f7b6eef6..8a1ffb7e 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/IndexesParser.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/IndexesParser.java @@ -50,6 +50,7 @@ public class IndexesParser extends AbstractParser { List artists = new ArrayList(); List shortcuts = new ArrayList(); Long lastModified = null; + String ignoredArticles = null; int eventType; String index = "#"; boolean changed = false; @@ -58,9 +59,10 @@ public class IndexesParser extends AbstractParser { eventType = nextParseEvent(); if (eventType == XmlPullParser.START_TAG) { String name = getElementName(); - if ("indexes".equals(name)) { + if ("indexes".equals(name) || "artists".equals(name)) { changed = true; lastModified = getLong("lastModified"); + ignoredArticles = get("ignoredArticles"); } else if ("index".equals(name)) { index = get("name"); @@ -68,6 +70,8 @@ public class IndexesParser extends AbstractParser { Artist artist = new Artist(); artist.setId(get("id")); artist.setName(get("name")); + artist.setCoverArt(get("coverArt")); + artist.setAlbumCount(getLong("albumCount")); artist.setIndex(index); artists.add(artist); diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/MusicDirectoryEntryParser.java b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/MusicDirectoryEntryParser.java index 2b5ddea2..2a9a492d 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/MusicDirectoryEntryParser.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/MusicDirectoryEntryParser.java @@ -31,19 +31,22 @@ public class MusicDirectoryEntryParser extends AbstractParser { super(context); } - protected MusicDirectory.Entry parseEntry(String artist) { + protected MusicDirectory.Entry parseEntry(String artist, boolean isAlbum) { MusicDirectory.Entry entry = new MusicDirectory.Entry(); entry.setId(get("id")); entry.setParent(get("parent")); - entry.setTitle(get("title")); - entry.setDirectory(getBoolean("isDir")); + entry.setTitle(isAlbum ? get("name") : get("title")); + entry.setIsDirectory(getBoolean("isDir") || isAlbum); entry.setCoverArt(get("coverArt")); entry.setArtist(get("artist")); + entry.setArtistId(get("artistId")); entry.setYear(getInteger("year")); + entry.setCreated(get("created")); entry.setStarred(getValueExists(Constants.STARRED)); if (!entry.isDirectory()) { entry.setAlbum(get("album")); + entry.setAlbumId(get("albumId")); entry.setTrack(getInteger("track")); entry.setGenre(get("genre")); entry.setContentType(get("contentType")); @@ -54,8 +57,9 @@ public class MusicDirectoryEntryParser extends AbstractParser { entry.setDuration(getInteger("duration")); entry.setBitRate(getInteger("bitRate")); entry.setPath(get("path")); - entry.setVideo(getBoolean("isVideo")); + entry.setIsVideo(getBoolean("isVideo")); entry.setDiscNumber(getInteger("discNumber")); + entry.setType(get("type")); } else if(!"".equals(artist)) { entry.setPath(artist + "/" + entry.getTitle()); } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/MusicDirectoryParser.java b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/MusicDirectoryParser.java index c9d08e51..cdfcd27f 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/MusicDirectoryParser.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/MusicDirectoryParser.java @@ -37,7 +37,7 @@ public class MusicDirectoryParser extends MusicDirectoryEntryParser { super(context); } - public MusicDirectory parse(String artist, Reader reader, ProgressListener progressListener) throws Exception { + public MusicDirectory parse(String artist, Reader reader, ProgressListener progressListener, boolean isAlbum) throws Exception { long t0 = System.currentTimeMillis(); updateProgress(progressListener, R.string.parser_reading); @@ -49,9 +49,12 @@ public class MusicDirectoryParser extends MusicDirectoryEntryParser { eventType = nextParseEvent(); if (eventType == XmlPullParser.START_TAG) { String name = getElementName(); - if ("child".equals(name)) { - dir.addChild(parseEntry(artist)); - } else if ("directory".equals(name)) { + + if ("child".equals(name) || "song".equals(name)) { + dir.addChild(parseEntry(artist, false)); + } else if ("album".equals(name) && !isAlbum) { + dir.addChild(parseEntry(artist, true)); + } else if ("directory".equals(name) || "artist".equals(name)) { dir.setName(get("name")); } else if ("error".equals(name)) { handleError(); diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/PlaylistParser.java b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/PlaylistParser.java index e2bcc4f9..9c0d9ec5 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/PlaylistParser.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/PlaylistParser.java @@ -46,7 +46,7 @@ public class PlaylistParser extends MusicDirectoryEntryParser { if (eventType == XmlPullParser.START_TAG) { String name = getElementName(); if ("entry".equals(name)) { - dir.addChild(parseEntry("")); + dir.addChild(parseEntry("", false)); } else if ("error".equals(name)) { handleError(); } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/RandomSongsParser.java b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/RandomSongsParser.java index 81704629..247d929d 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/RandomSongsParser.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/RandomSongsParser.java @@ -46,7 +46,7 @@ public class RandomSongsParser extends MusicDirectoryEntryParser { if (eventType == XmlPullParser.START_TAG) { String name = getElementName(); if ("song".equals(name)) { - dir.addChild(parseEntry("")); + dir.addChild(parseEntry("", false)); } else if ("error".equals(name)) { handleError(); } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/SearchResult2Parser.java b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/SearchResult2Parser.java index 49dd5ede..2665d0c3 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/SearchResult2Parser.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/SearchResult2Parser.java @@ -39,7 +39,7 @@ public class SearchResult2Parser extends MusicDirectoryEntryParser { super(context); } - public SearchResult parse(Reader reader, ProgressListener progressListener) throws Exception { + public SearchResult parse(Reader reader, ProgressListener progressListener, boolean useId3) throws Exception { updateProgress(progressListener, R.string.parser_reading); init(reader); @@ -57,9 +57,9 @@ public class SearchResult2Parser extends MusicDirectoryEntryParser { artist.setName(get("name")); artists.add(artist); } else if ("album".equals(name)) { - albums.add(parseEntry("")); + albums.add(parseEntry("", useId3)); } else if ("song".equals(name)) { - songs.add(parseEntry("")); + songs.add(parseEntry("", false)); } else if ("error".equals(name)) { handleError(); } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/SearchResultParser.java b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/SearchResultParser.java index db953758..d685d5d0 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/service/parser/SearchResultParser.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/service/parser/SearchResultParser.java @@ -51,7 +51,7 @@ public class SearchResultParser extends MusicDirectoryEntryParser { if (eventType == XmlPullParser.START_TAG) { String name = getElementName(); if ("match".equals(name)) { - songs.add(parseEntry("")); + songs.add(parseEntry("", false)); } else if ("error".equals(name)) { handleError(); } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/util/Constants.java b/src/com/thejoshwa/ultrasonic/androidapp/util/Constants.java index d0542b02..1ff8d4ec 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/util/Constants.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/util/Constants.java @@ -53,6 +53,7 @@ public final class Constants { public static final String INTENT_EXTRA_NAME_STARRED = "subsonic.starred"; public static final String INTENT_EXTRA_NAME_RANDOM = "subsonic.random"; public static final String INTENT_EXTRA_NAME_GENRE_NAME = "subsonic.genre"; + public static final String INTENT_EXTRA_NAME_IS_ALBUM = "subsonic.isalbum"; // Notification IDs. public static final int NOTIFICATION_ID_PLAYING = 100; @@ -113,6 +114,7 @@ public final class Constants { public static final String PREFERENCES_EQUALIZER_SETTINGS = "equalizerSettings"; public static final String PREFERENCES_KEY_DOWNLOAD_TRANSITION = "transitionToDownloadOnPlay"; public static final String PREFERENCES_KEY_INCREMENT_TIME = "incrementTime"; + public static final String PREFERENCES_KEY_ID3_TAGS = "useId3Tags"; // Name of the preferences file. public static final String PREFERENCES_FILE_NAME = "com.thejoshwa.ultrasonic.androidapp_preferences"; @@ -121,7 +123,7 @@ public final class Constants { public static final int FREE_TRIAL_DAYS = 30; // URL for project donations. - public static final String DONATION_URL = "http://subsonic.org/pages/android-donation.jsp"; + public static final String DONATION_URL = "http://www.subsonic.org/pages/premium.jsp"; public static final String ALBUM_ART_FILE = "folder.jpeg"; public static final String STARRED = "starred"; diff --git a/src/com/thejoshwa/ultrasonic/androidapp/util/Util.java b/src/com/thejoshwa/ultrasonic/androidapp/util/Util.java index d22eaf51..62a827a4 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/util/Util.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/util/Util.java @@ -644,6 +644,18 @@ public class Util extends DownloadActivity { throw new RuntimeException(x.getMessage(), x); } } + + public static String getGrandparent(final String path) { + // Find the top level folder, assume it is the album artist + if (path != null) { + int slashIndex = path.indexOf("/"); + if (slashIndex != 0) { + return path.substring(0, slashIndex); + } + } + + return null; + } public static boolean isNetworkConnected(Context context) { ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); @@ -1197,4 +1209,9 @@ public class Util extends DownloadActivity { SharedPreferences prefs = getPreferences(context); return prefs.getBoolean(Constants.PREFERENCES_KEY_DOWNLOAD_TRANSITION, true); } + + public static boolean getShouldUseId3Tags(Context context) { + SharedPreferences prefs = getPreferences(context); + return prefs.getBoolean(Constants.PREFERENCES_KEY_ID3_TAGS, false); + } } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/view/AlbumView.java b/src/com/thejoshwa/ultrasonic/androidapp/view/AlbumView.java index 653c19f9..e5823b2b 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/view/AlbumView.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/view/AlbumView.java @@ -82,12 +82,13 @@ public class AlbumView extends UpdateView { new Thread(new Runnable() { public void run() { MusicService musicService = MusicServiceFactory.getMusicService(null); + boolean useId3 = Util.getShouldUseId3Tags(getContext()); try { if (!isStarred) { - musicService.star(id, getContext(), null); + musicService.star(!useId3 ? id : null, useId3 ? id : null, null, getContext(), null); } else { - musicService.unstar(id, getContext(), null); + musicService.unstar(!useId3 ? id : null, useId3 ? id : null, null, getContext(), null); } } catch (Exception e) { Log.e(TAG, e.getMessage(), e); diff --git a/src/com/thejoshwa/ultrasonic/androidapp/view/ArtistAdapter.java b/src/com/thejoshwa/ultrasonic/androidapp/view/ArtistAdapter.java index a79c9a00..bda3f12e 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/view/ArtistAdapter.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/view/ArtistAdapter.java @@ -43,9 +43,11 @@ public class ArtistAdapter extends ArrayAdapter implements SectionIndexe Set sectionSet = new LinkedHashSet(30); List positionList = new ArrayList(30); + for (int i = 0; i < artists.size(); i++) { Artist artist = artists.get(i); String index = artist.getIndex(); + if (!sectionSet.contains(index)) { sectionSet.add(index); positionList.add(i); diff --git a/src/com/thejoshwa/ultrasonic/androidapp/view/GenreAdapter.java b/src/com/thejoshwa/ultrasonic/androidapp/view/GenreAdapter.java index 451f8606..acc4a929 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/view/GenreAdapter.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/view/GenreAdapter.java @@ -43,6 +43,7 @@ public class GenreAdapter extends ArrayAdapter implements SectionIndexer Set sectionSet = new LinkedHashSet(30); List positionList = new ArrayList(30); + for (int i = 0; i < genres.size(); i++) { Genre genre = genres.get(i); String index = genre.getIndex(); @@ -51,6 +52,7 @@ public class GenreAdapter extends ArrayAdapter implements SectionIndexer positionList.add(i); } } + sections = sectionSet.toArray(new Object[sectionSet.size()]); positions = positionList.toArray(new Integer[positionList.size()]); } diff --git a/src/com/thejoshwa/ultrasonic/androidapp/view/SongView.java b/src/com/thejoshwa/ultrasonic/androidapp/view/SongView.java index 4a98f0a5..5a93dfb7 100644 --- a/src/com/thejoshwa/ultrasonic/androidapp/view/SongView.java +++ b/src/com/thejoshwa/ultrasonic/androidapp/view/SongView.java @@ -132,9 +132,9 @@ public class SongView extends UpdateView implements Checkable { try { if (!isStarred) { - musicService.star(id, getContext(), null); + musicService.star(id, null, null, getContext(), null); } else { - musicService.unstar(id, getContext(), null); + musicService.unstar(id, null, null, getContext(), null); } } catch (Exception e) { Log.e(TAG, e.getMessage(), e);