From 12f0d7625e4192fbcbbc966920633e678254d0c0 Mon Sep 17 00:00:00 2001 From: Collins Mucho <72305974+sleepchild@users.noreply.github.com> Date: Thu, 13 Jan 2022 11:26:48 +0200 Subject: [PATCH] update-20220113 --- aupod/AndroidManifest.xml | 60 +++ aupod/libs/mp3agic-0.8.1.jar | Bin 0 -> 78595 bytes aupod/res/drawable/fallback_cover.png | Bin 0 -> 178 bytes .../res/drawable/ic_dashboard_black_24dp.png | Bin 0 -> 187 bytes .../drawable/ic_format_paint_black_24dp.png | Bin 0 -> 201 bytes aupod/res/drawable/ic_headset_black_24dp.png | Bin 0 -> 545 bytes .../ic_keyboard_arrow_left_black_24dp.png | Bin 0 -> 259 bytes aupod/res/drawable/ic_launcher.png | Bin 0 -> 6081 bytes aupod/res/drawable/ic_launcher2.png | Bin 0 -> 2672 bytes .../res/drawable/ic_more_vert_black_24dp.png | Bin 0 -> 239 bytes aupod/res/drawable/ic_next.png | Bin 0 -> 1536 bytes aupod/res/drawable/ic_next_24px.png | Bin 0 -> 652 bytes aupod/res/drawable/ic_pause.png | Bin 0 -> 855 bytes aupod/res/drawable/ic_pause_24px.png | Bin 0 -> 417 bytes aupod/res/drawable/ic_play.png | Bin 0 -> 1557 bytes aupod/res/drawable/ic_play_24px.png | Bin 0 -> 524 bytes aupod/res/drawable/ic_prev.png | Bin 0 -> 1316 bytes aupod/res/drawable/ic_prev_24px.png | Bin 0 -> 646 bytes aupod/res/drawable/ic_save_white_24dp.png | Bin 0 -> 359 bytes aupod/res/drawable/ic_search_black_24dp.png | Bin 0 -> 576 bytes aupod/res/drawable/ic_search_white_moss.png | Bin 0 -> 325 bytes aupod/res/drawable/ic_settings.png | Bin 0 -> 737 bytes aupod/res/drawable/ic_settings_black_24dp.png | Bin 0 -> 691 bytes aupod/res/drawable/scrollbar_v_thumb.xml | 11 + aupod/res/drawable/scrollbar_v_track.xml | 8 + aupod/res/layout/activity_auplayer.xml | 218 ++++++++++ aupod/res/layout/activity_main.xml | 230 +++++++++++ aupod/res/layout/activity_settings.xml | 76 ++++ aupod/res/layout/activity_tageditor.xml | 227 +++++++++++ aupod/res/layout/customview_ibutton.xml | 20 + aupod/res/layout/customview_settingsitem.xml | 36 ++ aupod/res/layout/customview_tabview.xml | 39 ++ aupod/res/layout/dlg_auplayer_options.xml | 6 + aupod/res/layout/dlg_songitem_options.xml | 109 +++++ aupod/res/layout/iplayer.xml | 16 + aupod/res/layout/list_view.xml | 13 + aupod/res/layout/notificationlayout.xml | 37 ++ aupod/res/layout/songlist_item.xml | 73 ++++ aupod/res/layout/tabtitle.xml | 23 ++ aupod/res/values-v21/styles.xml | 21 + aupod/res/values/attrs.xml | 15 + aupod/res/values/colors.xml | 17 + aupod/res/values/strings.xml | 4 + aupod/res/values/styles.xml | 21 + aupod/res/values/tabview_attrs.xml | 8 + aupod/src/sleepchild/aupod22/App.java | 23 ++ aupod/src/sleepchild/aupod22/AudioPlayer.java | 120 ++++++ .../src/sleepchild/aupod22/AudioService.java | 375 ++++++++++++++++++ aupod/src/sleepchild/aupod22/PlayQueue.java | 16 + aupod/src/sleepchild/aupod22/Playlist.java | 5 + aupod/src/sleepchild/aupod22/SearchPanel.java | 115 ++++++ .../aupod22/activity/BaseActivity.java | 61 +++ .../aupod22/activity/IntentActivity.java | 29 ++ .../aupod22/activity/MainActivity.java | 211 ++++++++++ .../aupod22/activity/PlayerActivity.java | 292 ++++++++++++++ .../aupod22/activity/SettingsActivity.java | 43 ++ .../aupod22/activity/TagEditorActivity.java | 244 ++++++++++++ .../aupod22/adapters/ArtistsListAdapter.java | 85 ++++ .../aupod22/adapters/SongListAdaptor.java | 135 +++++++ .../aupod22/library/MediaStoreUpdator.java | 33 ++ .../aupod22/library/SongFactory.java | 178 +++++++++ .../aupod22/library/SongLibrary.java | 103 +++++ .../aupod22/library/SongRetreiverCursor.java | 58 +++ .../src/sleepchild/aupod22/library/test.java | 50 +++ .../aupod22/menu/ArtisItemOptions.java | 20 + .../aupod22/menu/ConfirmDeleteDialog.java | 42 ++ .../aupod22/menu/CurrentSongOptions.java | 32 ++ .../sleepchild/aupod22/menu/SongOptions.java | 119 ++++++ .../aupod22/models/PlaybackRequest.java | 24 ++ .../sleepchild/aupod22/models/SongItem.java | 24 ++ .../models/events/AudioServiceConnect.java | 10 + .../models/events/SongChangedEvent.java | 13 + .../models/events/SongCompletionEvent.java | 15 + .../models/events/SongInfoChangedEvent.java | 11 + .../aupod22/models/events/SongPauseEvent.java | 11 + .../models/events/SongResumeEvent.java | 11 + .../models/events/SongsListReadyEvent.java | 12 + .../aupod22/recievers/ButtonReciever.java | 30 ++ .../sleepchild/aupod22/tabs/AlbumsTab.java | 24 ++ .../sleepchild/aupod22/tabs/ArtistTab.java | 66 +++ .../sleepchild/aupod22/tabs/PlaylistsTab.java | 25 ++ .../sleepchild/aupod22/tabs/SongsListTab.java | 79 ++++ .../aupod22/tasks/UpdateSongListTask.java | 62 +++ .../sleepchild/aupod22/utils/FastBlur.java | 214 ++++++++++ .../src/sleepchild/aupod22/utils/Noteaf.java | 63 +++ .../src/sleepchild/aupod22/utils/SPrefs.java | 99 +++++ .../aupod22/utils/SearchHelper.java | 65 +++ .../aupod22/utils/SearchResult.java | 8 + aupod/src/sleepchild/aupod22/utils/Utils.java | 39 ++ aupod/src/sleepchild/postman/PostEvent.java | 11 + aupod/src/sleepchild/postman/PostMan.java | 149 +++++++ aupod/src/sleepchild/view/ColorTextView.java | 5 + .../src/sleepchild/view/ContainerLayout.java | 49 +++ .../src/sleepchild/view/RoundedImageView.java | 73 ++++ .../sleepchild/view/RoundedLinearLayout.java | 109 +++++ aupod/src/sleepchild/view/SettingsItem.java | 115 ++++++ .../src/sleepchild/view/TintedImageView.java | 61 +++ aupod/src/sleepchild/view/Util.java | 11 + aupod/src/sleepchild/view/tabview/Tab.java | 17 + .../src/sleepchild/view/tabview/TabView.java | 135 +++++++ 100 files changed, 5317 insertions(+) create mode 100644 aupod/AndroidManifest.xml create mode 100644 aupod/libs/mp3agic-0.8.1.jar create mode 100644 aupod/res/drawable/fallback_cover.png create mode 100644 aupod/res/drawable/ic_dashboard_black_24dp.png create mode 100644 aupod/res/drawable/ic_format_paint_black_24dp.png create mode 100644 aupod/res/drawable/ic_headset_black_24dp.png create mode 100644 aupod/res/drawable/ic_keyboard_arrow_left_black_24dp.png create mode 100644 aupod/res/drawable/ic_launcher.png create mode 100644 aupod/res/drawable/ic_launcher2.png create mode 100644 aupod/res/drawable/ic_more_vert_black_24dp.png create mode 100644 aupod/res/drawable/ic_next.png create mode 100644 aupod/res/drawable/ic_next_24px.png create mode 100644 aupod/res/drawable/ic_pause.png create mode 100644 aupod/res/drawable/ic_pause_24px.png create mode 100644 aupod/res/drawable/ic_play.png create mode 100644 aupod/res/drawable/ic_play_24px.png create mode 100644 aupod/res/drawable/ic_prev.png create mode 100644 aupod/res/drawable/ic_prev_24px.png create mode 100644 aupod/res/drawable/ic_save_white_24dp.png create mode 100644 aupod/res/drawable/ic_search_black_24dp.png create mode 100644 aupod/res/drawable/ic_search_white_moss.png create mode 100644 aupod/res/drawable/ic_settings.png create mode 100644 aupod/res/drawable/ic_settings_black_24dp.png create mode 100644 aupod/res/drawable/scrollbar_v_thumb.xml create mode 100644 aupod/res/drawable/scrollbar_v_track.xml create mode 100644 aupod/res/layout/activity_auplayer.xml create mode 100644 aupod/res/layout/activity_main.xml create mode 100644 aupod/res/layout/activity_settings.xml create mode 100644 aupod/res/layout/activity_tageditor.xml create mode 100644 aupod/res/layout/customview_ibutton.xml create mode 100644 aupod/res/layout/customview_settingsitem.xml create mode 100644 aupod/res/layout/customview_tabview.xml create mode 100644 aupod/res/layout/dlg_auplayer_options.xml create mode 100644 aupod/res/layout/dlg_songitem_options.xml create mode 100644 aupod/res/layout/iplayer.xml create mode 100644 aupod/res/layout/list_view.xml create mode 100644 aupod/res/layout/notificationlayout.xml create mode 100644 aupod/res/layout/songlist_item.xml create mode 100644 aupod/res/layout/tabtitle.xml create mode 100644 aupod/res/values-v21/styles.xml create mode 100644 aupod/res/values/attrs.xml create mode 100644 aupod/res/values/colors.xml create mode 100644 aupod/res/values/strings.xml create mode 100644 aupod/res/values/styles.xml create mode 100644 aupod/res/values/tabview_attrs.xml create mode 100644 aupod/src/sleepchild/aupod22/App.java create mode 100644 aupod/src/sleepchild/aupod22/AudioPlayer.java create mode 100644 aupod/src/sleepchild/aupod22/AudioService.java create mode 100644 aupod/src/sleepchild/aupod22/PlayQueue.java create mode 100644 aupod/src/sleepchild/aupod22/Playlist.java create mode 100644 aupod/src/sleepchild/aupod22/SearchPanel.java create mode 100644 aupod/src/sleepchild/aupod22/activity/BaseActivity.java create mode 100644 aupod/src/sleepchild/aupod22/activity/IntentActivity.java create mode 100644 aupod/src/sleepchild/aupod22/activity/MainActivity.java create mode 100644 aupod/src/sleepchild/aupod22/activity/PlayerActivity.java create mode 100644 aupod/src/sleepchild/aupod22/activity/SettingsActivity.java create mode 100644 aupod/src/sleepchild/aupod22/activity/TagEditorActivity.java create mode 100644 aupod/src/sleepchild/aupod22/adapters/ArtistsListAdapter.java create mode 100644 aupod/src/sleepchild/aupod22/adapters/SongListAdaptor.java create mode 100644 aupod/src/sleepchild/aupod22/library/MediaStoreUpdator.java create mode 100644 aupod/src/sleepchild/aupod22/library/SongFactory.java create mode 100644 aupod/src/sleepchild/aupod22/library/SongLibrary.java create mode 100644 aupod/src/sleepchild/aupod22/library/SongRetreiverCursor.java create mode 100644 aupod/src/sleepchild/aupod22/library/test.java create mode 100644 aupod/src/sleepchild/aupod22/menu/ArtisItemOptions.java create mode 100644 aupod/src/sleepchild/aupod22/menu/ConfirmDeleteDialog.java create mode 100644 aupod/src/sleepchild/aupod22/menu/CurrentSongOptions.java create mode 100644 aupod/src/sleepchild/aupod22/menu/SongOptions.java create mode 100644 aupod/src/sleepchild/aupod22/models/PlaybackRequest.java create mode 100644 aupod/src/sleepchild/aupod22/models/SongItem.java create mode 100644 aupod/src/sleepchild/aupod22/models/events/AudioServiceConnect.java create mode 100644 aupod/src/sleepchild/aupod22/models/events/SongChangedEvent.java create mode 100644 aupod/src/sleepchild/aupod22/models/events/SongCompletionEvent.java create mode 100644 aupod/src/sleepchild/aupod22/models/events/SongInfoChangedEvent.java create mode 100644 aupod/src/sleepchild/aupod22/models/events/SongPauseEvent.java create mode 100644 aupod/src/sleepchild/aupod22/models/events/SongResumeEvent.java create mode 100644 aupod/src/sleepchild/aupod22/models/events/SongsListReadyEvent.java create mode 100644 aupod/src/sleepchild/aupod22/recievers/ButtonReciever.java create mode 100644 aupod/src/sleepchild/aupod22/tabs/AlbumsTab.java create mode 100644 aupod/src/sleepchild/aupod22/tabs/ArtistTab.java create mode 100644 aupod/src/sleepchild/aupod22/tabs/PlaylistsTab.java create mode 100644 aupod/src/sleepchild/aupod22/tabs/SongsListTab.java create mode 100644 aupod/src/sleepchild/aupod22/tasks/UpdateSongListTask.java create mode 100644 aupod/src/sleepchild/aupod22/utils/FastBlur.java create mode 100644 aupod/src/sleepchild/aupod22/utils/Noteaf.java create mode 100644 aupod/src/sleepchild/aupod22/utils/SPrefs.java create mode 100644 aupod/src/sleepchild/aupod22/utils/SearchHelper.java create mode 100644 aupod/src/sleepchild/aupod22/utils/SearchResult.java create mode 100644 aupod/src/sleepchild/aupod22/utils/Utils.java create mode 100644 aupod/src/sleepchild/postman/PostEvent.java create mode 100644 aupod/src/sleepchild/postman/PostMan.java create mode 100644 aupod/src/sleepchild/view/ColorTextView.java create mode 100644 aupod/src/sleepchild/view/ContainerLayout.java create mode 100644 aupod/src/sleepchild/view/RoundedImageView.java create mode 100644 aupod/src/sleepchild/view/RoundedLinearLayout.java create mode 100644 aupod/src/sleepchild/view/SettingsItem.java create mode 100644 aupod/src/sleepchild/view/TintedImageView.java create mode 100644 aupod/src/sleepchild/view/Util.java create mode 100644 aupod/src/sleepchild/view/tabview/Tab.java create mode 100644 aupod/src/sleepchild/view/tabview/TabView.java diff --git a/aupod/AndroidManifest.xml b/aupod/AndroidManifest.xml new file mode 100644 index 0000000..90c065e --- /dev/null +++ b/aupod/AndroidManifest.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aupod/libs/mp3agic-0.8.1.jar b/aupod/libs/mp3agic-0.8.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..b2827c4ad0ba50abf6515899cef93a75e7f9b992 GIT binary patch literal 78595 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 Ho*n6b(Ne|l literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/fallback_cover.png b/aupod/res/drawable/fallback_cover.png new file mode 100644 index 0000000000000000000000000000000000000000..708d9b952884642e9a135d92d4ae2a1c511985e6 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeK3?y%aJ*@^(oCO|{#S9F5M?jcysy3fAP>?Oa zC&U#+K|CI}G zOtk!TLZ&*!&(`l;eTeYaDd%o;O;p^Hq2#$_aYdQ=`FHcCt60|a9hG!2Zb)M| z%P@;^OZKDPtKP3WKka@4K+RotV>gTe~DWM4fH*Q17 literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/ic_format_paint_black_24dp.png b/aupod/res/drawable/ic_format_paint_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..5d8fac64ce51042737a63484a6b1fb5873086473 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmSQK*5Dp-y;YjHK@*6x|978f1 z-(EY&)u1525ZL?g|Mb^l9Io0+9$(tCxm{N5V$hQM)s4o-KWIixoT+zvg=U&z!?s7V z6-CzBzj!4aq74^J>)W1iv_X&U!nXr6*X=)<^U^$lLAQu~(FFTokc!`*`1VMCnz!VB u1EUFZ2HORm1(FWN4QUK#8D=p~ick;EV~z;;7Ul(X3xlVtpUXO@geCy5Ku9eB literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/ic_headset_black_24dp.png b/aupod/res/drawable/ic_headset_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..1dc89f1203a5bf6f82eb59ae421edd9270c33fe5 GIT binary patch literal 545 zcmV++0^a?JP)004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN zS#tmY3ljhU3ljkVnw%H_00EgvL_t(o!|j$$FGE2Th952U(OPPSSg2a)j<9N%;^QBP z{syt&&nU6sCuq`@kW?co8qz45SlEh{q*9@^nLEAo&i!gF%007~{DH_d2D|Jeo~y%P>ek5_}j5xrJ^*~#vM!U%!k;wG}p#1gHG)u zTFSP{* z>;am&&k(d!hsa9(j=hu9wC}UEp*|gA(fZt1WO9PGYZj7;DqG!)lq~J6qf@sa%e`hU z)NXCs@x9S1cV;Gv$#Wld449VpVp9Lv_f51c=2I8Hu?o2#E(U;vn2%ijTry%#ssV9X z2{(}!^Nd>ZBC;5E1sD~ppVg9gAqltw^o!Lsbw_JB>T|7Ou-^CEJ-Pbq#eE+K(OzS9`_rr0n+X56Bv+k^$6sS4| jRJmZoWjFW2i$5M;X>j;Ani@Km00000NkvXXu0mjfAXMtx literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/ic_keyboard_arrow_left_black_24dp.png b/aupod/res/drawable/ic_keyboard_arrow_left_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..23ef6d65af26ebab5f93b29f8eb08f50a54ab033 GIT binary patch literal 259 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 Hu0mjfDXy-& literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/ic_launcher2.png b/aupod/res/drawable/ic_launcher2.png new file mode 100644 index 0000000000000000000000000000000000000000..a8e8beb0b7cc9e3a8bb50c28ebceb2adb567dc94 GIT binary patch literal 2672 zcmV-$3Xk=PP)nPUsvcz=s-0G>OSLXYT|jgMWl_8wOkc3V49TE~C%e?neFvcXju*~-lhva_u-rxJad++bw7X-$0 z#q-QreKMv}L2@J^3P(^X9dY#t(x_098WEDBv5H2ihj<^+c$r1Us))U>)Ln@TtfZSz z!t5<5G_h3ffc{lXvN9qwt*NG%{`$^ANmJK=ytP+GGBY8!wDk^(x+ThMh>Vmi_^U5} zEIy1H06U7ikwK^I0VTLB4WLs#@uSmbu*?Yg@?0o_TyD2Gr?^K(Awf-3=io^}TEJC8 zn>B8lsRe z07g`inTNGeo*Tp1>u`t@-PLYvj%zw8Y>`6z-NsJzZ%K0tbrC<^y`KmWLI6Df%$D3EhO?qXRjRhs+?0VP#tMfw+e|@>SOFF0s&)VwtgDwy{0box) zm}Qo9X1%NBcs^M}b#1;>)md0Cj(HX5cUIe8tpGUDMKj$QCOQAuJJrfigA*aY2)$0i zw!wwMRKEgE{qF(5vW+zb=_vb)pV34(gXvsxP>zJK_5ct~yP6 z9^lI4eKd2;?DQUh840D2uYBe5J8$O1Wt)&wl^{UV=JUheU}j9lot_@ggGc*3z}k$W z6-3FKKG<@l=JB&b-oIBDcn5%6RN<;QQ!OrD-NLq+sHczV_$c z$h~^F9pR3DjTN%3S8MQ7(6#u@Qut$rptks^ugiM?I0uS1E%UWJacb=p>xq2&H=egc zah(K`KAj8;Q(wb{jVxfC6$$B zZDo0mmD`L2KIYaN@N+hWKLy*unV*|MGN^>ePbT5pZoce*S5;z2UgNA&O;u|@Y`9oe zl7G<4Zx{eZi5Zs4S5IQSEk<%+tlwh+oD|9g-^ny+>>7a8rv>ou7_VWqSbXqP{q>p& zPAu(h?v(}9oCv7GPrze8H+tP1+r*d^PUFkaw78+^;1_2Fuxkkeg4yP{^nsu1APA-9 zt7quWBZu$Qi>^Oyj};ydIE4d1t8US`^{)Oz`TS^4VJLv_?NSAZNHF!rXeAFT#p0@|a9FD#$v$LdFS^wg6UFeJr~H7<4LpHP0UZcqD?Cl-(%% zTYk%a9Kgnp?2g5*WR5z8illNVs_R4PKtDPH0$`(+HNcq$=m=%lM{NPD4&Zg81R{T| zgZq0`3>91Y2;R}Z*Y{ukrR^Yog%xRXf;n#l zp9MR>H;YtNR#yP4gIIpD0@6Nr22V%TZPrKdwq336$t&sEiU)Ckv+s+bW;qk>R~Gi*Fyl9eeui1Hj!e&a~Ge5yv!PCe8P0Q2X}KbwJ<yx3cBdTzXEj};sbOvfeM_LOjJ zt&xJ~hr9{RfAA}G8ofg8#I6w2&I2W9Uf{;i&27|=L(^eRg7;xUX-}(kAfP(=gX-ai zW@aL<@Wytx02hKY&z)I9$Sp*JSkk6Hh)wNa`7}11T1%WOJ{O1pyJFY3y}fcn1W$=t z`|?87uW0WQgc%+N;C_I+VX?R6$&7U_gj>ppYkbHl)R#t?5ISQrq z;cnn)rJC*x5xknV{;o%5q6mJ9-?euDVE_2X7QeX@!C~s7v6`M_vhOV^SCNQNUuwwxO--;2uk5gV_&%Czqh?b@v6LO8>hRo&A zE}^qXTSE*=22d(dD*-+_S-=(t8X0lF9A+IU0|z>_r=~+XpPwA~Urjwa$Lm3dOScEHOq0=pt3e!TG>+=q6MUp} zP%Kqk;2rY|*Cwa;1;>Vq!gVH8()qJrx)7^CVJqMco6 z244Xr<#cU#o^T9k3S!yG&VDeL!!Qnv3vsgI5acyP!B(Oy^zhw=j+!=U;Zv^nV$E!$ zOAnzFP~VKcep+c}M9!G&VQv|TzUXGzk1af~7ab=bGH eh>A3g!}=dxNFL#WL*8Kk0000+}rLn02ponpv!KtX`zxvAr)%D|d%gB4pdn-U~B)%vWVLd%aso{1MuvdsTE z`)AzOfGMW-GgYb&-e5T!cVRDUrLar2pJ722WQ%mvv4FO#n?ePdoqs literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/ic_next.png b/aupod/res/drawable/ic_next.png new file mode 100644 index 0000000000000000000000000000000000000000..9ed64fecce9ce641bdd9ed06c9a9dedd842c5dae GIT binary patch literal 1536 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 Hu0mjf!D!;& literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/ic_play_24px.png b/aupod/res/drawable/ic_play_24px.png new file mode 100644 index 0000000000000000000000000000000000000000..497b9c84d0308cee8339d7374d9a93ba970517fa GIT binary patch literal 524 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaAtq$-Badj{70WyaKxbpDqF`z>& zOM?7@8QjjWaK)+B$v zV6t=hcePB09V^e2&g7E4>~s60?fLSY;Ou9eYox`P9HuQiz2w|?!_XhG3wOjnbzb>1 zhReGpVWqCd!zSO!neUn&u5em0Cp_U5>wlHLXN=b`o_({WSLwxBk4^Wcb|j|PT3+Lq zIAC`4ytiOPAJ-Xo8HS2Ge)DY{?3k}NOEH-4-Bp=f JS?83{1ORLqo6i6M literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/ic_prev.png b/aupod/res/drawable/ic_prev.png new file mode 100644 index 0000000000000000000000000000000000000000..87a394ffcf0c98b2903976dc35778e1b118a27e0 GIT binary patch literal 1316 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+yeRz?d4~6XNP#-~$vH1vCwTEv_qd zfEJXM1o;IsTx1vG|116b-=Di5oVFxr+qRqt9 zCu`)67B zq<^;+!*AaWQ(ClYqRZ;r>rPFsEbmekow0CQm+bX-(TcJb&iuJMi}=rdKRdfOYHv{A z@zYbQ)?R$mK8N3G*Y9E}DXrEIO22CiV*(1CPX9dq`#kG~EVKOwW=Eem|0pFPuV=Tp z>%DohKZWY2tx2^xoffU#?F&r=eW@SS-dXGgy#}( zV?NBW)V_Rbp6N_>4&EoJvLb%}?^?KPB(yG;*t@b}U(PAlhC>s6AKM$+?A*tz`AmaB z#CIc$z_#D^s&khnUR+g{YH)}_RX9YnMEZY4Ip^|wwFPqZk*$w3WUtgUtzz)K_Wz;s zmfkh`oj z5=E>WcoS|5L@|`U{;J*bZ5%b}1AI?1g!&xF^KhI$`|L+i?_;=Q76B`5HO+0H_<#F)GvkQ!F(TaPIiXOaZuFW7* zJN=m0q`gzV^PNy~lD*s>xMQi!9UsR{t!#PUegk=Dk7PcNF7FZBRW|d70oVGuJ6nq8 zA6U5l+rqRdiB1oLXO(~7el*Fxe&u70T$Yvh_BnmjSbW2?RAg=bn)x=hUe7emqQvh< zv}`x~cs8`6THHQ?L%#3`f8?X%HV>PZ{Rj;Ivq87+j`;oppNFTE>t4<}v^Aeg{JdsN c?f<7gm=lAn7Wc;0serP%r>mdKI;Vst08$Lc82|tP literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/ic_prev_24px.png b/aupod/res/drawable/ic_prev_24px.png new file mode 100644 index 0000000000000000000000000000000000000000..f47b6e2cc0235862543416fe1a93522ca40a24ca GIT binary patch literal 646 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaAy$bLNadj{70WwDdm=gap59m+d zk|4iehOfBgVeZ;JtXI(xgf6Ry&JI&DKl_DlGo= z<>x=M@AKI+KOcE_m-$xh+i6Wl^2`#J_A_sr^|Im0)PU(8@z#GAzVP?{&y&9IJmc2@ Vk%%WglB+>U$FUAnJhAibi%P z{*n$w1{(ziyIyvi533K%R25`o{zs_2v-=N#*|yls-=vKzMeEt<;LvBqHy zGn2MJo#2KIOr3lu);O$VmRiRD_W7y%B4uZ+-hO`-cyWW0nu?0z`<=D=1(SMq{j%IJ zk>RKS_X%5ex4+s~X8mfO9=zrDZ_{hcUAve*?KrXY(x;;hK(8`*y85}Sb4q9e0E^az A761SM literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/ic_search_black_24dp.png b/aupod/res/drawable/ic_search_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..a2d894f4168a38076b1c079537e860fb8cc60c95 GIT binary patch literal 576 zcmV-G0>Ax004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN zS#tmY3ljhU3ljkVnw%H_00Fp3L_t(o!|j*PZUI3Y$G;auanQ4iKi85TL_|XR9E6u> z(?7Ijy@CtrYY1t|5?blKk$3<+0}|Uqe>+yXb~~ffq{;r~WasnyeP(9OP6lwo3Au5O zItEx`jWw1~p&;>l#V_y*&7_TyJHGe{o=l7Dtp)EfzK?|)^wX(FX*8a{)uRNme&W1JWaG)>b~GQ0~# zL{tgJaOY6Pw=U2MKP5^sq7Ld6eo9C-q6)?mzb7S{xDCV>zb7V{cxH;oGJnwE6`snzq_;_H3Oz}!mr~X( z3^h*3mRg^9Q^D X!t01FroTla00000NkvXXu0mjfimrX< literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/ic_settings.png b/aupod/res/drawable/ic_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..12e5d100dd80ca03315f8d15af6289c3db015327 GIT binary patch literal 737 zcmV<70v`Q|P)004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN zS#tmY3ljhU3ljkVnw%H_00LP_L_t(o!{wOIYZFlr$0xNhfhN^PB<61QP-zeTfPz1; z^dQxPr5C}!K?FUt)`L*6MGt!LRCWH-_|9`s9Bn=AF69nLToD#$tcrfQw2R&clt z?Jgx4ZbNGd=9r>Nk%`tk!#!$fQe%ms7H)zf-3#A zMO5-qBbW&=`pPULBuH?KIZ6TOX)nQf>OKZ}23)5jMZpJM=bUy-$F1*`C+11Wn3duS zr)+tUWkubb0Yn*T$_n}!2mKPQp9db3S=GHD%zLo++2fzdg0N{AjaUgr4W#46csp93 zY#W-S)GbMsl%GbQj`#LfL70Bfkj>C_|EMvq1{1{Pkz@?rB`bmXuj#Dh2rdWEd*6rEAeH9$d4v}Fsr#JEN<>Dyikq>Z;<_H98*skj_azRJuqN|GdF z+*UVdr(D#wXf?8O{ala1@rWAEHe z8?~_0z4vCfm-XgC-*S!p%uw;&4u@%mxX!!QbuAuLt}jp_&*|2D9}E0Yoo{i6!4~c; zPjQ$Gx;pBkXlbM&Y{Ql7^)|E}^@E-hthJ&2H&@^&AFVI6{?+Mc?5_S-(Q|^oR4iHa T4YrnW00000NkvXXu0mjftyfGA literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/ic_settings_black_24dp.png b/aupod/res/drawable/ic_settings_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..2b775b64659e4cef4afc79b8e0b6a1ae1b049f2d GIT binary patch literal 691 zcmV;k0!;mhP)004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN zS#tmY3ljhU3ljkVnw%H_00JvXL_t(o!|j;8Pm@s;#(${TCVWYWY1uUn7#Kto62wRt z3^+(wO#B;+2@XXVOk4~OIykuiLt|6^2qH7G94dG7n(+vnW8upf?S@kSof=0CzN;gCH%D-93Wz>xQyl;C^+Qv4$W`U(W(<>BGo?S~pjnvz6Z%GrQQ{qEOxv7hReU*ZBD#YO z0lmUed*8YnE6EzsvoY))4!YfFODpO#BKtLD+0S3~Rhiu-sUg2NYuCP^d<3d&dHene zZC-H;v~r)6mb+*a(0|ErFLu4r+_Wehyb|pqx|6biUL|d!KP#SVg(5Hh(UuM95CjfcY;8e;Ra|n|*9NonlO)LibK=YSb4*CjPz+|*kK{c#6{z9-WWcn|3qb@P zn2%|iFMFo{WOvhS9r&vkWj$)z?k0y>uK{0hl_N~CX(cZ+NjKMc8C};}U50gmO>zuJ z^Db@~ZcCrJNoRx`;UQ(lnsdp5p^*l=U9UHg{W}F-H;`>AGU6WeglvXSWAw%Sj|~4x Z`~p3i20ETM-aG&R002ovPDHLkV1jZ(BwGLg literal 0 HcmV?d00001 diff --git a/aupod/res/drawable/scrollbar_v_thumb.xml b/aupod/res/drawable/scrollbar_v_thumb.xml new file mode 100644 index 0000000..2170f51 --- /dev/null +++ b/aupod/res/drawable/scrollbar_v_thumb.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/aupod/res/drawable/scrollbar_v_track.xml b/aupod/res/drawable/scrollbar_v_track.xml new file mode 100644 index 0000000..e2e7063 --- /dev/null +++ b/aupod/res/drawable/scrollbar_v_track.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/aupod/res/layout/activity_auplayer.xml b/aupod/res/layout/activity_auplayer.xml new file mode 100644 index 0000000..bd26848 --- /dev/null +++ b/aupod/res/layout/activity_auplayer.xml @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aupod/res/layout/activity_main.xml b/aupod/res/layout/activity_main.xml new file mode 100644 index 0000000..e561e7e --- /dev/null +++ b/aupod/res/layout/activity_main.xml @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aupod/res/layout/activity_settings.xml b/aupod/res/layout/activity_settings.xml new file mode 100644 index 0000000..2116779 --- /dev/null +++ b/aupod/res/layout/activity_settings.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aupod/res/layout/activity_tageditor.xml b/aupod/res/layout/activity_tageditor.xml new file mode 100644 index 0000000..5f68fc7 --- /dev/null +++ b/aupod/res/layout/activity_tageditor.xml @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aupod/res/layout/customview_ibutton.xml b/aupod/res/layout/customview_ibutton.xml new file mode 100644 index 0000000..1bd3a95 --- /dev/null +++ b/aupod/res/layout/customview_ibutton.xml @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/aupod/res/layout/customview_settingsitem.xml b/aupod/res/layout/customview_settingsitem.xml new file mode 100644 index 0000000..3cf7329 --- /dev/null +++ b/aupod/res/layout/customview_settingsitem.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/aupod/res/layout/customview_tabview.xml b/aupod/res/layout/customview_tabview.xml new file mode 100644 index 0000000..9172ccc --- /dev/null +++ b/aupod/res/layout/customview_tabview.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + diff --git a/aupod/res/layout/dlg_auplayer_options.xml b/aupod/res/layout/dlg_auplayer_options.xml new file mode 100644 index 0000000..45e459f --- /dev/null +++ b/aupod/res/layout/dlg_auplayer_options.xml @@ -0,0 +1,6 @@ + + + diff --git a/aupod/res/layout/dlg_songitem_options.xml b/aupod/res/layout/dlg_songitem_options.xml new file mode 100644 index 0000000..5992b8e --- /dev/null +++ b/aupod/res/layout/dlg_songitem_options.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aupod/res/layout/iplayer.xml b/aupod/res/layout/iplayer.xml new file mode 100644 index 0000000..849ce0d --- /dev/null +++ b/aupod/res/layout/iplayer.xml @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/aupod/res/layout/list_view.xml b/aupod/res/layout/list_view.xml new file mode 100644 index 0000000..26936fa --- /dev/null +++ b/aupod/res/layout/list_view.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/aupod/res/layout/notificationlayout.xml b/aupod/res/layout/notificationlayout.xml new file mode 100644 index 0000000..a3c47b3 --- /dev/null +++ b/aupod/res/layout/notificationlayout.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/aupod/res/layout/songlist_item.xml b/aupod/res/layout/songlist_item.xml new file mode 100644 index 0000000..d8cfcab --- /dev/null +++ b/aupod/res/layout/songlist_item.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aupod/res/layout/tabtitle.xml b/aupod/res/layout/tabtitle.xml new file mode 100644 index 0000000..4422af8 --- /dev/null +++ b/aupod/res/layout/tabtitle.xml @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/aupod/res/values-v21/styles.xml b/aupod/res/values-v21/styles.xml new file mode 100644 index 0000000..b1e024d --- /dev/null +++ b/aupod/res/values-v21/styles.xml @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/aupod/res/values/attrs.xml b/aupod/res/values/attrs.xml new file mode 100644 index 0000000..df93e32 --- /dev/null +++ b/aupod/res/values/attrs.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/aupod/res/values/colors.xml b/aupod/res/values/colors.xml new file mode 100644 index 0000000..90dbcd4 --- /dev/null +++ b/aupod/res/values/colors.xml @@ -0,0 +1,17 @@ + + + #000000 + @color/pluto + @color/color2 + + #082B56 + #0A5CB9 + #ffffff + #000000 + + #ffffff + + @color/color2 + + #D7D7D7 + diff --git a/aupod/res/values/strings.xml b/aupod/res/values/strings.xml new file mode 100644 index 0000000..1ba5e70 --- /dev/null +++ b/aupod/res/values/strings.xml @@ -0,0 +1,4 @@ + + aupod + 0.1.3 + diff --git a/aupod/res/values/styles.xml b/aupod/res/values/styles.xml new file mode 100644 index 0000000..305c515 --- /dev/null +++ b/aupod/res/values/styles.xml @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/aupod/res/values/tabview_attrs.xml b/aupod/res/values/tabview_attrs.xml new file mode 100644 index 0000000..80b3828 --- /dev/null +++ b/aupod/res/values/tabview_attrs.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/aupod/src/sleepchild/aupod22/App.java b/aupod/src/sleepchild/aupod22/App.java new file mode 100644 index 0000000..62d6f87 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/App.java @@ -0,0 +1,23 @@ +package sleepchild.aupod22; + +import android.app.Application; +import android.content.Context; +import sleepchild.aupod22.library.*; + +public class App extends Application +{ + private static Context ctx; + + @Override + public void onCreate(){ + super.onCreate(); + ctx = getApplicationContext(); + SongLibrary.get().discover(this); + //new Ape(); Utils.toast(ctx,"done"); + } + + public static Context getContext(){ + return ctx; + } + +} diff --git a/aupod/src/sleepchild/aupod22/AudioPlayer.java b/aupod/src/sleepchild/aupod22/AudioPlayer.java new file mode 100644 index 0000000..5001b86 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/AudioPlayer.java @@ -0,0 +1,120 @@ +package sleepchild.aupod22; + +import android.media.AudioManager; +import android.media.MediaPlayer; +import java.io.File; +import java.io.IOException; +import sleepchild.postman.PostMan; + +import sleepchild.aupod22.models.events.SongCompletionEvent; +import sleepchild.aupod22.models.events.SongResumeEvent; +import sleepchild.aupod22.models.events.SongPauseEvent; +import sleepchild.aupod22.models.*; + +public class AudioPlayer{ + + private MediaPlayer mPlayer; + public boolean isActive=false; + private SongItem currentsong; + + public AudioPlayer(){ + initPlayer(); + } + + private void initPlayer(){ + if(mPlayer!=null){ + try{ + mPlayer.stop(); + mPlayer.release(); + }catch(Exception e){} + } + mPlayer = new MediaPlayer(); + mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){ + @Override + public void onCompletion(MediaPlayer p1) + { + isActive=false; + PostMan.getInstance().post(new SongCompletionEvent(currentsong)); + } + }); + mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener(){ + @Override + public void onPrepared(MediaPlayer p1) + { + isActive=true; + } + }); + + } + + public void setSong(SongItem si){ + stop(); + currentsong = si; + try + { + mPlayer.setDataSource(si.path); + mPlayer.prepare(); + } + catch (IllegalStateException e) + {} + catch (IOException e) + {} + catch (SecurityException e) + {} + catch (IllegalArgumentException e) + {} + } + + public SongItem getCurrentSong(){ + return currentsong; + } + + // play the specified song + public void play(SongItem si){ + setSong(si); + resume(); + } + + // resume playing current song + public void resume(){ + mPlayer.start(); + isActive = true; + PostMan.getInstance().post(new SongResumeEvent(currentsong)); + } + + // pause the current song + public void pause(){ + if(mPlayer!=null && mPlayer.isPlaying()){ + mPlayer.pause(); + } + PostMan.getInstance().post(new SongPauseEvent(currentsong)); + } + + // stop and reset the player + public void stop(){ + if(mPlayer != null){ + mPlayer.stop(); + mPlayer.reset(); + } + isActive=false; + + } + + public boolean isPlaying(){ + return mPlayer != null && mPlayer.isPlaying(); + } + + public int getDuration(){ + return mPlayer.getDuration(); + } + + public int getCurrentPosition(){ + return mPlayer.getCurrentPosition(); + } + + public void seekTo(int pos){ + mPlayer.seekTo(pos); + } + +} diff --git a/aupod/src/sleepchild/aupod22/AudioService.java b/aupod/src/sleepchild/aupod22/AudioService.java new file mode 100644 index 0000000..e13abef --- /dev/null +++ b/aupod/src/sleepchild/aupod22/AudioService.java @@ -0,0 +1,375 @@ +package sleepchild.aupod22; + +import android.app.*; +import android.os.*; +import android.content.*; +import java.util.*; +import sleepchild.postman.PostMan; +import sleepchild.postman.PostEvent; +import sleepchild.aupod22.models.*; +import android.media.*; +import android.net.*; +import sleepchild.aupod22.tasks.*; +import sleepchild.aupod22.recievers.*; +import sleepchild.aupod22.utils.*; +import sleepchild.aupod22.models.events.*; +import sleepchild.aupod22.library.*; + +public class AudioService extends Service implements SongFactory.FactoryEvents +{ + public static final int REQUEST_CODE = 914826; + public static final String CMD_START = "sleepchild.aupod.service_cmd.start"; + public static final String CMD_EXIT = "sleepchild.aupod.service_cmdE_Exit"; + + public static final String CMD_PLAY = "sleepchild.aupod.service_cmd_PLAY"; + public static final String CMD_PAUSE = "sleepchild.aupod.service_cmd.PAUSECMD"; + public static final String CMD_PLAY_PAUSE = "sleepchild.aupod.service_cmd.PAUSEplayp"; + public static final String CMD_PLAY_NEXT = "sleepchild.aupod.service_cmd.playnextsong"; + public static final String CMD_PLAY_PREV = "sleepchild.aupod.service_cmdplayprev.song"; + + public static final String CMD_MEDIA_BUTTON = "sleepchild.aupod.service.MEDIA_BUTTON.CMD"; + + private Handler handle = new Handler(Looper.getMainLooper()); + private AudioPlayer player; + AudioManager audioMgr; + private SPrefs prefs; + private Context ctx; + final int nid = 826384; + boolean receiversReg=false; + boolean songListUpdateRequired = true; + + // todo: create a singleton global object to hold the songs? + private List songlist=null; + + @Override + public IBinder onBind(Intent p1){ + return null; + } + + @Override + public void onCreate(){ + PostMan.getInstance().register(this); + super.onCreate(); + ctx = getApplicationContext(); + audioMgr = (AudioManager) getSystemService(AUDIO_SERVICE); + prefs = new SPrefs(ctx); + player = new AudioPlayer(); + SongFactory.get().registerEventListener(this); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId){ + String cmd = intent.getAction(); + switch(cmd){ + case CMD_START: + PostMan.getInstance().post(new AudioServiceConnect(this)); + break; + case CMD_EXIT: + quit(); + break; + case CMD_PLAY: + resume(); + break; + case CMD_PAUSE: + pause(); + break; + case CMD_PLAY_NEXT: + playNext(); + break; + case CMD_PLAY_PREV: + playPrev(); + break; + case CMD_MEDIA_BUTTON: + handleMediaButton(); + break; + } + return START_NOT_STICKY;// 2 + } + + public static void start(Context ctx){ + Intent i = new Intent(ctx, AudioService.class); + i.setAction(CMD_START); + ctx.startService(i); + } + + public static void quit(Context ctx){ + Intent i = new Intent(ctx, AudioService.class); + i.setAction(CMD_EXIT); + ctx.startService(i); + } + + @Override + public void onDestroy() + { + unRegisterAudioNoisy(); + unRegisterMediaButtons(); + player.stop(); + super.onDestroy(); + } + + + ///////////////// + /// + + public void playSong(SongItem si){ + player.play(si); + prefs.saveLastPath(si.path); + } + + public void pause(){ + player.pause(); + } + + public void resume(){ + player.resume(); + } + + public void playPause(){ + if(player.isPlaying()){ + pause(); + }else{ + resume(); + } + } + + public void playPrev(){ + if(player.getCurrentPosition()>5000){ + player.seekTo(0); + return; + } + int idx = songlist.indexOf(getCurrentSong()); + idx--; + if(idx<0){ + idx=0; + } + playSong(songlist.get(idx)); + } + + public void playNext(){ + int idx = songlist.indexOf( getCurrentSong() ); + idx++; + if(idx list){ + handle.postDelayed(new Runnable(){ + public void run(){ + songlist = list; + //* + if(!songlist.isEmpty() && f2){ + f2 = false; + player.setSong(songlist.get(0)); + + ///// + // this is terrible. We Must implement a playing queue and do this there + + //@lp : last played song path + String lp = prefs.getLastPath(); + // lp is empty bcause it was reset or was never set + if(lp.isEmpty()){ + player.setSong(songlist.get(0)); + }else{ + SongItem ss=null; + for (SongItem s : songlist){ + if(s.path.equals(lp)){ + ss = s; + break;// break the loop; no need to check others + } + } + if(ss!=null){// song still exists in same path as last time. + player.setSong(ss); + //player.seekTo(prefs.getPos()); + }else{// we reach here because the song was moved/renamed or deleted + //we set the first song int the list and clear the preferences + player.setSong(songlist.get(0)); + prefs.saveLastPath(""); + //prefs.setPos(0); + } + } + } + //*/ + // setup done; send the list + PostMan.getInstance().post(new SongsListReadyEvent(songlist)); + } + },0); + } + + @Override + public void onGetSongsError(final String message){ + handle.postDelayed(new Runnable(){ + public void run(){ + Utils.toast(ctx, message); + } + },0); + } + + @PostEvent + public void onSongInfoChange(final SongInfoChangedEvent evt){ + handle.postDelayed(new Runnable(){ + public void run(){ + songListUpdateRequired=true; + getSongList(); + } + },0); + } + + public void onSongListUpdated(List newlist){ + Utils.toast(this,"songupdate"); + } + //////////////// + // the private life of AudioService. + + private void registerReceivers(){ + if(receiversReg){return;} + receiversReg = true; + registerAudioNoisy(); + registerMediaButtons(); + } + + private void registerAudioNoisy(){ + // + } + + private void unRegisterAudioNoisy(){ + // + } + + ComponentName mediaButtonComp;// <-- move to top of file. + private void registerMediaButtons(){ + mediaButtonComp = new ComponentName(this, ButtonReciever.class.getName()); + audioMgr.registerMediaButtonEventReceiver(mediaButtonComp); + } + + private void unRegisterMediaButtons(){ + audioMgr.unregisterMediaButtonEventReceiver(mediaButtonComp); + } + + private void quit(){ + player.stop(); + unRegisterMediaButtons(); + unRegisterAudioNoisy(); + stopForeground(true); + stopSelf(); + } + + Runnable dblk; + int d=0; + private void handleMediaButton(){ + if(dblk==null){ + dblk = new Runnable(){ + public void run(){ + //single click + d=0; + playPause(); + } + }; + } + d++; + if(d==2){ + // double click + handle.removeCallbacks(dblk); + playNext(); + d=0; + }else if(d==1){ + handle.postDelayed(dblk,250); + } + } + +} diff --git a/aupod/src/sleepchild/aupod22/PlayQueue.java b/aupod/src/sleepchild/aupod22/PlayQueue.java new file mode 100644 index 0000000..6b65a46 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/PlayQueue.java @@ -0,0 +1,16 @@ +package sleepchild.aupod22; +import java.util.*; +import sleepchild.aupod22.models.*; + +public class PlayQueue{ + String Qname; + List songlist = new ArrayList<>(); + + public PlayQueue(String name){ + // + } + + public void addSong(SongItem song){ + // + } +} diff --git a/aupod/src/sleepchild/aupod22/Playlist.java b/aupod/src/sleepchild/aupod22/Playlist.java new file mode 100644 index 0000000..438655d --- /dev/null +++ b/aupod/src/sleepchild/aupod22/Playlist.java @@ -0,0 +1,5 @@ +package sleepchild.aupod22; + +public class Playlist +{ +} diff --git a/aupod/src/sleepchild/aupod22/SearchPanel.java b/aupod/src/sleepchild/aupod22/SearchPanel.java new file mode 100644 index 0000000..f2c0a57 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/SearchPanel.java @@ -0,0 +1,115 @@ +package sleepchild.aupod22; + +import android.widget.*; +import android.view.*; +import java.util.*; +import android.text.*; +import sleepchild.aupod22.activity.*; +import sleepchild.aupod22.utils.*; + +public class SearchPanel implements SearchHelper.ResultCallback +{ + MainActivity act; + LinearLayout searchPanel; + EditText input; + ListView list8; + SearchResutlAdapter adaptor; + + public SearchPanel(MainActivity act){ + this.act = act; + searchPanel = (LinearLayout) act.findViewById(R.id.activity_main_searchpanel); + input = (EditText) act.vid(R.id.activity_main_search_input); + input.addTextChangedListener(new TextWatcher(){ + @Override + public void beforeTextChanged(CharSequence p1, int p2, int p3, int p4) + { + // TODO: Implement this method + } + + @Override + public void onTextChanged(CharSequence p1, int p2, int p3, int p4) + { + // TODO: Implement this method + } + + @Override + public void afterTextChanged(Editable p1) + { + String q = input.getText().toString(); + if(!q.isEmpty()){ + SearchHelper.serch(q, SearchPanel.this); + } + } + }); + list8 = (ListView) act.findViewById(R.id.activity_main_search_list8); + adaptor = new SearchResutlAdapter(act); + list8.setAdapter(adaptor); + } + + @Override + public void onSearchResult(List list) + { + act.toast(""+new Date().getTime()); + } + + public void show(){ + searchPanel.setVisibility(View.VISIBLE); + this.act.showKeyboard(input); + } + + public void hide(){ + searchPanel.setVisibility(View.GONE); + adaptor.clear(); + input.setText(""); + } + + public boolean isVisible(){ + return searchPanel.getVisibility()==View.VISIBLE; + } + + // + private class SearchResutlAdapter extends BaseAdapter{ + + private LayoutInflater inf; + private List resultlist = new ArrayList<>(); + + public SearchResutlAdapter(MainActivity ctx){ + this.inf = ctx.getLayoutInflater(); + } + + public void update(){ + // + } + + public void clear(){ + // + } + + @Override + public int getCount(){ + return this.resultlist.size(); + } + + @Override + public Object getItem(int pos) + { + return this.resultlist.get(pos); + } + + @Override + public long getItemId(int p1) + { + // TODO: Implement this method + return p1; + } + + @Override + public View getView(int pos, View v, ViewGroup p3) + { + //v= inf.inflate(R.layout.songlist_item); + return v; + } + + + } +} diff --git a/aupod/src/sleepchild/aupod22/activity/BaseActivity.java b/aupod/src/sleepchild/aupod22/activity/BaseActivity.java new file mode 100644 index 0000000..878e63f --- /dev/null +++ b/aupod/src/sleepchild/aupod22/activity/BaseActivity.java @@ -0,0 +1,61 @@ +package sleepchild.aupod22.activity; + +import android.app.*; +import android.os.*; +import android.content.*; +import android.widget.*; +import android.view.*; +//import android.inputmethodservice.*; +import android.view.inputmethod.*; + +public class BaseActivity extends Activity +{ + + public Context ctx; + public InputMethodManager ims; + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + this.ctx = getApplicationContext(); + ims = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + } + + public void toast(String msg){ + Toast.makeText(ctx, msg, 500).show(); + } + + public View vid(int resid){ + return findViewById(resid); + } + + public void startActivity(Class clazz){ + startActivity(new Intent(this, clazz)); + } + + public void showView(View v){ + v.setVisibility(View.VISIBLE); + } + + public void hideView(View v){ + v.setVisibility(View.GONE); + } + + public boolean isViewVisible(View v){ + return v.getVisibility()==View.VISIBLE; + } + + public void showKeyboard(View v){ + v.requestFocus(); + ims.showSoftInput(v,InputMethodManager.SHOW_IMPLICIT); + } + + //@Override + public void onPointerCaptureChanged(boolean hasCapture) + { + // TODO: Implement this method + } + + +} diff --git a/aupod/src/sleepchild/aupod22/activity/IntentActivity.java b/aupod/src/sleepchild/aupod22/activity/IntentActivity.java new file mode 100644 index 0000000..fd5db71 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/activity/IntentActivity.java @@ -0,0 +1,29 @@ +package sleepchild.aupod22.activity; + +import android.os.Bundle; +import android.content.*; +import android.view.*; +import sleepchild.aupod22.R; + +public class IntentActivity extends BaseActivity +{ + @Override + public void onCreate(Bundle savedInstanceState) + { + requestWindowFeature(Window.FEATURE_NO_TITLE); + super.onCreate(savedInstanceState); + setContentView(R.layout.iplayer); + Intent i = getIntent(); + String path = clean(i.getDataString()); + //AudioService.playSong(this,path); + finish(); + //startActivity(PlayerActivity.class); + } + + String clean(String str){ + return str.replaceAll("%20"," "); + } + + + +} diff --git a/aupod/src/sleepchild/aupod22/activity/MainActivity.java b/aupod/src/sleepchild/aupod22/activity/MainActivity.java new file mode 100644 index 0000000..fdc613f --- /dev/null +++ b/aupod/src/sleepchild/aupod22/activity/MainActivity.java @@ -0,0 +1,211 @@ +package sleepchild.aupod22.activity; + +import android.app.Activity; +import android.os.Bundle; +import android.view.*; +import android.widget.*; +import android.content.*; +import java.util.*; +import android.os.*; +import android.graphics.*; +import android.net.*; +import android.graphics.drawable.*; +import sleepchild.postman.PostMan; +import sleepchild.postman.PostEvent; +import sleepchild.aupod22.models.*; +import sleepchild.aupod22.tabs.*; +import sleepchild.view.*; +import sleepchild.view.tabview.Tab; +import sleepchild.view.tabview.TabView; +import sleepchild.aupod22.activity.*; +import sleepchild.aupod22.adapters.*; +import sleepchild.aupod22.*; +import sleepchild.aupod22.utils.*; +import sleepchild.aupod22.models.events.*; +import sleepchild.aupod22.library.*; + +public class MainActivity extends BaseActivity +{ + AudioService aupod; + ImageView currentImage; + public final static int REQUEST_CODE = 22466; + ListView list001; + SongListAdaptor sAdaptor; + TextView currentsongTitle, currentsongArtist; + TintedImageView miniPlayPause; + TabView tabview; + SongsListTab songsTab; + ArtistTab artistTab; + AlbumsTab albumsTab; + PlaylistsTab playlistTab; + + SearchPanel searchPanel; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + // + init(); + } + //* + private void init(){ + // + currentsongTitle = (TextView) findViewById(R.id.activity_main_tv_title); + currentsongArtist = (TextView) findViewById(R.id.activity_main_tv_artist); + currentImage = (ImageView) findViewById(R.id.activity_main_iv_currentimage); + miniPlayPause = (TintedImageView)findViewById(R.id.activity_main_iv_playpause); + searchPanel = new SearchPanel(this); + + tabview = (TabView) findViewById(R.id.activity_main_tabview1); + + songsTab = new SongsListTab(this); + artistTab = new ArtistTab(this); + albumsTab = new AlbumsTab(this); + playlistTab = new PlaylistsTab(this); + + tabview.addTab("SONGS", songsTab); + tabview.addTab("ARTIST", artistTab); + tabview.addTab("ALBUMS", albumsTab); + tabview.addTab("PLAYLIST",playlistTab); + + tabview.showTab(0); + } + + public void onClick(View v){ + int id = v.getId(); + switch(id){ + case R.id.activity_main_btn_showsettings: + startActivity(SettingsActivity.class); + break; + case R.id.activity_main_btn_search: + searchPanel.show(); + break; + case R.id.activity_main_btn_playpause: + if(aupod!=null){ + aupod.playPause(); + } + break; + case R.id.activity_main_btn_next: + if(aupod!=null){ + aupod.playNext(); + } + break; + } + } + + public void showFullPlayer(View v){ + startActivity(PlayerActivity.class); + } + + @PostEvent + public void onServiceConnect(AudioServiceConnect event){ + //toast("connect!"); + aupod = event.service; + aupod.getSongList(); + } + + @PostEvent + public void onSongListReady(final SongsListReadyEvent event){ + runOnUiThread(new Runnable(){ + public void run(){ + //toast(""+event.songList.size()); + songsTab.update(event.songList); + updateCurrentInfo(); + updateButtons(); + //songsTab.showCurrent(); + } + }); + } + + @PostEvent + public void onSongResume(SongResumeEvent evt){ + runOnUiThread(new Runnable(){ + public void run(){ + updateCurrentInfo(); + updateButtons(); + } + }); + } + + @PostEvent + public void OnSongPaused(SongPauseEvent event){ + runOnUiThread(new Runnable(){ + public void run(){ + updateCurrentInfo(); + updateButtons(); + } + }); + } + + private void updateButtons(){ + //* + if(aupod!=null){ + if(aupod.isPlaying()){ + miniPlayPause.setBackgroundResource(R.drawable.ic_pause); + }else{ + miniPlayPause.setBackgroundResource(R.drawable.ic_play); + } + miniPlayPause.setTint(getResources().getColor(R.color.color2)); + } + //*/ + } + + + private void updateCurrentInfo(){ + //todo: merge in @updateButtons methods + if(aupod==null){return;} + //* + final SongItem si = aupod.getCurrentSong(); + currentsongTitle.setText(si.title); + currentsongArtist.setText(si.artist); + if(si.icon!=null){ + currentImage.setBackgroundDrawable(new BitmapDrawable(getResources(), si.icon)); + }else{ + SongFactory.get().updateSong(si, new SongFactory.UCB(){ + @Override + public void onResult(final SongItem item){ + runOnUiThread(new Runnable(){ + public void run(){ + si.icon = item.icon; + currentImage.setBackgroundDrawable(Utils.bmpToDrawable(ctx, si.icon)); + if(si.icon==null){ + currentImage.setBackgroundResource(R.drawable.fallback_cover); + } + } + }); + } + }); + } + songsTab.setCurrent(si); + //*/ + } + + @Override + protected void onPause() + { + PostMan.getInstance().unregister(this); + super.onPause(); + } + + @Override + protected void onResume() + { + PostMan.getInstance().register(this); + super.onResume(); + AudioService.start(this); + } + + @Override + public void onBackPressed() + { + if(searchPanel.isVisible()){ + searchPanel.hide(); + }else{ + super.onBackPressed(); + } + + } + + +} diff --git a/aupod/src/sleepchild/aupod22/activity/PlayerActivity.java b/aupod/src/sleepchild/aupod22/activity/PlayerActivity.java new file mode 100644 index 0000000..7b9de43 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/activity/PlayerActivity.java @@ -0,0 +1,292 @@ +package sleepchild.aupod22.activity; + +import android.os.*; +import android.widget.*; +import android.graphics.*; +import java.util.*; +import sleepchild.postman.PostMan; +import sleepchild.postman.PostEvent; +import sleepchild.aupod22.models.*; +import android.graphics.drawable.*; +import android.view.*; +import java.util.concurrent.*; +import sleepchild.aupod22.menu.*; +import sleepchild.view.*; +import android.view.animation.*; +import sleepchild.aupod22.utils.*; +import sleepchild.aupod22.activity.*; +import sleepchild.aupod22.*; +import sleepchild.aupod22.models.events.*; +import sleepchild.aupod22.library.*; + +public class PlayerActivity extends BaseActivity +{ + + TextView currentTitle, currentArtist; + TextView trackTimeCurrent, trackTimeDuration; + LinearLayout art2Background; + ImageView currentArt; + AudioService aupod; + TintedImageView playpauseIcon; + SeekBar seeker; + Runnable seekerTick; + boolean seektouch; + Handler handle; + SongItem mCurrentSong; + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_auplayer); + init(); + } + + void init(){ + handle = new Handler(); + currentTitle = (TextView) findViewById(R.id.auplayer_tv_title); + currentArtist = (TextView) findViewById(R.id.auplayer_tv_artist); + art2Background = (LinearLayout) findViewById(R.id.aupalyer_iv_art2_background); + currentArt = (ImageView) findViewById(R.id.auplayer_iv_art); + playpauseIcon = (TintedImageView) findViewById(R.id.auplayer_btn_playpause); + // + seeker = (SeekBar) findViewById(R.id.aupalyer_seeker); + seeker.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){ + @Override + public void onProgressChanged(SeekBar p1, int pos, boolean touch) + { + if(seektouch){ + aupod.seekTo(pos); + trackTimeCurrent.setText(formatTime(pos)); + } + } + + @Override + public void onStartTrackingTouch(SeekBar p1) + { + stopSeeker(); + seektouch = true; + } + + @Override + public void onStopTrackingTouch(SeekBar p1) + { + seektouch = false; + if(aupod.isPlaying()){ + startSeeker(); + } + } + }); + + seekerTick = new Runnable(){ + @Override + public void run(){ + if(aupod!=null){ + int pos = aupod.getCurrentPosition(); + seeker.setProgress(pos); + trackTimeCurrent.setText(formatTime(pos)); + handle.postDelayed(seekerTick,1000); + } + } + }; + + trackTimeCurrent = (TextView) findViewById(R.id.auplayer_currentpos); + trackTimeDuration = (TextView) findViewById(R.id.auplayer_duration); + + } + + void updateInfo(){ + //* + final SongItem si = aupod.getCurrentSong(); + if(mCurrentSong==si){ + return; + } + mCurrentSong=si; + currentTitle.setText(si.title); + currentArtist.setText(si.artist); + if(si.icon!=null){ + currentArt.setImageBitmap(si.icon); + art2Background.setBackground(null); + SongFactory.get().submit(new Runnable(){ + public void run(){ + final Bitmap bmp = FastBlur.fastblur(si.icon,1,8); + if(bmp!=null){ + handle.postDelayed(new Runnable(){ + public void run(){ + //art2Background.setVisibility(View.INVISIBLE); + art2Background.setBackground(new BitmapDrawable(getResources(), bmp)); + //* + Animation anim = new AlphaAnimation(0,1); + anim.setDuration(500); + anim.setRepeatCount(0); + anim.setInterpolator(new DecelerateInterpolator()); + anim.setAnimationListener(new Animation.AnimationListener(){ + @Override + public void onAnimationStart(Animation p1) + { + // TODO: Implement this method + } + + @Override + public void onAnimationEnd(Animation p1) + { + art2Background.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationRepeat(Animation p1) + { + // TODO: Implement this method + } + }); + art2Background.setAnimation(anim); + //*/ + //anim.start(); + } + + },0); + } + } + }); + }else{ + currentArt.setImageResource(R.drawable.fallback_cover); + art2Background.setBackground(null); + } + + if(aupod.isPlaying()){ + seeker.setMax(aupod.getDuration()); + }else{ + seeker.setMax((int)si.duration); + } + + seeker.setProgress(aupod.getCurrentPosition()); + trackTimeDuration.setText(formatTime((int)si.duration)); + //*/ + + } + + void updateButtons(){ + //* + if(aupod!=null){ + if(aupod.isPlaying()){ + playpauseIcon.setImageResource(R.drawable.ic_pause); + }else{ + playpauseIcon.setImageResource(R.drawable.ic_play); + } + } + //*/ + } + + void startSeeker(){ + stopSeeker(); + handle.postDelayed(seekerTick, 1000); + } + + void stopSeeker(){ + handle.removeCallbacks(seekerTick); + } + + String formatTime(int time){ + //String t = ""; + int hrs = (int) (time/ (1000*60*60)) % 60; + int min = (int) ( time/ (1000*60)) % 60; + int sec = (int) (time /1000) % 60; + if(hrs==0){ + return d(min)+":"+d(sec); + } + return d(hrs)+":"+d(min)+":"+d(sec); + } + + String d(int t){ + if(t<10){ + return "0"+t; + } + return ""+t; + } + + public void onButton(View v){ + int id = v.getId(); + switch(id){ + case R.id.auplayer_btn_playpause: + if(aupod!=null){ + aupod.playPause(); + } + break; + case R.id.auplayer_btn_next: + if(aupod!=null){ + aupod.playNext(); + } + break; + case R.id.auplayer_btn_prev: + if(aupod!=null){ + aupod.playPrev(); + } + break; + case R.id.auplayer_btn_back: + finish(); + break; + case R.id.auplayer_btn_options: + new CurrentSongOptions(this, aupod.getCurrentSong()).show(); + break; + } + } + + @PostEvent + public void onConnect(AudioServiceConnect conn){ + aupod = conn.service; + updateInfo(); + //* + updateButtons(); + if(aupod.isPlaying()){ + startSeeker(); + } + //*/ + } + + @PostEvent + public void onSongResumed(SongResumeEvent evt){ + runOnUiThread(new Runnable(){ + public void run(){ + updateInfo(); + updateButtons(); + startSeeker(); + } + }); + } + + @PostEvent + public void onSongPaused(SongPauseEvent evt){ + runOnUiThread(new Runnable(){ + public void run(){ + updateInfo(); + updateButtons(); + stopSeeker(); + } + }); + } + + //@PostEvent + public void onSongStopped(){ + + } + + @Override + protected void onPause() + { + stopSeeker(); + //APEvents.getInstance().unregister(this); + PostMan.getInstance().unregister(this); + super.onPause(); + } + + + @Override + protected void onResume() + { + //APEvents.getInstance().register(this); + PostMan.getInstance().register(this); + AudioService.start(this); + super.onResume(); + } + +} diff --git a/aupod/src/sleepchild/aupod22/activity/SettingsActivity.java b/aupod/src/sleepchild/aupod22/activity/SettingsActivity.java new file mode 100644 index 0000000..a5f810b --- /dev/null +++ b/aupod/src/sleepchild/aupod22/activity/SettingsActivity.java @@ -0,0 +1,43 @@ +package sleepchild.aupod22.activity; + +import android.os.*; +import android.view.*; +import sleepchild.aupod22.activity.*; +import sleepchild.aupod22.*; + +public class SettingsActivity extends BaseActivity +{ + public static final int requetsCode = 333749; + + @Override + public void onCreate(Bundle savedInstanceState) + { + // TODO: Implement this method + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_settings); + // + init(); + } + + public void init(){ + // + } + + public void onClick(View v){ + int id = v.getId(); + switch(id){ + case R.id.settings_item_interface: + // + break; + case R.id.settings_item_medialibrary: + // + break; + case R.id.settings_item_headsetbt: + // + break; + } + toast(""+id); + } + + +} diff --git a/aupod/src/sleepchild/aupod22/activity/TagEditorActivity.java b/aupod/src/sleepchild/aupod22/activity/TagEditorActivity.java new file mode 100644 index 0000000..eee2dc2 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/activity/TagEditorActivity.java @@ -0,0 +1,244 @@ +package sleepchild.aupod22.activity; + +import android.content.*; +import android.graphics.*; +import android.graphics.drawable.*; +import android.os.*; +import android.view.*; +import android.widget.*; +import com.mpatric.mp3agic.*; +import java.io.*; +import java.util.*; +import sleepchild.aupod22.*; +import sleepchild.aupod22.models.*; +import sleepchild.postman.*; +import sleepchild.aupod22.models.events.*; +import sleepchild.aupod22.library.*; + +public class TagEditorActivity extends BaseActivity{ + + private static SongItem xsongItem=null; + + private EditText etTitle, etArtist, etAlbum, etYear; + View art; + public static final String EPATH="Sleep.tagedit.act.path"; + String mPath; + Mp3File mp3; + ID3v2 v2; + private SongItem mSongItem; + byte[] newArt; + String newArtType="image/*"; + + @Override + public void onCreate(Bundle si){ + super.onCreate(si); + setContentView(R.layout.activity_tageditor); + // + if(xsongItem!=null){ + mSongItem = xsongItem; + xsongItem = null; + init(); + } + else{ + toast("no data."); + } + } + + public static void start(Context ctx,SongItem si){ + TagEditorActivity.xsongItem = si; + ctx.startActivity(new Intent(ctx, TagEditorActivity.class)); + } + + private void init(){ + if(mSongItem==null){ + //setContentView(error); + return; + } + etTitle = (EditText) findViewById(R.id.activity_tageditor_title); + etArtist = (EditText) findViewById(R.id.activity_tageditor_artist); + etAlbum = (EditText) findViewById(R.id.activity_tageditor_album); + etYear = (EditText) findViewById(R.id.activity_tageditor_year); + art = findViewById(R.id.tageditor_art); + //* + mPath = mSongItem.path; + if(mPath!=null && !mPath.isEmpty()){ + try{ + mp3 = new Mp3File(mPath); + v2 = mp3.getId3v2Tag(); + if(v2!=null){ + String t = nn(v2.getTitle()); + if(t.isEmpty()){ + t = mSongItem.title; + } + etTitle.setText(t); + etArtist.setText(nn(v2.getArtist())); + etAlbum.setText(nn(v2.getAlbum())); + + byte[] image = v2.getAlbumImage(); + if(image!=null && image.length>3){// why 3? + art.setBackground( new BitmapDrawable(getResources(), BitmapFactory.decodeByteArray(image,0,image.length))); + + } + + } + + } + catch (InvalidDataException e){ + toast("InvalidDataException: "+e.getDetailedMessage()); + finish(); + } + catch (IOException e){ + toast("IOException: "+e.getMessage()); + finish(); + } + catch (UnsupportedTagException e){ + toast("UnsupportedTagException: "+e.getMessage()); + finish(); + } + } + //*/ + } + + // never null + // return str elif str == null return empty string "" + String nn(String str){ + if(str==null){ + return ""; + } + return str; + } + + int pikerRequestCode = 826384; + void getNewArt(){ + if(v2==null){ + if(mp3!=null){ + if(mp3.hasId3v2Tag()){ + v2 = mp3.getId3v2Tag(); + }else{ + v2 = new ID3v24Tag(); + } + } + } + if(v2!=null){ + Intent piker = new Intent(Intent.ACTION_GET_CONTENT); + piker.setType("image/*"); + startActivityForResult(piker, pikerRequestCode); + } + } + + String artPath =null; + public void setArt(Intent data){ + if(data!=null){ + try{ + artPath = data.getData().getPath(); + InputStream ins = getContentResolver().openInputStream(data.getData()); + byte[] buff = new byte[ins.available()]; + ins.read(buff); + Bitmap a = BitmapFactory.decodeByteArray(buff,0,buff.length); + //Bitmap a = BitmapFactory.decodeStream(ins); + art.setBackground(new BitmapDrawable(getResources(), a)); + if(buff!=null){ + newArt = buff; + newArtType = getContentResolver().getType(data.getData()); + } + } + catch (FileNotFoundException e) + {}catch(IOException e){} + } + } + + private boolean saveData(){ + try{ + if(mp3 == null){ + try{ + mp3 = new Mp3File(mPath); + }catch(Exception e){ + // + } + if(mp3==null){ + toast("Failed to Edit: Not an mp3 file!"); + return false; + } + } + if(v2==null){ + if(mp3.hasId3v2Tag()){ + v2 = mp3.getId3v2Tag(); + }else{ + v2 = new ID3v24Tag(); + } + } + //title + String t = etTitle.getText().toString(); + v2.setTitle(t); + mSongItem.title = t; + // artist + String ar = etArtist.getText().toString(); + v2.setArtist(ar); + mSongItem.artist = ar; + //album + String al = etAlbum.getText().toString(); + v2.setAlbum(al); + mSongItem.album = al; + //year + String yr = etYear.getText().toString(); + v2.setYear(yr); + // album art + if(newArt!=null){ + v2.setAlbumImage(newArt, newArtType); + } + //v2.setAlbumImage(new byte[10]," "); + // + mp3.setId3v2Tag(v2); + try + { + if(new File(mp3.getFilename()).exists()){ + + } + String fn = mPath.substring(0,mPath.lastIndexOf(".")); + mp3.save(fn); + new File(mPath).delete(); + new File(fn).renameTo(new File(mPath)); + MediaStoreUpdator.update(ctx,mSongItem, artPath); + PostMan.getInstance().post(new SongInfoChangedEvent(mSongItem)); + return true; + } + catch (IOException e) + {} + catch (NotSupportedException e) + {} + }catch(Exception e){ + toast(e.getMessage()); + } + return false; + } + + + public void onButton(View v){ + int id = v.getId(); + switch(id){ + case R.id.tageditor_art: + getNewArt(); + break; + case R.id.activity_tageditor_btn_save: + if(saveData()){ + finish(); + } + break; + case R.id.activity_tageditor_exit: + finish(); + break; + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) + { + if(requestCode==pikerRequestCode){ + setArt(data); + } + super.onActivityResult(requestCode, resultCode, data); + } + + + +} diff --git a/aupod/src/sleepchild/aupod22/adapters/ArtistsListAdapter.java b/aupod/src/sleepchild/aupod22/adapters/ArtistsListAdapter.java new file mode 100644 index 0000000..9269b65 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/adapters/ArtistsListAdapter.java @@ -0,0 +1,85 @@ +package sleepchild.aupod22.adapters; +import android.widget.*; +import android.view.*; +import android.content.*; +import sleepchild.aupod22.*; +import java.util.*; +import android.graphics.*; +import sleepchild.aupod22.activity.*; +import sleepchild.aupod22.models.*; + +public class ArtistsListAdapter extends BaseAdapter +{ + MainActivity ctx; + List artistlist = new ArrayList<>(); + Map al = new HashMap<>(); + LayoutInflater inf; + + public ArtistsListAdapter(MainActivity act){ + this.ctx = act; + inf = LayoutInflater.from(ctx); + } + + public void update(List list){ + artistlist.clear(); + Set s = new HashSet<>(); + //* + for(SongItem si : list){ + s.add(si.artist); + //int ts = 0; + Integer ts = al.get(si.artist); + if(ts==null){ + ts = 0; + } + ts++; + al.put(si.artist, ts); + } + for(String a : s){ + artistlist.add(a); + } + Collections.sort(artistlist, new Comparator(){ + @Override + public int compare(String p1, String p2){ + return p1.toLowerCase().compareTo(p2.toLowerCase()); + } + }); + //*/ + notifyDataSetChanged(); + } + + @Override + public int getCount() + { + // TODO: Implement this method + return artistlist.size(); + } + + @Override + public Object getItem(int pos){ + return artistlist.get(pos); + } + + @Override + public long getItemId(int p1){ + return p1; + } + + @Override + public View getView(int pos, View v, ViewGroup p3){ + String artist = artistlist.get(pos); + v = inf.inflate(R.layout.songlist_item, null, false); + TextView name = (TextView) v.findViewById(R.id.songlist_itemTitle); + name.setText(artist); + + TextView songs = (TextView) v.findViewById(R.id.songlist_itemArtist); + Integer num = al.get(artist); + //String snum = num==1? " Song" : " Songs"; snum = num + snum; + String snum = num==1? num+" Song" : num+" Songs"; + songs.setText(snum); + + //v.findViewById(R.id.songlist_item_albumart).setVisibility(View.GONE); + + return v; + } + +} diff --git a/aupod/src/sleepchild/aupod22/adapters/SongListAdaptor.java b/aupod/src/sleepchild/aupod22/adapters/SongListAdaptor.java new file mode 100644 index 0000000..24db680 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/adapters/SongListAdaptor.java @@ -0,0 +1,135 @@ +package sleepchild.aupod22.adapters; + +import android.widget.*; +import android.view.*; +import android.content.*; +import java.util.*; +import android.graphics.*; +import android.graphics.drawable.*; +import android.os.*; +import sleepchild.postman.PostMan; +import sleepchild.postman.PostEvent; +import sleepchild.aupod22.models.*; +import sleepchild.aupod22.menu.*; +import sleepchild.aupod22.activity.*; +import sleepchild.aupod22.*; +import sleepchild.aupod22.models.events.*; +import sleepchild.aupod22.library.*; +import sleepchild.view.*; + +public class SongListAdaptor extends BaseAdapter +{ + Handler handle = new Handler(); + LayoutInflater inf; + List songList = new ArrayList<>(); + BaseActivity ctx; + SongItem currentSong; + + public SongListAdaptor(BaseActivity ctx){ + this.ctx = ctx; + inf = LayoutInflater.from(ctx); + } + + public void update(List list){ + this.songList = list; + notifyDataSetChanged(); + } + + public void setCurrent(SongItem songitem){ + // + this.currentSong = songitem; + notifyDataSetChanged(); + } + + public int getPos(SongItem si){ + return songList.indexOf(si); + } + + @Override + public int getCount(){ + return songList.size(); + } + + @Override + public Object getItem(int p1){ + return songList.get(p1); + } + + @Override + public long getItemId(int p1){ + return p1; + } + + //@Override + public CharSequence[] getAutofillOptions() + { + return null; + } + + @PostEvent + public void onSongResume(SongResumeEvent evt){ + handle.postDelayed(new Runnable(){ + public void run(){ + // + } + },0); + } + + @Override + public View getView(int pos, View p2, ViewGroup p3) + { + final SongItem item = songList.get(pos); + + View v = inf.inflate(R.layout.songlist_item, null, false); + TextView title = (TextView) v.findViewById(R.id.songlist_itemTitle); + title.setText(item.title); + // + TextView artist = (TextView) v.findViewById(R.id.songlist_itemArtist); + artist.setText(item.artist); + // + final ImageView art = (ImageView) v.findViewById(R.id.songlist_item_albumart); + if(item.updated){ + if(item.icon!=null){ + art.setBackgroundDrawable(new BitmapDrawable(ctx.getResources(),item.icon)); + } + }else{ + // this be a mess.. + SongFactory.get().updateSong(item, new SongFactory.UCB(){ + @Override + public void onResult(final SongItem si){ + handle.postDelayed(new Runnable(){ + public void run(){ + //item.title = si.title; + //item.artist = si.artist; + item.icon = si.icon; + item.updated = true; + if(item.icon!=null){ + art.setBackgroundDrawable(new BitmapDrawable(ctx.getResources(),item.icon)); + } + } + },0); + } + }); + } + ((View) v.findViewById(R.id.songlist_item_more)).setOnClickListener(new View.OnClickListener(){ + public void onClick(View v){ + new SongOptions(ctx, item).show(); + } + }); + + TintedImageView mv = (TintedImageView) v.findViewById(R.id.songlist_itemsleepchild_view_T2); + + if(currentSong!=null && currentSong.equals(item)){ + v.setBackgroundResource(R.color.color2); + title.setTextColor(ctx.getColor(R.color.pluto)); + artist.setTextColor(ctx.getColor(R.color.pluto)); + + mv.setTint(ctx.getColor(R.color.pluto)); + }else{ + //mv.setTint(ctx.getColor(R.color.white)); + } + v.setTag(item); + return v; + } + +} diff --git a/aupod/src/sleepchild/aupod22/library/MediaStoreUpdator.java b/aupod/src/sleepchild/aupod22/library/MediaStoreUpdator.java new file mode 100644 index 0000000..b488803 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/library/MediaStoreUpdator.java @@ -0,0 +1,33 @@ +package sleepchild.aupod22.library; + +import android.content.*; +import android.provider.*; +import android.net.*; +import java.nio.*; +import sleepchild.aupod22.models.*; + +public class MediaStoreUpdator +{ + public MediaStoreUpdator(){ + // + } + + public static void update(Context ctx, SongItem si, String artPath){ + ContentResolver cr = ctx.getContentResolver(); + ContentValues vals = new ContentValues(); + vals.put(MediaStore.Audio.Media.TITLE, si.title); + vals.put(MediaStore.Audio.Media.ARTIST, si.artist); + vals.put(MediaStore.Audio.Media.ALBUM, si.album); + if(si.icon!=null && si.artId!=0 && artPath!=null){ + Uri artworkUris = Uri.parse("content://media/external/audio/albumart"); + cr.delete(ContentUris.withAppendedId(artworkUris, si.artId), null, null); + + ContentValues cv = new ContentValues(); + cv.put("album_id",si.artId); + cv.put("_data", artPath); + cr.insert(artworkUris, cv); + } + Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + cr.update(uri,vals,MediaStore.Audio.Media._ID +" = ? " , new String[]{si.id}); + } +} diff --git a/aupod/src/sleepchild/aupod22/library/SongFactory.java b/aupod/src/sleepchild/aupod22/library/SongFactory.java new file mode 100644 index 0000000..d056803 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/library/SongFactory.java @@ -0,0 +1,178 @@ +package sleepchild.aupod22.library; + +import java.util.*; +import java.util.concurrent.*; +import java.io.*; +import android.provider.*; +import android.content.*; +import android.net.*; +import com.mpatric.mp3agic.*; +import android.graphics.*; +import android.os.*; +import android.media.*; +import sleepchild.aupod22.models.*; + +public class SongFactory +{ + private static volatile SongFactory deftInstance; + private ExecutorService worker; + private List eListeners = new ArrayList<>(); + public List songs = new ArrayList<>(); + + private SongFactory(){ + worker = Executors.newFixedThreadPool(3); + } + + public static SongFactory get(){ + SongFactory instance = deftInstance; + if(instance==null){ + synchronized(SongFactory.class){ + instance = SongFactory.deftInstance; + if(instance==null){ + instance = SongFactory.deftInstance = new SongFactory(); + } + } + } + return instance; + } + + public void submit(Runnable task){ + worker.submit(task); + } + + public SongFactory registerEventListener(FactoryEvents listener){ + eListeners.add(listener); + return this; + } + + public SongFactory unregisterEventListener(FactoryEvents listener){ + eListeners.remove(listener); + return this; + } + + public void getSongs(Context ctx){ + worker.submit(new GetSongListTask(ctx)); + } + + public static class GetSongListTask implements Runnable{ + List itemlist = new ArrayList<>(); + Context ctx; + + public GetSongListTask(Context ctx){ + this.ctx = ctx; + } + + @Override + public void run(){ + try{ + // + List sl = SongRetreiverCursor.get(ctx); + itemlist.addAll(sl); + Collections.sort(itemlist, new Comparator(){ + @Override + public int compare(SongItem p1, SongItem p2) { + return p1.title.toLowerCase().compareTo(p2.title.toLowerCase()); + } + }); + SongFactory.get().songs = itemlist; + SongFactory.get().notifyComplete(itemlist); + }catch (Exception e){ + SongFactory.get().notifyError(e.getMessage()); + MediaScannerConnection.scanFile(ctx, new String[]{"file:///sdcard/"}, new String[]{"audio/*"}, new MediaScannerConnection.OnScanCompletedListener(){ + @Override + public void onScanCompleted(String p1, Uri p2) + { + SongFactory.get().notifyError(p1); + } + // + }); + } + } + } + + // + public interface FactoryEvents{ + public void onGetSongsResult(List songlist); + public void onGetSongsError(String message); + } + + private void notifyComplete(List list){ + for(FactoryEvents l : eListeners){ + l.onGetSongsResult(list); + } + } + + private void notifyError(String message){ + for(FactoryEvents l : eListeners){ + l.onGetSongsError(message); + } + } + + /// + public void updateSong(SongItem si, UCB cb){ + worker.submit(new SongUpdateTask(si,cb)); + } + + private class SongUpdateTask implements Runnable{ + SongItem si; + UCB cb; + + public SongUpdateTask(SongItem si, UCB cb){ + this.si = si; + this.cb = cb; + } + + @Override + public void run() + { + si = r(si); + if(cb!=null){ + cb.onResult(si); + } + } + + private SongItem r(SongItem si){ + try{ + Mp3File m = new Mp3File(si.path); + ID3v2 v2 = m.getId3v2Tag(); + if(v2!=null){ + si.title = v2.getTitle(); + si.artist = v2.getArtist(); + byte[] art = v2.getAlbumImage(); + if(art!=null){ + si.icon = BitmapFactory.decodeByteArray(art,0,art.length); + } + }else{ + ID3v1 v1 = m.getId3v1Tag(); + if(v1!=null){ + si.title = v1.getTitle(); + si.artist = v1.getArtist(); + // + } + + } + + } + catch (UnsupportedTagException e) + {} + catch (InvalidDataException e) + {} + catch (IOException e) + {} + + if(si.title==null || si.title.isEmpty()){ + String t = new File(si.path).getName(); + si.title = t.substring(0, t.lastIndexOf(".")); + } + if(si.artist==null || si.artist.isEmpty()){ + si.artist = ""; + } + + return si; + } + + } + public static interface UCB{ + public void onResult(SongItem si); + } +} diff --git a/aupod/src/sleepchild/aupod22/library/SongLibrary.java b/aupod/src/sleepchild/aupod22/library/SongLibrary.java new file mode 100644 index 0000000..615cbf0 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/library/SongLibrary.java @@ -0,0 +1,103 @@ +package sleepchild.aupod22.library; + +import android.content.*; +import java.util.*; +import java.util.concurrent.*; +import sleepchild.aupod22.utils.*; +import android.os.*; +import sleepchild.aupod22.*; + +public class SongLibrary{ + // + private static volatile SongLibrary deftInstance; + + /* + * main list of songs + * this is the list we will use to resolve things like artists, albums, genres etc. + * + * note: thus we need to ensure it is always up-to-date + * prehaps by implementing some kind of directory/file watcher or a listener to mediastore updates + * + */ + private List songlist = new ArrayList<>(); + + // + private List artistList = new ArrayList<>(); + + // + private List albumList = new ArrayList<>(); + + private ExecutorService worker; + + private Handler handle = new Handler(Looper.getMainLooper()); + + /* + * track if ::discover() has been called at least once + */ + private volatile boolean discoverdOnce=false; + private static boolean isDiscovering=false; + + private SongLibrary(){ + worker = Executors.newFixedThreadPool(2); + } + + // ensure a single instance of this class (to some degree) + public static SongLibrary get(){ + SongLibrary inst = deftInstance; + if(inst==null){ + synchronized(SongLibrary.class){ + inst = SongLibrary.deftInstance; + if(inst==null){ + inst = SongLibrary.deftInstance = new SongLibrary(); + } + } + } + return inst; + } + + /* + * Begin a query for songs on the device from android.media.MediaStore. + * + * Idea--ly, this MUST be the first method to be called. + * and it should be done so as early as posible. + * for instance in the main/starting Activity's onstart method + * or if the android.app.Application class is used, it's onCreate method is a perhaps the best place. + * + */ + public void discover(final Context ctx){ + isDiscovering = true; + worker.submit(new Runnable(){ + public void run(){ + //final List l = new test().findmp3("/sdcard/"); + //+l.size()); + handle.post(new Runnable(){ + public void run(){ + //Utils.toast(ctx, ""+l.size()); + } + }); + } + }); + discoverdOnce=true; + } + + // returns the main list of songs found + public void getAllSongs(){ + // + //return songlist; + } + + // returns a list of Artists. + public void getAllArtists(){ + // + //return artistList; + } + + // retuns a list of albums found + public void getAllAlbums(){ + // + //return albumList; + } + + // return genres + +} diff --git a/aupod/src/sleepchild/aupod22/library/SongRetreiverCursor.java b/aupod/src/sleepchild/aupod22/library/SongRetreiverCursor.java new file mode 100644 index 0000000..58b3871 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/library/SongRetreiverCursor.java @@ -0,0 +1,58 @@ +package sleepchild.aupod22.library; + +import android.database.*; +import android.content.*; +import android.provider.*; +import java.util.*; +import android.net.*; +import sleepchild.aupod22.models.*; + +public class SongRetreiverCursor +{ + //Context ctx; + private SongRetreiverCursor(){ + //this.ctx = ctx; + } + + public static List get(Context ctx){ + if(ctx==null){return null;} + + List stitles = new ArrayList<>(); + + Uri suri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0"; + String sortOrder = MediaStore.Audio.Media.TITLE + " ASC"; + + Cursor c = ctx.getContentResolver().query( + suri, + null, + selection, + null, + sortOrder); + + if(c==null || c.getCount() ==0){ + return null; + } + c.moveToFirst(); + + do{ + SongItem si = new SongItem(); + + si.id = c.getString(c.getColumnIndex(MediaStore.Audio.Media._ID)); + si.title = c.getString(c.getColumnIndex(MediaStore.Audio.Media.TITLE)); + si.artist = c.getString(c.getColumnIndex(MediaStore.Audio.Media.ARTIST)); + si.path = c.getString(c.getColumnIndex(MediaStore.Audio.Media.DATA)); + si.album = c.getString(c.getColumnIndex(MediaStore.Audio.Media.ALBUM)); + si.duration = c.getInt(c.getColumnIndex(MediaStore.Audio.Media.DURATION)); + si.artId = c.getLong(c.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)); + + stitles.add(si); + // + }while(c.moveToNext()); + + c.close(); + + return stitles; + } + +} diff --git a/aupod/src/sleepchild/aupod22/library/test.java b/aupod/src/sleepchild/aupod22/library/test.java new file mode 100644 index 0000000..5f2ee1c --- /dev/null +++ b/aupod/src/sleepchild/aupod22/library/test.java @@ -0,0 +1,50 @@ +package sleepchild.aupod22.library; +import java.io.*; +import java.util.*; + +public class test +{ + public test(){ + // + } + + public List findmp3(String path){ + return findmp3(new File(path)); + } + + public List findmp3(File dir){ + List list = new ArrayList<>(); + if(dir.isDirectory()){ + for(File f : dir.listFiles()){ + if(isAudio(f)){ + list.add(new MP3(f)); + } + if(f.isDirectory()){ + list.addAll(findmp3(f)); + } + } + } + return list; + } + + String[] aext = new String[]{".mp3", ".wav", ".ogg"}; + boolean isAudio(File fl){ + if(fl.isDirectory()){ + return false; + } + String n = fl.getName().toLowerCase(); + for(String t : aext){ + if(n.endsWith(t)){ + return true; + } + } + return false; + } + + class MP3{ + File fl; + public MP3(File fl){ + this.fl = fl; + } + } +} diff --git a/aupod/src/sleepchild/aupod22/menu/ArtisItemOptions.java b/aupod/src/sleepchild/aupod22/menu/ArtisItemOptions.java new file mode 100644 index 0000000..a78abef --- /dev/null +++ b/aupod/src/sleepchild/aupod22/menu/ArtisItemOptions.java @@ -0,0 +1,20 @@ +package sleepchild.aupod22.menu; +import android.app.*; + +public class ArtisItemOptions{ + Dialog dlg; + Activity act; + + public ArtisItemOptions(Activity ctx){ + act = ctx; + dlg = new Dialog(ctx); + } + + public void show(){ + dlg.show(); + } + + public void dismiss(){ + dlg.dismiss(); + } +} diff --git a/aupod/src/sleepchild/aupod22/menu/ConfirmDeleteDialog.java b/aupod/src/sleepchild/aupod22/menu/ConfirmDeleteDialog.java new file mode 100644 index 0000000..2b40bc5 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/menu/ConfirmDeleteDialog.java @@ -0,0 +1,42 @@ +package sleepchild.aupod22.menu; +//import android.content.*; +import android.app.*; +import android.view.*; +import android.content.*; +import sleepchild.aupod22.models.*; + +public class ConfirmDeleteDialog +{ + String path; + Activity ctx; + AlertDialog dlg; + public ConfirmDeleteDialog(Activity ctx, SongItem si){ + this.ctx = ctx; + String a = si.artist==""? "": " - "+si.artist; + String msg = si.title+a; + dlg = new AlertDialog.Builder(ctx) + .setMessage(msg) + .setPositiveButton("Delete", new DialogInterface.OnClickListener(){ + @Override + public void onClick(DialogInterface p1, int p2) + { + // + } + }) + .setNegativeButton("cancel", new DialogInterface.OnClickListener(){ + @Override + public void onClick(DialogInterface p1, int p2) + { + // TODO: Implement this method + } + }) + .create(); + dlg.setTitle("Are you sure to delete"); + //dlg.getWindow().requestFeature(Window.FEATURE_NO_TITLE); + // + } + + public void show(){ + dlg.show(); + } +} diff --git a/aupod/src/sleepchild/aupod22/menu/CurrentSongOptions.java b/aupod/src/sleepchild/aupod22/menu/CurrentSongOptions.java new file mode 100644 index 0000000..57490b0 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/menu/CurrentSongOptions.java @@ -0,0 +1,32 @@ +package sleepchild.aupod22.menu; + +import android.app.Activity; +import sleepchild.aupod22.models.*; +import android.app.*; +import sleepchild.aupod22.*; +import android.view.*; + +public class CurrentSongOptions +{ + Activity act; + SongItem si; + + Dialog dlg; + + public CurrentSongOptions(Activity ctx, SongItem song){ + this.act = ctx; + this.si = song; + // + dlg = new Dialog(ctx); + dlg.getWindow().requestFeature(Window.FEATURE_NO_TITLE); + dlg.setContentView(R.layout.dlg_auplayer_options); + } + + public void show(){ + dlg.show(); + } + + public void dismiss(){ + dlg.dismiss(); + } +} diff --git a/aupod/src/sleepchild/aupod22/menu/SongOptions.java b/aupod/src/sleepchild/aupod22/menu/SongOptions.java new file mode 100644 index 0000000..b1902d1 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/menu/SongOptions.java @@ -0,0 +1,119 @@ +package sleepchild.aupod22.menu; + +import sleepchild.aupod22.activity.BaseActivity; +import android.content.*; +import android.widget.*; +import android.view.*; +import android.app.*; +import sleepchild.aupod22.models.SongItem; +import sleepchild.aupod22.activity.TagEditorActivity; +import sleepchild.aupod22.R; +import sleepchild.aupod22.*; +import sleepchild.aupod22.activity.*; +import sleepchild.postman.*; +import sleepchild.aupod22.models.*; + +public class SongOptions implements View.OnClickListener +{ + BaseActivity ctx; + SongItem si; + RelativeLayout container; + TextView title, artist; + Dialog dlg; + + + public SongOptions(BaseActivity ctx, SongItem si){ + this.ctx = ctx; + this.si = si; + dlg = new Dialog(ctx); + Window w = dlg.getWindow(); + w.requestFeature(Window.FEATURE_NO_TITLE); + + dlg.setContentView(R.layout.dlg_songitem_options); + // + title = ftv(R.id.popup_auplayer_songoptions_title); + artist = ftv(R.id.popup_auplayer_songoptions_artist); + + title.setText(si.title); + artist.setText(si.artist); + + LinearLayout ops = (LinearLayout) fv(R.id.popup_auplayer_songoptions_clk); + int cc = ops.getChildCount(); + for(int i=0;i=2){ + return p[1]; + } + return null; + } + + private String[] getValues(View v){ + if(v.getTag()!=null && (v.getTag() instanceof String)){ + String t = v.getTag().toString(); + String[] p = t.split(" "); + return p; + } + return null; + } + + private View fv(int resid){ + return dlg.findViewById(resid); + } + + private TextView ftv(int resid){ + return (TextView) fv(resid); + } + + + public void show(){ + dlg.show(); + } + + public void hide(){ + dlg.dismiss(); + title.setText(""); + artist.setText(""); + si = null; + } + + @Override + public void onClick(View v) + { + if(v.getTag()!=null){ + String tag = v.getTag().toString(); + if(tag!=null){ + tag = tag.split(" ")[0]; + } + switch(tag){ + case "playnext": + // + break; + case "addtoplaylist": + // + break; + case "editfiletags": + TagEditorActivity.start(ctx, si); + break; + case "deletesong": + new ConfirmDeleteDialog(ctx, si).show(); + break; + case "exit": + AudioService.quit(ctx); + ctx.finishAffinity(); + break; + /* + case "": + // + break; + //*/ + } + } + hide(); + } + +} diff --git a/aupod/src/sleepchild/aupod22/models/PlaybackRequest.java b/aupod/src/sleepchild/aupod22/models/PlaybackRequest.java new file mode 100644 index 0000000..c314af2 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/models/PlaybackRequest.java @@ -0,0 +1,24 @@ +package sleepchild.aupod22.models; + +public class PlaybackRequest{ + + public static class TYPE{ + public static final int PLAY_SONGITEM = 371; + public static final int RESUME = 372; + public static final int PAUSE = 373; + public static final int STOP = 377; + public static final int DELETE = 988; + } + + private int mType; + public Object object; + + public PlaybackRequest(int type, Object obj){ + this.mType = type; + this.object = obj; + } + + public int getType(){ + return mType; + } +} diff --git a/aupod/src/sleepchild/aupod22/models/SongItem.java b/aupod/src/sleepchild/aupod22/models/SongItem.java new file mode 100644 index 0000000..af9d88e --- /dev/null +++ b/aupod/src/sleepchild/aupod22/models/SongItem.java @@ -0,0 +1,24 @@ +package sleepchild.aupod22.models; + +import android.graphics.Bitmap; + +public class SongItem +{ + public String id=""; + public String title=""; + public String artist=""; + public String path=""; + public String album=""; + public long duration=0; + public Bitmap icon=null; + public boolean updated=false; + public long artId; + + public SongItem(){ + // + } + + public SongItem(String path){ + this.path = path; + } +} diff --git a/aupod/src/sleepchild/aupod22/models/events/AudioServiceConnect.java b/aupod/src/sleepchild/aupod22/models/events/AudioServiceConnect.java new file mode 100644 index 0000000..5966e96 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/models/events/AudioServiceConnect.java @@ -0,0 +1,10 @@ +package sleepchild.aupod22.models.events; + +import sleepchild.aupod22.*; + +public class AudioServiceConnect{ + public AudioService service; + public AudioServiceConnect(AudioService service){ + this.service = service; + } +} diff --git a/aupod/src/sleepchild/aupod22/models/events/SongChangedEvent.java b/aupod/src/sleepchild/aupod22/models/events/SongChangedEvent.java new file mode 100644 index 0000000..894105b --- /dev/null +++ b/aupod/src/sleepchild/aupod22/models/events/SongChangedEvent.java @@ -0,0 +1,13 @@ +package sleepchild.aupod22.models.events; + +import sleepchild.aupod22.models.SongItem; + +public class SongChangedEvent{ + private SongItem si; + public SongChangedEvent(SongItem si){ + this.si = si; + } + public SongItem getSong(){ + return si; + } +} diff --git a/aupod/src/sleepchild/aupod22/models/events/SongCompletionEvent.java b/aupod/src/sleepchild/aupod22/models/events/SongCompletionEvent.java new file mode 100644 index 0000000..02ade80 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/models/events/SongCompletionEvent.java @@ -0,0 +1,15 @@ +package sleepchild.aupod22.models.events; + +import sleepchild.aupod22.models.SongItem; + +public class SongCompletionEvent +{ + private SongItem si; + public SongCompletionEvent(SongItem si){ + this.si = si; + } + // return the song that just completed + public SongItem getCompletedSong(){ + return si; + } +} diff --git a/aupod/src/sleepchild/aupod22/models/events/SongInfoChangedEvent.java b/aupod/src/sleepchild/aupod22/models/events/SongInfoChangedEvent.java new file mode 100644 index 0000000..ba5f3fb --- /dev/null +++ b/aupod/src/sleepchild/aupod22/models/events/SongInfoChangedEvent.java @@ -0,0 +1,11 @@ +package sleepchild.aupod22.models.events; + +import sleepchild.aupod22.models.SongItem; + +public class SongInfoChangedEvent +{ + public SongItem songitem; + public SongInfoChangedEvent(SongItem si){ + this.songitem = si; + } +} diff --git a/aupod/src/sleepchild/aupod22/models/events/SongPauseEvent.java b/aupod/src/sleepchild/aupod22/models/events/SongPauseEvent.java new file mode 100644 index 0000000..80ad4be --- /dev/null +++ b/aupod/src/sleepchild/aupod22/models/events/SongPauseEvent.java @@ -0,0 +1,11 @@ +package sleepchild.aupod22.models.events; + +import sleepchild.aupod22.models.SongItem; + +public class SongPauseEvent +{ + public SongItem songitem; + public SongPauseEvent(SongItem songitem){ + this.songitem = songitem; + } +} diff --git a/aupod/src/sleepchild/aupod22/models/events/SongResumeEvent.java b/aupod/src/sleepchild/aupod22/models/events/SongResumeEvent.java new file mode 100644 index 0000000..aa51379 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/models/events/SongResumeEvent.java @@ -0,0 +1,11 @@ +package sleepchild.aupod22.models.events; + +import sleepchild.aupod22.models.SongItem; + +public class SongResumeEvent +{ + public SongItem songitem; + public SongResumeEvent(SongItem songitem){ + this.songitem = songitem; + } +} diff --git a/aupod/src/sleepchild/aupod22/models/events/SongsListReadyEvent.java b/aupod/src/sleepchild/aupod22/models/events/SongsListReadyEvent.java new file mode 100644 index 0000000..bd78850 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/models/events/SongsListReadyEvent.java @@ -0,0 +1,12 @@ +package sleepchild.aupod22.models.events; + +import java.util.List; +import sleepchild.aupod22.models.*; + +public class SongsListReadyEvent +{ + public List songList; + public SongsListReadyEvent(List songlist){ + this.songList = songlist; + } +} diff --git a/aupod/src/sleepchild/aupod22/recievers/ButtonReciever.java b/aupod/src/sleepchild/aupod22/recievers/ButtonReciever.java new file mode 100644 index 0000000..9e4b5da --- /dev/null +++ b/aupod/src/sleepchild/aupod22/recievers/ButtonReciever.java @@ -0,0 +1,30 @@ +package sleepchild.aupod22.recievers; + +import android.content.*; +import android.view.*; +import sleepchild.aupod22.*; + +public class ButtonReciever extends BroadcastReceiver { + @Override + public void onReceive(final Context ctx, Intent intent) + { + String act = intent.getAction(); + switch(act){ + case Intent.ACTION_MEDIA_BUTTON: + KeyEvent evt = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); + if(evt!=null){ + int action = evt.getAction(); + switch(evt.getKeyCode()){ + case KeyEvent.KEYCODE_HEADSETHOOK: + if(action == KeyEvent.ACTION_DOWN){ + Intent i = new Intent(ctx, AudioService.class); + i.setAction(AudioService.CMD_MEDIA_BUTTON); + ctx.startService(i); + } + break; + } + } + break; + } + } +} diff --git a/aupod/src/sleepchild/aupod22/tabs/AlbumsTab.java b/aupod/src/sleepchild/aupod22/tabs/AlbumsTab.java new file mode 100644 index 0000000..4f13872 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/tabs/AlbumsTab.java @@ -0,0 +1,24 @@ +package sleepchild.aupod22.tabs; +import sleepchild.aupod22.*; +import android.view.*; +import android.widget.*; +import sleepchild.view.tabview.Tab; +import sleepchild.aupod22.activity.*; + +public class AlbumsTab extends Tab +{ + MainActivity act; + View root; + ListView list1; + + public AlbumsTab(MainActivity act){ + this.act = act; + root = LayoutInflater.from(act).inflate(R.layout.list_view,null,false); + list1 = (ListView) root.findViewById(R.id.list_view_list1); + } + + @Override + public View getView(){ + return root; + } +} diff --git a/aupod/src/sleepchild/aupod22/tabs/ArtistTab.java b/aupod/src/sleepchild/aupod22/tabs/ArtistTab.java new file mode 100644 index 0000000..76a654b --- /dev/null +++ b/aupod/src/sleepchild/aupod22/tabs/ArtistTab.java @@ -0,0 +1,66 @@ +package sleepchild.aupod22.tabs; + +import android.view.View; +import android.view.LayoutInflater; +import sleepchild.aupod22.activity.MainActivity; +import android.widget.ListView; +import sleepchild.view.tabview.Tab; +import sleepchild.aupod22.adapters.ArtistsListAdapter; +import java.util.List; +import sleepchild.aupod22.models.SongItem; +import sleepchild.aupod22.library.SongFactory; +import sleepchild.aupod22.R; + +public class ArtistTab extends Tab { + + MainActivity act; + View root; + ListView list1; + ArtistsListAdapter adapter; + boolean t1; + + public ArtistTab(MainActivity act){ + this.act = act; + root = LayoutInflater.from(act).inflate(R.layout.list_view,null,false); + list1 = (ListView) root.findViewById(R.id.list_view_list1); + adapter = new ArtistsListAdapter(act); + list1.setAdapter(adapter); + list1.setBackgroundResource(R.color.black); + } + + public void update(List list){ + adapter.update(list); + } + + @Override + public View getView(){ + return root; + } + + @Override + public void onTabShown() + { + if(!t1){ + t1 = true; + if(SongFactory.get().songs!=null){ + update(SongFactory.get().songs); + } + } + super.onTabShown(); + } + + @Override + public void onTabHidden() + { + // TODO: Implement this method + super.onTabHidden(); + } + + @Override + public void onTabAlreadyVisible() + { + // TODO: Implement this method + super.onTabAlreadyVisible(); + } + +} diff --git a/aupod/src/sleepchild/aupod22/tabs/PlaylistsTab.java b/aupod/src/sleepchild/aupod22/tabs/PlaylistsTab.java new file mode 100644 index 0000000..c16bb0b --- /dev/null +++ b/aupod/src/sleepchild/aupod22/tabs/PlaylistsTab.java @@ -0,0 +1,25 @@ +package sleepchild.aupod22.tabs; + +import android.view.*; +import android.widget.*; +import sleepchild.view.tabview.*; +import sleepchild.aupod22.activity.MainActivity; +import sleepchild.aupod22.R; + +public class PlaylistsTab extends Tab +{ + MainActivity act; + View root; + ListView list1; + + public PlaylistsTab(MainActivity act){ + this.act = act; + root = LayoutInflater.from(act).inflate(R.layout.list_view,null,false); + list1 = (ListView) root.findViewById(R.id.list_view_list1); + } + + @Override + public View getView(){ + return root; + } +} diff --git a/aupod/src/sleepchild/aupod22/tabs/SongsListTab.java b/aupod/src/sleepchild/aupod22/tabs/SongsListTab.java new file mode 100644 index 0000000..0b52f8e --- /dev/null +++ b/aupod/src/sleepchild/aupod22/tabs/SongsListTab.java @@ -0,0 +1,79 @@ +package sleepchild.aupod22.tabs; + +import android.view.*; +import android.content.*; +import android.widget.*; +import java.util.*; +import sleepchild.postman.PostMan; +import sleepchild.aupod22.models.*; +import sleepchild.aupod22.*; +import sleepchild.view.tabview.Tab; +import sleepchild.aupod22.adapters.*; +import sleepchild.aupod22.activity.*; + +public class SongsListTab extends Tab +{ + private View root; + private SongListAdaptor adapter; + private SongItem currentSong; + private ListView list1; + //MainActivity act; + + //* + public SongsListTab(MainActivity ctx){ + //act = ctx; + root = LayoutInflater.from(ctx).inflate(R.layout.list_view, null, false); + list1 = (ListView) root.findViewById(R.id.list_view_list1); + adapter = new SongListAdaptor(ctx); + list1.setAdapter(adapter); + //list1.setFastScrollEnabled(true); + //list1.setScrollbarFadingEnabled(false); + //list1.setFastScrollAlwaysVisible(true); + //list1.setScrollBarStyle(R.style.scrollbarstyles); + list1.setOnItemClickListener(new AdapterView.OnItemClickListener(){ + @Override + public void onItemClick(AdapterView p1, View v, int pos, long p4){ + SongItem si = (SongItem) v.getTag(); + PostMan.getInstance().post(new PlaybackRequest(PlaybackRequest.TYPE.PLAY_SONGITEM, si)); + } + }); + } + //*/ + + public void update(List list){ + adapter.update(list); + } + + public void setCurrent(SongItem currentSong){ + adapter.setCurrent(currentSong); + this.currentSong = currentSong; + } + + public void showCurrent(){ + if(currentSong!=null){ + list1.setSelection(adapter.getPos(currentSong)); + } + } + + @Override + public void onTabShown(){ + super.onTabShown(); + } + + @Override + public void onTabAlreadyVisible(){ + super.onTabAlreadyVisible(); + showCurrent(); + } + + @Override + public void onTabHidden(){ + super.onTabHidden(); + } + + @Override + public View getView(){ + return root; + } + +} diff --git a/aupod/src/sleepchild/aupod22/tasks/UpdateSongListTask.java b/aupod/src/sleepchild/aupod22/tasks/UpdateSongListTask.java new file mode 100644 index 0000000..f0b788d --- /dev/null +++ b/aupod/src/sleepchild/aupod22/tasks/UpdateSongListTask.java @@ -0,0 +1,62 @@ +package sleepchild.aupod22.tasks; +import android.os.*; +import android.content.*; +import sleepchild.aupod22.*; +import java.util.*; +import com.mpatric.mp3agic.*; +import java.io.*; +import android.graphics.*; +import sleepchild.aupod22.models.*; + +public class UpdateSongListTask extends AsyncTask> +{ + List songlist = new ArrayList<>(); + AudioService audios; + + public UpdateSongListTask(AudioService service, List oldlist){ + this.songlist = oldlist; + this.audios = service; + } + + @Override + protected List doInBackground(Void[] p1) + { + for(SongItem si : songlist){ + si = update(si); + } + return songlist; + } + + private SongItem update(SongItem si){ + try + { + Mp3File mp3 = new Mp3File(si.path); + if(mp3.hasId3v2Tag()){ + ID3v2 v2 = mp3.getId3v2Tag(); + String t = v2.getTitle(); + if(t!=null && !t.isEmpty()){ + // + } + byte[] art = v2.getAlbumImage(); + if(art!=null){ + si.icon = BitmapFactory.decodeByteArray(art,0,art.length); + } + } + } + catch (InvalidDataException e) + {} + catch (UnsupportedTagException e) + {} + catch (IOException e) + {} + return si; + } + + @Override + protected void onPostExecute(List result) + { + audios.onSongListUpdated(result); + super.onPostExecute(result); + } + +} diff --git a/aupod/src/sleepchild/aupod22/utils/FastBlur.java b/aupod/src/sleepchild/aupod22/utils/FastBlur.java new file mode 100644 index 0000000..a8b74aa --- /dev/null +++ b/aupod/src/sleepchild/aupod22/utils/FastBlur.java @@ -0,0 +1,214 @@ +package sleepchild.aupod22.utils; + +import android.graphics.*; + +public class FastBlur +{ + public static Bitmap fastblur(Bitmap sentBitmap, float scale, int radius) { + + int width = Math.round(sentBitmap.getWidth() * scale); + int height = Math.round(sentBitmap.getHeight() * scale); + sentBitmap = Bitmap.createScaledBitmap(sentBitmap, width, height, false); + + Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); + + if (radius < 1) { + return (null); + } + + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + + int[] pix = new int[w * h]; + //Log.e("pix", w + " " + h + " " + pix.length); + bitmap.getPixels(pix, 0, w, 0, 0, w, h); + + int wm = w - 1; + int hm = h - 1; + int wh = w * h; + int div = radius + radius + 1; + + int r[] = new int[wh]; + int g[] = new int[wh]; + int b[] = new int[wh]; + int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; + int vmin[] = new int[Math.max(w, h)]; + + int divsum = (div + 1) >> 1; + divsum *= divsum; + int dv[] = new int[256 * divsum]; + for (i = 0; i < 256 * divsum; i++) { + dv[i] = (i / divsum); + } + + yw = yi = 0; + + int[][] stack = new int[div][3]; + int stackpointer; + int stackstart; + int[] sir; + int rbs; + int r1 = radius + 1; + int routsum, goutsum, boutsum; + int rinsum, ginsum, binsum; + + for (y = 0; y < h; y++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + for (i = -radius; i <= radius; i++) { + p = pix[yi + Math.min(wm, Math.max(i, 0))]; + sir = stack[i + radius]; + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + rbs = r1 - Math.abs(i); + rsum += sir[0] * rbs; + gsum += sir[1] * rbs; + bsum += sir[2] * rbs; + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + } + stackpointer = radius; + + for (x = 0; x < w; x++) { + + r[yi] = dv[rsum]; + g[yi] = dv[gsum]; + b[yi] = dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (y == 0) { + vmin[x] = Math.min(x + radius + 1, wm); + } + p = pix[yw + vmin[x]]; + + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[(stackpointer) % div]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi++; + } + yw += w; + } + for (x = 0; x < w; x++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + yp = -radius * w; + for (i = -radius; i <= radius; i++) { + yi = Math.max(0, yp) + x; + + sir = stack[i + radius]; + + sir[0] = r[yi]; + sir[1] = g[yi]; + sir[2] = b[yi]; + + rbs = r1 - Math.abs(i); + + rsum += r[yi] * rbs; + gsum += g[yi] * rbs; + bsum += b[yi] * rbs; + + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + + if (i < hm) { + yp += w; + } + } + yi = x; + stackpointer = radius; + for (y = 0; y < h; y++) { + // Preserve alpha channel: ( 0xff000000 & pix[yi] ) + pix[yi] = ( 0xff000000 & pix[yi] ) | ( dv[rsum] << 16 ) | ( dv[gsum] << 8 ) | dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (x == 0) { + vmin[y] = Math.min(y + r1, hm) * w; + } + p = x + vmin[y]; + + sir[0] = r[p]; + sir[1] = g[p]; + sir[2] = b[p]; + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[stackpointer]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi += w; + } + } + + //Log.e("pix", w + " " + h + " " + pix.length); + bitmap.setPixels(pix, 0, w, 0, 0, w, h); + + return (bitmap); + } +} diff --git a/aupod/src/sleepchild/aupod22/utils/Noteaf.java b/aupod/src/sleepchild/aupod22/utils/Noteaf.java new file mode 100644 index 0000000..a0e9e80 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/utils/Noteaf.java @@ -0,0 +1,63 @@ +package sleepchild.aupod22.utils; + +import android.app.*; +import android.content.*; +import android.media.session.*; +import android.graphics.*; +import android.widget.RemoteViews; +import android.widget.*; +import android.graphics.drawable.*; +import sleepchild.aupod22.activity.*; +import sleepchild.aupod22.models.*; +import sleepchild.aupod22.*; + +public class Noteaf{ + private Noteaf(){} + + public static Notification get(Context ctx, SongItem song, boolean isPlaying){ + Notification.Builder b = new Notification.Builder(ctx); + b.setSmallIcon(R.drawable.ic_launcher) + .setContentTitle(song.title) + .setContentText(song.artist) + .setOngoing(isPlaying) + .setShowWhen(false) + .setLargeIcon(song.icon) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setPriority(Notification.PRIORITY_MAX) + .setContentIntent(getContentIntent(ctx)); + + b.setColor(ctx.getResources().getColor(R.color.pluto)); + + if(song.icon==null){ + b.setLargeIcon(BitmapFactory.decodeResource(ctx.getResources(),R.drawable.fallback_cover)); + } + + b.addAction(R.drawable.ic_prev_24px,"prev",getActionIntent(ctx, AudioService.CMD_PLAY_PREV)); + if(isPlaying){ + b.addAction(R.drawable.ic_pause_24px,"pause",getActionIntent(ctx, AudioService.CMD_PAUSE)); + }else{ + b.addAction(R.drawable.ic_play_24px,"play", getActionIntent(ctx, AudioService.CMD_PLAY)); + } + b.addAction(R.drawable.ic_next_24px, "next", getActionIntent(ctx, AudioService.CMD_PLAY_NEXT)); + b.setStyle( + new Notification.MediaStyle() + .setShowActionsInCompactView(new int[]{0,1,2}) + ); + + return b.build(); + } + + private static PendingIntent getActionIntent(Context ctx, String action){ + Intent i = new Intent(ctx, AudioService.class); + i.setAction(action); + return PendingIntent.getService(ctx, AudioService.REQUEST_CODE, i ,0); + } + + private static PendingIntent getContentIntent(Context ctx){ + return PendingIntent.getActivity( + ctx, + MainActivity.REQUEST_CODE, + new Intent(ctx, PlayerActivity.class), + Intent.FLAG_ACTIVITY_CLEAR_TOP); + } +} diff --git a/aupod/src/sleepchild/aupod22/utils/SPrefs.java b/aupod/src/sleepchild/aupod22/utils/SPrefs.java new file mode 100644 index 0000000..a0611c4 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/utils/SPrefs.java @@ -0,0 +1,99 @@ +package sleepchild.aupod22.utils; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +public class SPrefs{ + public Context ctx; + SharedPreferences pref; + SharedPreferences.Editor edit; + + /// keys .. + private enum K{ + LAST_PLAYING_SONG_PATH, + LAST_PLAYING_SONG_TIME_POSITION, + APP_THEME, + BG_COLOR, + TEXT_COLOR_P, + TEXT_COLOR_S + } + + public SPrefs(Context ctx){ + this.ctx = ctx; + pref = PreferenceManager.getDefaultSharedPreferences(ctx); + edit = pref.edit(); + } + + // remember the last song to play + // todo: this should be a user option + public String getLastPath(){ + return getString(K.LAST_PLAYING_SONG_PATH,""); + } + + public void saveLastPath(String path){ + saveString(K.LAST_PLAYING_SONG_PATH,path); + } + + // remember track pos of last song to play + // todo: this should be a user option + public void setPos(int pos){ + saveInt(K.LAST_PLAYING_SONG_TIME_POSITION,pos); + } + + public int getPos(){ + return getInt(K.LAST_PLAYING_SONG_TIME_POSITION,0); + } + + ////// app theme + //background color + public int getBackgroundColor(){ + return getInt(K.BG_COLOR, 0); + } + + public void setBackgroundColor(int color){ + saveInt(K.BG_COLOR,color); + } + + //primary text color + + //secondary text color + + + + + //||||||| helper methods ||||||\\ + + // enum K to String + private String k2s(K key){ + return key.toString(); + } + + // string + private String getString(K key, String deft){ + return pref.getString(k2s(key), deft); + } + + private void saveString(K key, String value){ + edit.putString(k2s(key), value).commit(); + } + + // Integer + private int getInt(K key, int deft){ + return pref.getInt(k2s(key), deft); + } + + private void saveInt(K key, int value){ + edit.putInt(k2s(key), value).commit(); + } + + // boolean + private boolean getBool(K key, boolean deft){ + return pref.getBoolean(k2s(key), deft); + } + + private void saveBool(K key, boolean value){ + edit.putBoolean(k2s(key), value).commit(); + } + +} diff --git a/aupod/src/sleepchild/aupod22/utils/SearchHelper.java b/aupod/src/sleepchild/aupod22/utils/SearchHelper.java new file mode 100644 index 0000000..e1f316c --- /dev/null +++ b/aupod/src/sleepchild/aupod22/utils/SearchHelper.java @@ -0,0 +1,65 @@ +package sleepchild.aupod22.utils; +import java.util.*; +import android.os.*; +import java.util.concurrent.*; + +public class SearchHelper +{ + Handler handle = new Handler(Looper.getMainLooper()); + ExecutorService worker; + Thread mThread; + + private static SearchHelper deft; + private SearchHelper(){ + worker = Executors.newSingleThreadExecutor(); + } + + private static SearchHelper get(){ + SearchHelper inst = deft; + if(inst==null){ + synchronized(SearchHelper.class){ + inst = SearchHelper.deft; + if(inst==null){ + inst = SearchHelper.deft = new SearchHelper(); + } + } + } + return inst; + } + + + // todo: find a way to stop the thread when a new query comes in + private void search_(final String query, ResultCallback cb){ + worker.submit(new SearchTask(query, cb)); + } + + private class SearchTask implements Runnable{ + ResultCallback cb; + String sQuery; + public SearchTask(String query, ResultCallback cb){ + this.sQuery = query; + this.cb = cb; + } + + public void run(){ + // + final List l2 = new ArrayList<>(); + // search logic + // + handle.postDelayed(new Runnable(){ + public void run(){ + cb.onSearchResult(l2); + } + },1); + } + } + + public static void serch(String query, ResultCallback cb){ + get().search_(query, cb); + } + + public static interface ResultCallback{ + public void onSearchResult(List list); + } + +} diff --git a/aupod/src/sleepchild/aupod22/utils/SearchResult.java b/aupod/src/sleepchild/aupod22/utils/SearchResult.java new file mode 100644 index 0000000..ea43c54 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/utils/SearchResult.java @@ -0,0 +1,8 @@ +package sleepchild.aupod22.utils; + +public class SearchResult +{ + public SearchResult(){ + // + } +} diff --git a/aupod/src/sleepchild/aupod22/utils/Utils.java b/aupod/src/sleepchild/aupod22/utils/Utils.java new file mode 100644 index 0000000..55ba827 --- /dev/null +++ b/aupod/src/sleepchild/aupod22/utils/Utils.java @@ -0,0 +1,39 @@ +package sleepchild.aupod22.utils; + +import android.content.*; +import android.widget.Toast; +import java.io.FileOutputStream; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import java.io.FileNotFoundException; +import java.io.IOException; +import android.renderscript.RenderScript; +import android.renderscript.*; + +public class Utils +{ + public static void toast(Context ctx, String msg){ + Toast.makeText(ctx, msg, 500).show(); + } + + public static void log(String msg){ + try + { + FileOutputStream out = new FileOutputStream("/sdcard/aupodlog.txt"); + out.write(msg.getBytes()); + out.flush(); + out.close(); + } + catch (FileNotFoundException e) + {}catch(IOException e){} + } + + public static Drawable bmpToDrawable(Context ctx, Bitmap bmp){ + return new BitmapDrawable(ctx.getResources(), bmp); + } + + void blur(){ + // + } +} diff --git a/aupod/src/sleepchild/postman/PostEvent.java b/aupod/src/sleepchild/postman/PostEvent.java new file mode 100644 index 0000000..d658442 --- /dev/null +++ b/aupod/src/sleepchild/postman/PostEvent.java @@ -0,0 +1,11 @@ +package sleepchild.postman; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +// +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface PostEvent{ +} diff --git a/aupod/src/sleepchild/postman/PostMan.java b/aupod/src/sleepchild/postman/PostMan.java new file mode 100644 index 0000000..c76394c --- /dev/null +++ b/aupod/src/sleepchild/postman/PostMan.java @@ -0,0 +1,149 @@ +package sleepchild.postman; + +import java.util.*; +import java.lang.reflect.*; +import android.content.*; +import android.widget.*; +import java.util.concurrent.*; + + +public class PostMan{ + // + private volatile static PostMan deftInstance; + /* + / holds a list of subscribers and ther subscribed subscriptions ;) + / the subscription is basicly an object with info abt the type and method of the subscription + */ + Map> subscriberMap = new HashMap>(); + + + // infomation abt a single subscription + // the subscriber is currently subscribed to + class SubInfo{ + public Class type; // the param type of the sub + public Method method; // the method to which the type is registered + } + + // recomendation: use {@link #getInstance} instead + PostMan(){ + this("DEFAULTS"); + } + PostMan(String options){ + //do sth w/ the options + //subscriberMap = new HashMap>(); + } + + // singleton for process-wide access + public static PostMan getInstance(){ + PostMan instance = deftInstance; + if(instance==null){ + synchronized (PostMan.class){ + instance = PostMan.deftInstance; + if(instance==null){ + instance = PostMan.deftInstance = new PostMan(); + } + } + } + return instance; + } + + public void register(Object subscriber){ + List subscriberMethods = getQualifyngMethods(subscriber); + if(subscriberMethods!=null){ + synchronized(this){ + for(Method method : subscriberMethods){ + Class[] paramtype = method.getParameterTypes(); + if(paramtype.length==1){ + addSubsBySubscriber(subscriber,paramtype[0], method); + } + } + } + } + } + + //public static void postt(){ + //getInstance().post(""); + //} + + public void post(Object event){ + // + Class eventType = event.getClass(); + Set sublist = subscriberMap.keySet(); + // loop through each subscriber's subscriptions and + // find a matching handler method for the event class + for(Object sub : sublist){ + List subinfos = subscriberMap.get(sub); + for(SubInfo si : subinfos ){ + if(eventType.equals(si.type)){ + postSingleEvent(sub,si.method,event); + } + } + } + } + + + public synchronized void unregister(Object subscriber){ + List subinfo = subscriberMap.remove(subscriber); + // TODO: lwhat to do with subinfo ? + } + + /////////// + /// private Methods + /////////// + + /* + | + */ + private List getQualifyngMethods(Object subscriber){ + List collect = new ArrayList(); + for(Method sm : subscriber.getClass().getMethods()){ + if(sm.getAnnotation(PostEvent.class) != null){ + collect.add(sm); + } + } + if (collect.isEmpty()){ + return null; + } + return collect; + } + + /* + / to be called in syncronised + */ + private void addSubsBySubscriber(Object subscriber, Class type, Method method){ + // + List subscriptions = subscriberMap.get(subscriber); + if(subscriptions==null){ + subscriptions = new ArrayList(); + subscriberMap.put(subscriber, subscriptions); + } + SubInfo subinfo = new SubInfo();// aka subscription + subinfo.type = type; + subinfo.method = method; + // + subscriptions.add(subinfo); + // + } + + /* + | + */ + + private void postSingleEvent(final Object subscriber, final Method method, final Object event){ + // TODO: + //* + try + { + method.invoke(subscriber, event); + } + catch (InvocationTargetException e) + {} + catch (IllegalAccessException e) + {} + catch (IllegalArgumentException e) + {} + //*/ + } + + +} diff --git a/aupod/src/sleepchild/view/ColorTextView.java b/aupod/src/sleepchild/view/ColorTextView.java new file mode 100644 index 0000000..6389c21 --- /dev/null +++ b/aupod/src/sleepchild/view/ColorTextView.java @@ -0,0 +1,5 @@ +package sleepchild.view; + +public class ColorTextView +{ +} \ No newline at end of file diff --git a/aupod/src/sleepchild/view/ContainerLayout.java b/aupod/src/sleepchild/view/ContainerLayout.java new file mode 100644 index 0000000..3fbb171 --- /dev/null +++ b/aupod/src/sleepchild/view/ContainerLayout.java @@ -0,0 +1,49 @@ +package sleepchild.view; +import android.widget.*; +import android.content.*; +import android.util.*; +import sleepchild.aupod22.*; +import sleepchild.aupod22.utils.*; + +public class ContainerLayout extends RelativeLayout +{ + public ContainerLayout(Context ctx){ + super(ctx); + init(); + } + + public ContainerLayout(Context ctx, AttributeSet attrs){ + super(ctx, attrs); + init(); + } + + public ContainerLayout(Context ctx, AttributeSet attrs, int defStyleAttr){ + super(ctx, attrs, defStyleAttr); + init(); + } + + public ContainerLayout(Context ctx, AttributeSet attrs, int defStyleAttr, int defStyleRes){ + super(ctx, attrs, defStyleAttr, defStyleRes); + init(); + } + + SPrefs pref; + Context ctx; + + private void init(){ + // + ctx = getContext(); + pref = new SPrefs(ctx); + + setBackgroundColor(); + + } + + public void setBackgroundColor(){ + int col = pref.getBackgroundColor(); + if(col==0){ + col = getResources().getColor(R.color.pluto); + } + //setBackgroundColor(col); + } +} diff --git a/aupod/src/sleepchild/view/RoundedImageView.java b/aupod/src/sleepchild/view/RoundedImageView.java new file mode 100644 index 0000000..50277f9 --- /dev/null +++ b/aupod/src/sleepchild/view/RoundedImageView.java @@ -0,0 +1,73 @@ +package sleepchild.view; + +import android.widget.*; +import android.content.*; +import android.util.*; +import android.graphics.drawable.*; +import android.graphics.*; + +public class RoundedImageView extends ImageView +{ + public RoundedImageView(Context ctx){ + super(ctx); + init(); + } + + public RoundedImageView(Context ctx, AttributeSet attrs){ + super(ctx, attrs); + init(); + } + + public RoundedImageView(Context ctx, AttributeSet attrs, int defStyleAttr){ + super(ctx, attrs, defStyleAttr); + init(); + } + + public RoundedImageView(Context ctx, AttributeSet attrs, int defStyleAttr, int defStyleRes){ + super(ctx, attrs, defStyleAttr, defStyleRes); + init(); + } + + private void init(){ + + } + + @Override + public void setBackground(Drawable background) + { + // TODO: Implement this method + super.setBackground(background); + } + + @Override + public void setBackgroundDrawable(Drawable background) + { + // TODO: Implement this method + super.setBackgroundDrawable(background); + } + + @Override + public void setBackgroundResource(int resid) + { + // TODO: Implement this method + super.setBackgroundResource(resid); + } + + @Override + public void setBackgroundColor(int color) + { + // TODO: Implement this method + super.setBackgroundColor(color); + } + + private void setBG(){ + GradientDrawable gd = new GradientDrawable(); + gd.setStroke(5, Util.getColor("")); + gd.setCornerRadius(20); + + super.setBackground(gd); + } + + + +} diff --git a/aupod/src/sleepchild/view/RoundedLinearLayout.java b/aupod/src/sleepchild/view/RoundedLinearLayout.java new file mode 100644 index 0000000..fc8214f --- /dev/null +++ b/aupod/src/sleepchild/view/RoundedLinearLayout.java @@ -0,0 +1,109 @@ +package sleepchild.view; +import android.content.*; +import android.util.*; +import android.widget.*; +import android.graphics.drawable.*; +import android.graphics.*; +import sleepchild.aupod22.*; +import android.content.res.*; + +public class RoundedLinearLayout extends LinearLayout +{ + int colorBG=0; + int mRadius=20; + RectF bounds; + Context ctx; + Paint mPaint; + int border=5; + + public RoundedLinearLayout(Context ctx){ + super(ctx); + init(); + } + + public RoundedLinearLayout(Context ctx, AttributeSet attrs){ + this(ctx, attrs,0); + } + + public RoundedLinearLayout(Context ctx, AttributeSet attrs, int defStyleAttr){ + super(ctx, attrs, defStyleAttr); + init(); + setAttrs(attrs); + } + + public RoundedLinearLayout(Context ctx, AttributeSet attrs, int defStyleAttr, int defStyleRes){ + super(ctx, attrs, defStyleAttr, defStyleRes); + init(); + setAttrs(attrs); + } + + void setAttrs(AttributeSet attrs){ + TypedArray a = ctx.getTheme().obtainStyledAttributes(attrs, R.styleable.RoundedLinearLayout, 0 ,0); + colorBG = a.getColor(R.styleable.RoundedLinearLayout_bgColor, colorBG); + mRadius = a.getDimensionPixelSize(R.styleable.RoundedLinearLayout_radius,mRadius); + border = a.getDimensionPixelSize(R.styleable.RoundedLinearLayout_border,border); + a.recycle(); + } + + private void init(){ + ctx = getContext(); + + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setColor(ctx.getResources().getColor(R.color.color2)); + mPaint.setAntiAlias(true); + + setWillNotDraw(true); + + + Drawable d = getBackground(); + if(d!=null){ + if(d instanceof ColorDrawable){ + ColorDrawable cd = (ColorDrawable) d; + if(cd!=null){ + colorBG = cd.getColor(); + } + } + } + + setClipChildren(true); + setClipToPadding(true); + + setBackground(null); + setBackgroundColor(Color.TRANSPARENT); + } + + @Override + public void setBackgroundColor(int color){ + super.setBackgroundColor(color); + } + + + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) + { + if(oldw!=w){ + bounds = new RectF(0,0,w,h); + } + super.onSizeChanged(w, h, oldw, oldh); + } + + @Override + public void draw(Canvas canvas){ + super.draw(canvas); + } + + @Override + protected void onDraw(Canvas canvas){ + mPaint.setColor(colorBG); + canvas.drawRoundRect(0,0, (int) bounds.width(), (int) bounds.height(), mRadius, mRadius, mPaint); + super.onDraw(canvas); + } + + + + + + + +} diff --git a/aupod/src/sleepchild/view/SettingsItem.java b/aupod/src/sleepchild/view/SettingsItem.java new file mode 100644 index 0000000..c11ae07 --- /dev/null +++ b/aupod/src/sleepchild/view/SettingsItem.java @@ -0,0 +1,115 @@ +package sleepchild.view; +import android.widget.*; +import android.content.*; +import android.util.*; +import android.view.*; +import sleepchild.aupod22.*; +import android.graphics.drawable.*; +import android.graphics.*; +import android.content.res.*; + +public class SettingsItem extends LinearLayout +{ + TextView mTextView; + ImageView mIcon; + int mTextColor=0; + int mIconColor=0; + + public SettingsItem(Context ctx){ + super(ctx); + init(); + } + + public SettingsItem(Context ctx, AttributeSet attrs){ + this(ctx, attrs,0); + } + + public SettingsItem(Context ctx, AttributeSet attrs, int defStyleAttrs){ + super(ctx, attrs, defStyleAttrs); + init(); + + TypedArray a = ctx.getTheme().obtainStyledAttributes(attrs,R.styleable.SettingsItem,defStyleAttrs,0); + + String textStr = a.getString(R.styleable.SettingsItem_text); + int textCol = a.getColor(R.styleable.SettingsItem_textColor,0); + if(textCol==0){ + textCol = Util.getColor("#ffffff"); + } + setText(textStr); + setTextColor(textCol); + // + Drawable d = a.getDrawable(R.styleable.SettingsItem_icon); + int iconCol = a.getColor(R.styleable.SettingsItem_iconColor,0); + if(iconCol==0){ + iconCol = Util.getColor("#ffffff"); + } + setIcon(d); + setIconColor(iconCol); + + a.recycle(); + } + + private void init(){ + getViewLayout(); + } + + private void getViewLayout(){ + View v = LayoutInflater.from(getContext()).inflate(R.layout.customview_settingsitem,null, false); + mTextView = (TextView) v.findViewById(R.id.customview_settingsitem_text); + mIcon = (ImageView) v.findViewById(R.id.customview_settingsitem_icon); + addView(v); + } + + public void setText(CharSequence text){ + mTextView.setText(text); + } + + public void setIcon(Bitmap icon){ + setIcon(new BitmapDrawable(getContext().getResources(), icon)); + } + + public void setIcon(Drawable drawable){ + mIcon.setBackground(drawable); + } + + public void refresh(){ + // + } + + public void setIconColor(String color){ + setIconColor(Util.getColor(color)); + } + + public void setIconColor(int color){ + if(mIconColor==color){ + return; + } + mIconColor = color; + mIcon.setColorFilter(color); + Drawable d = mIcon.getBackground(); + if(d!=null){ + d = d.mutate(); + d.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)); + mIcon.setBackground(d); + }else{ + //mIcon.getBackground() + } + } + + public void setTextColor(String color){ + setTextColor(Util.getColor(color)); + } + + public void setTextColor(int color){ + if(mTextColor==color){ + return; + } + mTextColor=color; + mTextView.setTextColor(color); + } + + public void onUpdate(){ + // + } + +} diff --git a/aupod/src/sleepchild/view/TintedImageView.java b/aupod/src/sleepchild/view/TintedImageView.java new file mode 100644 index 0000000..d6b2a07 --- /dev/null +++ b/aupod/src/sleepchild/view/TintedImageView.java @@ -0,0 +1,61 @@ +package sleepchild.view; +import android.widget.*; +import android.content.*; +import android.util.*; +import android.graphics.drawable.*; +import android.graphics.*; +import sleepchild.aupod22.*; + +public class TintedImageView extends ImageView +{ + public TintedImageView(Context ctx){ + super(ctx); + init(); + } + + public TintedImageView(Context ctx, AttributeSet attrs){ + super(ctx, attrs); + init(); + } + + public TintedImageView(Context ctx, AttributeSet attrs, int defStyleAttr){ + super(ctx, attrs, defStyleAttr); + init(); + } + + public TintedImageView(Context ctx, AttributeSet attrs, int defStyleAttr, int defStyleRes){ + super(ctx, attrs, defStyleAttr, defStyleRes); + init(); + } + + Context ctx; + private void init(){ + ctx = getContext(); + setTint(ctx.getResources().getColor(R.color.color2)); + } + + @Override + public void setBackgroundResource(int resid) + { + // TODO: Implement this method + super.setBackgroundResource(resid); + //setTint(); + } + + + public void setTint(int color){ + setColorFilter(color); + Drawable d = getBackground(); + if(d!=null){ + //d = d.mutate(); + + //d.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)); + d.setTint(color); + setBackground(d); + } + } + + + + +} diff --git a/aupod/src/sleepchild/view/Util.java b/aupod/src/sleepchild/view/Util.java new file mode 100644 index 0000000..21704f2 --- /dev/null +++ b/aupod/src/sleepchild/view/Util.java @@ -0,0 +1,11 @@ +package sleepchild.view; +import android.graphics.*; + +public class Util +{ + public Util(){} + + public static int getColor(String hexValue){ + return Color.parseColor(hexValue); + } +} diff --git a/aupod/src/sleepchild/view/tabview/Tab.java b/aupod/src/sleepchild/view/tabview/Tab.java new file mode 100644 index 0000000..ace2874 --- /dev/null +++ b/aupod/src/sleepchild/view/tabview/Tab.java @@ -0,0 +1,17 @@ +package sleepchild.view.tabview; + +import android.view.View; + +public abstract class Tab{ + + public Tab(){} + + public abstract View getView(); + + public void onTabShown(){} + + public void onTabHidden(){} + + public void onTabAlreadyVisible(){} + +} diff --git a/aupod/src/sleepchild/view/tabview/TabView.java b/aupod/src/sleepchild/view/tabview/TabView.java new file mode 100644 index 0000000..5b55a25 --- /dev/null +++ b/aupod/src/sleepchild/view/tabview/TabView.java @@ -0,0 +1,135 @@ +package sleepchild.view.tabview; + +import android.widget.*; +import android.content.*; +import android.util.*; +import android.view.*; +import android.graphics.*; +import sleepchild.aupod22.R; +import android.graphics.drawable.*; +import android.content.res.*; +import sleepchild.aupod22.tabs.*; +import java.util.*; + +public class TabView extends LinearLayout { + + public TabView(Context ctx){ + super(ctx); + init(); + } + + public TabView(Context ctx, AttributeSet attrs){ + super(ctx, attrs); + init(); + //setAttrs(attrs,0,0); + //applyAttrs(); + } + + public TabView(Context ctx, AttributeSet attrs, int defStyleAttr){ + super(ctx, attrs, defStyleAttr); + init(); + //setAttrs(attrs,defStyleAttr,0); + //applyAttrs(); + } + + public TabView(Context ctx, AttributeSet attrs, int defStyleAttr, int defStyleRes){ + super(ctx, attrs, defStyleAttr, defStyleRes); + init(); + //setAttrs(attrs, defStyleAttr, defStyleRes); + //applyAttrs(); + } + + ////// + Context ctx; + + LinearLayout tabstrip; + LinearLayout tabcontainer; + + int tabStripBackground=0; + int tabContainerBackground=0; + int rootBackground=0; + int cornerRadius=0; + int colorWhite, colorBlack; + + boolean showStrip = true; + Tab currentTab=null; + + //Map tablist = new HashMap<>(); + + List tablist = new ArrayList<>(); + List tabTitles = new ArrayList<>(); + + GradientDrawable gdrc; + + private void init(){ + ctx = getContext(); + View v = LayoutInflater.from(ctx).inflate(R.layout.customview_tabview, null, false); + + tabcontainer = (LinearLayout) v.findViewById(R.id.customview_tabview_tabcontainer); + tabstrip = (LinearLayout) v.findViewById(R.id.customview_tabview_tabstrip); + + addView(v, new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + + gdrc = new GradientDrawable(); + gdrc.setCornerRadius(20); + int col = ctx.getResources().getColor(R.color.color2); + gdrc.setStroke(5, col); + // + } + + public void addTab(String title, Tab tab){ + tablist.add(tab); + addTitle(title); + } + + private void addTitle(String title){ + LinearLayout v = (LinearLayout) LayoutInflater.from(ctx).inflate(R.layout.tabtitle,null, false); + final TextView tv = (TextView) v.findViewById(R.id.tabtitleTextView); + tv.setText(title); + v.removeAllViews(); + tv.setOnClickListener(new View.OnClickListener(){ + public void onClick(View v){ + int i = tabTitles.indexOf(tv); + showTab(i); + } + }); + tabTitles.add(tv); + tabstrip.addView(tv); + } + + private void setTitles(int index){ + int cc = tabstrip.getChildCount(); + for(int i=0;i=0 && index