[Android] [PATCH 2/2] Playlists in database

Geoffrey Métais geoffrey.metais at gmail.com
Tue Mar 24 00:39:36 CET 2015


Thing is, MediaDatabase.java aggregates all db accesses.

I'd rather split different db helpers, so I'm not against this idea but for
now all is done in this class.

Thus, I use already
present playlistDelete, playlistExists, playlistInsertItem and playlistAdd
mathods in this very class.

On Mon, Mar 23, 2015 at 6:37 PM, Edward Wang <edward.c.wang at compdigitec.com>
wrote:

> This shouldn't be using MediaDatabase directly; it should be using
> them through PlaylistDatabase.
>
> Regards,
> Edward
>
> On Mon, Mar 23, 2015 at 9:00 AM, Jean-Baptiste Kempf <jb at videolan.org>
> wrote:
> > OK.
> >
> >
> > On 23 Mar, Geoffrey Métais wrote :
> >> ---
> >>  .../res/drawable-hdpi/ic_save_grey600_24dp.png     | Bin 0 -> 344 bytes
> >>  .../res/drawable-hdpi/ic_save_white_24dp.png       | Bin 0 -> 341 bytes
> >>  .../res/drawable-mdpi/ic_save_grey600_24dp.png     | Bin 0 -> 259 bytes
> >>  .../res/drawable-mdpi/ic_save_white_24dp.png       | Bin 0 -> 257 bytes
> >>  .../res/drawable-xhdpi/ic_save_grey600_24dp.png    | Bin 0 -> 440 bytes
> >>  .../res/drawable-xhdpi/ic_save_white_24dp.png      | Bin 0 -> 359 bytes
> >>  .../res/drawable-xxhdpi/ic_save_grey600_24dp.png   | Bin 0 -> 493 bytes
> >>  .../res/drawable-xxhdpi/ic_save_white_24dp.png     | Bin 0 -> 489 bytes
> >>  .../res/drawable-xxxhdpi/ic_save_grey600_24dp.png  | Bin 0 -> 747 bytes
> >>  .../res/drawable-xxxhdpi/ic_save_white_24dp.png    | Bin 0 -> 747 bytes
> >>  vlc-android/res/layout/audio_player.xml            |  13 +++
> >>  vlc-android/res/layout/dialog_playlist.xml         |  37 +++++++
> >>  vlc-android/res/menu/audio_list_browser.xml        |   6 +-
> >>  vlc-android/res/values/attrs.xml                   |   1 +
> >>  vlc-android/res/values/strings.xml                 |   2 +
> >>  vlc-android/res/values/styles.xml                  |   2 +
> >>  vlc-android/src/org/videolan/vlc/MediaLibrary.java |  20 +++-
> >>  .../src/org/videolan/vlc/gui/CommonDialogs.java    |   7 ++
> >>  .../vlc/gui/audio/AudioBrowserFragment.java        |  62 ++++++++---
> >>  .../vlc/gui/audio/AudioBrowserListAdapter.java     |  35 ++++--
> >>  .../org/videolan/vlc/gui/audio/AudioPlayer.java    |  23 +++-
> >>  .../vlc/gui/audio/AudioPlaylistAdapter.java        |   4 +
> >>  .../org/videolan/vlc/gui/dialogs/SavePlaylist.java | 120
> +++++++++++++++++++++
> >>  23 files changed, 303 insertions(+), 29 deletions(-)
> >>  create mode 100644
> vlc-android/res/drawable-hdpi/ic_save_grey600_24dp.png
> >>  create mode 100644 vlc-android/res/drawable-hdpi/ic_save_white_24dp.png
> >>  create mode 100644
> vlc-android/res/drawable-mdpi/ic_save_grey600_24dp.png
> >>  create mode 100644 vlc-android/res/drawable-mdpi/ic_save_white_24dp.png
> >>  create mode 100644
> vlc-android/res/drawable-xhdpi/ic_save_grey600_24dp.png
> >>  create mode 100644
> vlc-android/res/drawable-xhdpi/ic_save_white_24dp.png
> >>  create mode 100644
> vlc-android/res/drawable-xxhdpi/ic_save_grey600_24dp.png
> >>  create mode 100644
> vlc-android/res/drawable-xxhdpi/ic_save_white_24dp.png
> >>  create mode 100644
> vlc-android/res/drawable-xxxhdpi/ic_save_grey600_24dp.png
> >>  create mode 100644
> vlc-android/res/drawable-xxxhdpi/ic_save_white_24dp.png
> >>  create mode 100644 vlc-android/res/layout/dialog_playlist.xml
> >>  create mode 100644
> vlc-android/src/org/videolan/vlc/gui/dialogs/SavePlaylist.java
> >>
> >> diff --git a/vlc-android/res/drawable-hdpi/ic_save_grey600_24dp.png
> b/vlc-android/res/drawable-hdpi/ic_save_grey600_24dp.png
> >> new file mode 100644
> >> index
> 0000000000000000000000000000000000000000..3ead270a02dbe60f07f722d4c58caadff02f361f
> >> GIT binary patch
> >> literal 344
> >> zcmeAS at N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K;Lb6AYF9SoB8UsT^3j at P1pisjL
> >> z28L1t28LG&3=CE?7#PG0=Ijcz0ZK3>dAqwX{BQ3+vmeOgEbxddW?<k3n!+v2$S`Y;
> >> z1W at pTr;B5V$MLt<e7Twp1Xv#&+1wc<P~95$NH=&BuiVnva*hFSa<lR$=q*{6S=ZCK
> >> zl>78;79M#uV<VvnxlZ30Q&${3AYS~*S#sTk#)oz*_|n!)i8Au=*mBQ#Yo3?x&euyn
> >> z?mX_b)Zx}U6OUC~%bfna4yd>)wqWZ|=h;rOEG)lFUi8(}#U=E#7p;{&9kIgLs=A}O
> >> zh0)Z$t%`Zq(YUgOhV4IA^=jOo;Vw~9w&hL(Tkq3=;2E5<i|r<!YI)Jc`12I&6|+s5
> >> m4^GTG6rh=AzTecdk}0CI%&h3-WD}s at 7(8A5T-G at yGywqLjDB7K
> >>
> >> literal 0
> >> HcmV?d00001
> >>
> >> diff --git a/vlc-android/res/drawable-hdpi/ic_save_white_24dp.png
> b/vlc-android/res/drawable-hdpi/ic_save_white_24dp.png
> >> new file mode 100644
> >> index
> 0000000000000000000000000000000000000000..8c9e9cec086bc0b7d2e1a07185c395e13a5e1175
> >> GIT binary patch
> >> literal 341
> >> zcmeAS at N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K;Lb6AYF9SoB8UsT^3j at P1pisjL
> >> z28L1t28LG&3=CE?7#PG0=Ijcz0ZK3>dAqwX{BQ3+vmeOgEbxddW?<k3n!+v2$S`Y;
> >> z1W at p-r;B5V$MLt<yt$eU1lS%N+1wc<P~94*qI!G6;*!hC99?^T-}3&`Thf~;_bl<{
> >> zp>sJbhuaI)d^k>+d46LQ%{X`<{PUA`t{6e7JM3FKIN!BNFf90-x2ib!)x_O)QuDLd
> >> zgzzm{d#-tb)(q~C>zyBlMmHus=FjE&Dj*>7X at T{r at 4vZ%twOTiMl5&Qd+}znlnRf>
> >> zKM5(G7t?-i*6y`j5}xa{H$g7(!p)0C$|_4zgNqG>t<+>E9&5=s(ol1h^@`c1%m*jt
> >> jO<ovyCU2c-<WH8uP(x<v=yq42#~3_a{an^LB{Ts5)j at m(
> >>
> >> literal 0
> >> HcmV?d00001
> >>
> >> diff --git a/vlc-android/res/drawable-mdpi/ic_save_grey600_24dp.png
> b/vlc-android/res/drawable-mdpi/ic_save_grey600_24dp.png
> >> new file mode 100644
> >> index
> 0000000000000000000000000000000000000000..e72945d9e59915a028a9add8e4e488125fe40146
> >> GIT binary patch
> >> literal 259
> >> zcmeAS at N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1g=CK)Uj~LMH3o);76yi2K%s^g
> >> z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tW<QX}S>O=~G=W<fgc%uT%>kKR
> >> z?djqeVsZNFWnZoa1p(Fs{RiidHd(c4?5O(PmmRAReREZ#S7DRDquew at c^+nehdtdd
> >> z*wl1ROg*C-5Wjz7 at re^hh2>hfJ3cu6W7zUZeZxT~r-O<g8<xsf%1vM~;n!elW0z?>
> >> wz|1Kp#l~1IyXNfjW7-nZy&V!&<+J88U*h=PQ0~0yFwhwcp00i_>zopr0I>;C<p2Nx
> >>
> >> literal 0
> >> HcmV?d00001
> >>
> >> diff --git a/vlc-android/res/drawable-mdpi/ic_save_white_24dp.png
> b/vlc-android/res/drawable-mdpi/ic_save_white_24dp.png
> >> new file mode 100644
> >> index
> 0000000000000000000000000000000000000000..bb26bc075dc41e7b30c7413a109940b7b302d945
> >> GIT binary patch
> >> literal 257
> >> zcmeAS at N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1g=CK)Uj~LMH3o);76yi2K%s^g
> >> z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tW<QX}S>O=~G=W<fgc%uT%>kKR
> >> z>FMGaVsZNF<+Gd(20U#K^)9?hYU&Hr+0pbkOnk$<IDfW3n!O55KlLo1GzxSawCVoI
> >> zQ{wX^YY+3!kHR;lAC$FnUu06OI>5akq at Iaeu6wci%ZBOFtg;)Jv}6mIvSeSd@>osa
> >> u2)V+urqV#XU#fqBZjH;5pTCx0y~%J?&PdMil4K>&5e%NLelF{r5}E+b<x-0P
> >>
> >> literal 0
> >> HcmV?d00001
> >>
> >> diff --git a/vlc-android/res/drawable-xhdpi/ic_save_grey600_24dp.png
> b/vlc-android/res/drawable-xhdpi/ic_save_grey600_24dp.png
> >> new file mode 100644
> >> index
> 0000000000000000000000000000000000000000..fad94a7fc2a1d0439af37920e916886006a36ce2
> >> GIT binary patch
> >> literal 440
> >> zcmV;p0Z0CcP)<h;3K|Lk000e1NJLTq001xm001xu1ONa4{R=S+0000WV at Og>004R>
> >> z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN
> >> zS#tmY3ljhU3ljkVnw%H_00A&bL_t(o!|m5UOG053$MLUA85QpK1{_iZuh8tK5aC{P
> >> zIEX|@t8KM}IEXJmcL}1U7m!H}g-fe63nAg1bWyyIKG#3D<DfogyFa++^KiHv?&Hg|
> >> z+VUA-`+yL4Bsg5M%Pob)fDo?)JRQ`PP=PvUo at e1gsKD>i!<kE{K!21j*s?#LkOee^
> >> zG%!WT0~5q50OfrHcm)2v;S6Aa4F!6XsnG(CIVZ!eEYK!N%kdoMnIk!%ho!U!h|pw5
> >> z3V7gJlNQNI0Wm%_sYO!?@MCMzJ^t1Puz1&`ao(hWB3GKUL{<v0iSsp)MQO-=rtm|G
> >> zPo at 16LD^MdQ=vLs6&GB(o_;3KWnW;`b)CP^D)7ju08l3_e*qa+hZDYMU7_wtaNv13
> >> iFWflWn`^8ABx(Sl*>NFF2Q9h)0000<MNUMnLSTYP9jbQ#
> >>
> >> literal 0
> >> HcmV?d00001
> >>
> >> diff --git a/vlc-android/res/drawable-xhdpi/ic_save_white_24dp.png
> b/vlc-android/res/drawable-xhdpi/ic_save_white_24dp.png
> >> new file mode 100644
> >> index
> 0000000000000000000000000000000000000000..aa0332092a831d643dc16620ff8741c3ec9ccc7c
> >> GIT binary patch
> >> literal 359
> >> zcmeAS at N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}tg=CK)Uj~LMH3o);76yi2K%s^g
> >> z3=E|}g|8AA7_4S6Fo+k-*%fF5lweBoc6VX;-`;;_Kaj^+;1OBOz`!jG!i)^F=12eq
> >> z?|Zs9hD02Gd)<+%$wB1U$D5tvoeEtBd*_RD9PZAL)y$G!=(z3I_O1(RGhY=4p8X!i
> >> z{Hd<_RCBt);b|Wa{AWz|(u(ta#nof^DK5x-!IQsB^c+~T7S--K`c>FUAnJhAibi%P
> >> z{*n$w1{(ziyIyvi533K%R25`o<TjEr-H>{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/vlc-android/res/drawable-xxhdpi/ic_save_grey600_24dp.png
> b/vlc-android/res/drawable-xxhdpi/ic_save_grey600_24dp.png
> >> new file mode 100644
> >> index
> 0000000000000000000000000000000000000000..6ecab92a7d4f604f08f24fcda65789486ca9722a
> >> GIT binary patch
> >> literal 493
> >> zcmeAS at N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhaw6p}rHd>I(3)EF2VS{N990fib~
> >> zFff!FFfhDIU|_JC!N4G1FlSew4N!t9$=lt9;eUJonf*W>XMsm#F#`j)FbFd;%$g&?
> >> zz`&U5>EalYaqsQT^I3-+1lT^rn6$p)7ODDhURy*^-u0roK<2~U-<P^*x>n^b5xFJs
> >> z!7^%z`rC!#ndzHn&pPwugW>kZR{5KE->?fSt_pW$5p)r7G-W*+ at jz1EVp_=e=Z)(=
> >> zhDj||@cd`>w7AJLs5p>QeS(VV<WmleDl30RDxUD3G;8_k^E(gySBh*X at -$l at GfDJ>
> >> z=O$)Lk7)`MQ at E{!fW}P~cLW>D64}fbk<`N{m9eOsGi=)e5%c;m{t1zda)p}5`ozq{
> >> z7F;>_Q!(|{g60j8%T2Ga>F%v8T+1z0?HC*zaGd+q%O<I~fHmA%*LbgdZThuqL8rLM
> >> zW!ANO7O=my|Ee(E_)@)<(Uv)L%*w?2UmtVKdVEr=E=7WC_SVh5J=s1NoqHr|&oK2D
> >> zIbN6^)o{1HG46_kr^E|CUK4)iScTAsd%W})Wgq#u?!ZnhGnRcv#eR476*cYD)-TBO
> >> g7XZ5b%j$iM)8ub3n}nB00b_x|)78&qol`;+0DIfJD*ylh
> >>
> >> literal 0
> >> HcmV?d00001
> >>
> >> diff --git a/vlc-android/res/drawable-xxhdpi/ic_save_white_24dp.png
> b/vlc-android/res/drawable-xxhdpi/ic_save_white_24dp.png
> >> new file mode 100644
> >> index
> 0000000000000000000000000000000000000000..6c87e1358816aaec842a21e215d2a70a3f0f2035
> >> GIT binary patch
> >> literal 489
> >> zcmV<F0T%v=P)<h;3K|Lk000e1NJLTq002k;002k`1ONa4|Kxkj0000WV at Og>004R>
> >> z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN
> >> zS#tmY3ljhU3ljkVnw%H_00Ci1L_t(&-tF1XO2a at 92Jl?k6>MKX at X$Z6Af@;yE$tJO
> >> zqEC>QDlH<#s}T`21o|9G at zl?Qm!iAbP1>Ew;hVV)B>Z4EnSn`=G%FK=2qK7}hJp;1
> >> zc*ZBr73pc9YrNy!k=6&92%KP&t++(2Nb7+zK#ycAegS$UTk$wf`GjkcG(e>!9Z(5L
> >> z3*;o}fgB`Fkd>qh0zm{36g>zch#-OpB1ju_zzP%e&_Wx1OtIDl<+%Cx^azC(=n<FJ
> >> zv7>{n1}JxMeo2Ki=wLal;~YzaR^EAWBMX{%K{HuU&kGvJf?8gXkp;Dz2I_l3Ls`(&
> >> z3!2M<)?Uzq^q+cE%DI(q9R)g0P8U0k=DKx|x_HtWKMIU3hqbHlh6oem1~Uv`U@*iy
> >> z at G4gXeTxmS`!LX}7$^$^-HU-1VW11-BAho{M|7<?KLj{e)t10_c)>o>RnD+*%?sSy
> >> f6GRX}1pUb$u{XmgXM?Q~00000NkvXXu0mjfr`^33
> >>
> >> literal 0
> >> HcmV?d00001
> >>
> >> diff --git a/vlc-android/res/drawable-xxxhdpi/ic_save_grey600_24dp.png
> b/vlc-android/res/drawable-xxxhdpi/ic_save_grey600_24dp.png
> >> new file mode 100644
> >> index
> 0000000000000000000000000000000000000000..6c8f219e8664bdc64931df96c55ec25e78ad1e6b
> >> GIT binary patch
> >> literal 747
> >> zcmeAS at N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%xcg6p}rHd>I(3)EF2VS{N990fib~
> >> zFff!FFfhDIU|_JC!N4G1FlSew4N!t9$=lt9;eUJonf*W>XMsm#F#`j)FbFd;%$g$s
> >> zRFUlI;uunK>+S8+*};w?$3Nza<Z!+63STQG8oR~mg}j0j%f-Dn#Me!^(%QA+=y9*`
> >> zuZ<EPI{SM)W?!>+aNY91QSVBZURLta-ghAznvShiIdk?*ZqfUlpR7+mX_<4rAkC<F
> >> z=96P5%AT+YI504RiCdg6(x)iduE{7?eQt5P%0WH+=KLE8$CO+cttt;~bNQ{vrpQ%b
> >> ze(++yZvpeK%894e at Tlxy+%DmpnaHWMgYo^%Ik#>}I2168-QHKQt>ppRl~=~mF-dDp
> >> zS#~q{H>Ea+A2d7AoFIE)N`m}_mI<s5DvHt#98O^j=iZBh9iX7-a7(d)fr&!_Mx?MB
> >> zoL4d4^H6(3n_U;r#mS-$QzzRz at xQzJw8R6Z*Ke5BG(H~wc+cydL56g}OkrQ6bp==S
> >> z5}E}2owVL;<y>*;dCt80WYNtf(JVYhPiI;lVy<qeG&5aevo7MC%<Hv`$1H^>)J`<a
> >> zZkTJsd*a?v<?IGMJNA_F%?Z304z6GDW<Jx3)_<ElYvx^Myg7Z=yO~1lAvYyHIDb>D
> >> zNS=EjENO=4`7^b5w(k&+S}^^+T;=MSOHV&5+jVGyyW-_H8><&+7VCVPY<Ws%W9^bT
> >> z&lv8{Ia{oM?S*>HivLG6wf^KqRJKX>U;M3U8}{>r$oa~%;t9IZHxC{Vn&)wZX-W0R
> >> zts7_6XgrXO=3%^dNt$cNNk`{~Y#BaQk&2t2ehU^Zc54h@*kGdn;QH}WKFjB2EDGn7
> >> zw at GW%x82n_#^^B5XlaP_%458JyH9`rDIL}*<Z5<d;*Ud?$BpxLSKXISut7xkG=X|X
> >> YkM<{y8w5O<foYJz)78&qol`;+0GBp3)&Kwi
> >>
> >> literal 0
> >> HcmV?d00001
> >>
> >> diff --git a/vlc-android/res/drawable-xxxhdpi/ic_save_white_24dp.png
> b/vlc-android/res/drawable-xxxhdpi/ic_save_white_24dp.png
> >> new file mode 100644
> >> index
> 0000000000000000000000000000000000000000..51998492cb52124ca6e6990966998dff0f116c0e
> >> GIT binary patch
> >> literal 747
> >> zcmeAS at N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%xcg6p}rHd>I(3)EF2VS{N990fib~
> >> zFff!FFfhDIU|_JC!N4G1FlSew4N!t9$=lt9;eUJonf*W>XMsm#F#`j)FbFd;%$g$s
> >> zRFUlI;uunK>+S8+*}{P$$3Nza<Z!+63STQG8oR~mg}j0j%f-Dn#Me!^(%SXoz;U2N
> >> zm&Aw8{$7vS*X$i!xBPF^yV9kXm3*}KUC4%}V{29JoZNdk<yp_4b4JBZ=bjh6J3IHG
> >> z-#WK#%IXaaOdJXz;)0)p{bG at qiLSG?Ezj?~#%#6o)W0Ka#$t+G7fuRqQ at zD+$Pw7E
> >> zo3pPjr%C$4`R<UkRE2}QJC0^}aeE6K<gGaW?8>!c3{BD-ZhULqtjc1(;GfgFqpH`U
> >> zoHuZPP>Eox5X at n=;kd@=%lVDbmm`wFMQ9Uahe8VLgFm&5ECLP;j6zIHWT7qrJ4eAG
> >> zjN!A7(P8O*OxZ6MpAfK(WDK!9>iq9Y?XDh1y$$E=5}JhUWv+)6wL9K!I6Wt0Qeo at j
> >> zGDhK^3X!11^}Y^M?b1L0kzPGx>20Ni37Y562+G}HKC^jc;?u&TMb9Ggc at 2);Y<SZ>
> >> zXA9enlb0Lb#M*3Pd-15)q0F578iVW~u2cUs8=_v=&pz^a4(Ew|S4z%Lu~=~GScCm0
> >> z{)5u5S+)rs_NhvH_jupYy%(7F)_gw^eO4#dZ2M)=HXE*)Y5jMlXBiz=+COvg8Nu7z
> >> zr(BkKFne?5yQ5NnTk>Do7tZ3^FC8{7 at mSKAI<NjvJENn;ai3WuPKT8lY-mvz+Q{%y
> >> zt|oVlnmkv<aWUtH?O)oM@`^49JdkR4W at L@q_NT_>&WgYXp&ANjnSXpOoa=mUr!3=%
> >> z&okb#otmF$-d)HrVY!dyRku}z&5z%Gs*O9W6|m?8o0U+!#q)||x#91BGxxN^Vq4*W
> >> b&?Ehw%@P7vCQFq9(;$PVtDnm{r-UW|xDGfS
> >>
> >> literal 0
> >> HcmV?d00001
> >>
> >> diff --git a/vlc-android/res/layout/audio_player.xml
> b/vlc-android/res/layout/audio_player.xml
> >> index 836ca00..49b13b4 100644
> >> --- a/vlc-android/res/layout/audio_player.xml
> >> +++ b/vlc-android/res/layout/audio_player.xml
> >> @@ -33,6 +33,18 @@
> >>              android:layout_weight="1" />
> >>
> >>          <ImageButton
> >> +            android:id="@+id/playlist_save"
> >> +            android:layout_width="40dp"
> >> +            android:layout_height="40dp"
> >> +            android:layout_gravity="center"
> >> +            android:layout_weight="0"
> >> +            android:background="#00000000"
> >> +            android:focusable="true"
> >> +            android:scaleType="fitXY"
> >> +            android:contentDescription="@string/playlist_save"
> >> +            android:src="?attr/ic_save" />
> >> +
> >> +        <ImageButton
> >>              android:id="@+id/playlist_switch"
> >>              android:layout_width="40dp"
> >>              android:layout_height="40dp"
> >> @@ -58,6 +70,7 @@
> >>              android:layout_width="wrap_content"
> >>              android:layout_height="wrap_content"
> >>              android:layout_gravity="center|left"
> >> +            android:layout_marginLeft="15dp"
> >>              android:layout_marginRight="15dp"
> >>              android:layout_weight="0"
> >>              android:clickable="true"
> >> diff --git a/vlc-android/res/layout/dialog_playlist.xml
> b/vlc-android/res/layout/dialog_playlist.xml
> >> new file mode 100644
> >> index 0000000..8783a11
> >> --- /dev/null
> >> +++ b/vlc-android/res/layout/dialog_playlist.xml
> >> @@ -0,0 +1,37 @@
> >> +<?xml version="1.0" encoding="utf-8"?>
> >> +<RelativeLayout xmlns:android="
> http://schemas.android.com/apk/res/android"
> >> +    xmlns:tools="http://schemas.android.com/tools"
> >> +    android:layout_width="match_parent"
> android:layout_height="match_parent">
> >> +
> >> +    <EditText
> >> +        android:id="@+id/dialog_playlist_name"
> >> +        android:layout_width="match_parent"
> >> +        android:layout_height="wrap_content"
> >> +        android:layout_alignParentTop="true"
> >> +        android:hint="@string/playlist_name_hint"
> >> +        android:inputType="text"
> >> +        android:imeOptions="actionSend"/>
> >> +    <FrameLayout
> >> +        android:id="@+id/dialog_list_container"
> >> +        android:layout_width="match_parent"
> >> +        android:layout_height="wrap_content"
> >> +        android:layout_below="@+id/dialog_playlist_name">
> >> +        <ListView
> >> +            android:id="@android:id/list"
> >> +            android:layout_width="match_parent"
> >> +            android:layout_height="wrap_content"/>
> >> +        <TextView
> >> +            android:id="@android:id/empty"
> >> +            android:layout_width="match_parent"
> >> +            android:layout_height="wrap_content"
> >> +            android:text="@string/noplaylist"/>
> >> +    </FrameLayout>
> >> +    <Button
> >> +        android:id="@+id/dialog_playlist_save"
> >> +        android:layout_width="match_parent"
> >> +        android:layout_height="wrap_content"
> >> +        android:text="@string/playlist_save"
> >> +        android:layout_below="@id/dialog_list_container"
> >> +        tools:targetApi="11"
> >> +        style="?android:attr/borderlessButtonStyle"/>
> >> +</RelativeLayout>
> >> \ No newline at end of file
> >> diff --git a/vlc-android/res/menu/audio_list_browser.xml
> b/vlc-android/res/menu/audio_list_browser.xml
> >> index 6bda46a..f838a5a 100644
> >> --- a/vlc-android/res/menu/audio_list_browser.xml
> >> +++ b/vlc-android/res/menu/audio_list_browser.xml
> >> @@ -11,10 +11,10 @@
> >>           <item
> >>               android:id="@+id/audio_list_browser_play_all"
> >>               android:title="@string/play_all" />
> >> -        <item
> >> -           android:id="@+id/audio_list_browser_delete"
> >> -           android:title="@string/delete"/>
> >>      </group>
> >> +    <item
> >> +        android:id="@+id/audio_list_browser_delete"
> >> +        android:title="@string/delete"/>
> >>      <group android:id="@+id/phone_only" >
> >>           <item
> >>               android:id="@+id/audio_list_browser_set_song"
> >> diff --git a/vlc-android/res/values/attrs.xml
> b/vlc-android/res/values/attrs.xml
> >> index 93cd223..13f36aa 100644
> >> --- a/vlc-android/res/values/attrs.xml
> >> +++ b/vlc-android/res/values/attrs.xml
> >> @@ -56,6 +56,7 @@
> >>      <attr name="ic_menu_preferences" format="reference" />
> >>      <attr name="ic_menu_cone" format="reference" />
> >>      <attr name="ic_move_media" format="reference" />
> >> +    <attr name="ic_save" format="reference" />
> >>      <attr name="ic_trash_small_normal" format="reference" />
> >>      <attr name="gridview_progressbar" format="reference" />
> >>      <attr name="toolbar_popup_style" format="reference" />
> >> diff --git a/vlc-android/res/values/strings.xml
> b/vlc-android/res/values/strings.xml
> >> index 1675b38..9ef83ec 100644
> >> --- a/vlc-android/res/values/strings.xml
> >> +++ b/vlc-android/res/values/strings.xml
> >> @@ -322,6 +322,8 @@
> >>      <string name="search_hint">Search media</string>
> >>      <string name="directory_show_medialib">Show in MediaLib</string>
> >>      <string name="directory_hide_medialib">Hide from MediaLib</string>
> >> +    <string name="playlist_save">Save Playlist</string>
> >> +    <string name="playlist_name_hint">playlist name</string>
> >>
> >>      <string-array name="hardware_acceleration_list">
> >>          <item>@string/automatic</item>
> >> diff --git a/vlc-android/res/values/styles.xml
> b/vlc-android/res/values/styles.xml
> >> index 09c767b..3913689 100644
> >> --- a/vlc-android/res/values/styles.xml
> >> +++ b/vlc-android/res/values/styles.xml
> >> @@ -67,6 +67,7 @@
> >>          <item
> name="ic_menu_preferences">@drawable/ic_menu_preferences</item>
> >>          <item name="ic_menu_cone">@drawable/ic_menu_cone</item>
> >>          <item name="ic_move_media">@drawable/ic_move_media</item>
> >> +        <item name="ic_save">@drawable/ic_save_grey600_24dp</item>
> >>          <item
> name="ic_trash_small_normal">@drawable/ic_trash_small_normal</item>
> >>          <item
> name="gridview_progressbar">@drawable/gridview_progressbar_w</item>
> >>          <item
> name="advanced_options_style">@style/Theme.VLC.AdvancedOptionsLight</item>
> >> @@ -138,6 +139,7 @@
> >>          <item
> name="ic_menu_preferences">@drawable/ic_menu_preferences_w</item>
> >>          <item name="ic_menu_cone">@drawable/ic_menu_cone_w</item>
> >>          <item name="ic_move_media">@drawable/ic_move_media_w</item>
> >> +        <item name="ic_save">@drawable/ic_save_white_24dp</item>
> >>          <item
> name="ic_trash_small_normal">@drawable/ic_trash_small_normal_w</item>
> >>          <item
> name="gridview_progressbar">@drawable/gridview_progressbar</item>
> >>          <item
> name="advanced_options_style">@style/Theme.VLC.AdvancedOptionsBlack</item>
> >> diff --git a/vlc-android/src/org/videolan/vlc/MediaLibrary.java
> b/vlc-android/src/org/videolan/vlc/MediaLibrary.java
> >> index 6d3ce3b..7ee3bb7 100644
> >> --- a/vlc-android/src/org/videolan/vlc/MediaLibrary.java
> >> +++ b/vlc-android/src/org/videolan/vlc/MediaLibrary.java
> >> @@ -39,11 +39,13 @@ import org.videolan.libvlc.LibVlcException;
> >>  import org.videolan.libvlc.Media;
> >>  import org.videolan.libvlc.util.Extensions;
> >>  import org.videolan.vlc.gui.MainActivity;
> >> +import org.videolan.vlc.gui.audio.AudioBrowserListAdapter;
> >>  import org.videolan.vlc.util.AndroidDevices;
> >>  import org.videolan.vlc.util.Util;
> >>  import org.videolan.vlc.util.VLCInstance;
> >>  import org.videolan.vlc.util.WeakHandler;
> >>
> >> +import android.app.LauncherActivity;
> >>  import android.content.Context;
> >>  import android.os.Environment;
> >>  import android.os.Handler;
> >> @@ -172,7 +174,7 @@ public class MediaLibrary {
> >>          return audioItems;
> >>      }
> >>
> >> -    public ArrayList<MediaWrapper> getPlaylistItems() {
> >> +    public ArrayList<MediaWrapper> getPlaylistFilesItems() {
> >>          ArrayList<MediaWrapper> playlistItems = new
> ArrayList<MediaWrapper>();
> >>          mItemListLock.readLock().lock();
> >>          for (int i = 0; i < mItemList.size(); i++) {
> >> @@ -185,6 +187,22 @@ public class MediaLibrary {
> >>          return playlistItems;
> >>      }
> >>
> >> +    public ArrayList<AudioBrowserListAdapter.ListItem>
> getPlaylistDbItems() {
> >> +        ArrayList<AudioBrowserListAdapter.ListItem> playlistItems =
> new ArrayList<AudioBrowserListAdapter.ListItem>();
> >> +        AudioBrowserListAdapter.ListItem playList;
> >> +        MediaDatabase db = MediaDatabase.getInstance();
> >> +        String[] items, playlistNames = db.getPlaylists();
> >> +        for (String playlistName : playlistNames){
> >> +            items = db.playlistGetItems(playlistName);
> >> +            playList = new
> AudioBrowserListAdapter.ListItem(playlistName, null, null, false);
> >> +            for (String track : items){
> >> +                playList.mMediaList.add(new MediaWrapper(track));
> >> +            }
> >> +            playlistItems.add(playList);
> >> +        }
> >> +        return playlistItems;
> >> +    }
> >> +
> >>      public ArrayList<MediaWrapper> getMediaItems() {
> >>          return mItemList;
> >>      }
> >> diff --git a/vlc-android/src/org/videolan/vlc/gui/CommonDialogs.java
> b/vlc-android/src/org/videolan/vlc/gui/CommonDialogs.java
> >> index c8d93c3..6f725e4 100644
> >> --- a/vlc-android/src/org/videolan/vlc/gui/CommonDialogs.java
> >> +++ b/vlc-android/src/org/videolan/vlc/gui/CommonDialogs.java
> >> @@ -60,6 +60,13 @@ public class CommonDialogs {
> >>                                            final String addressMedia,
> >>                                            final VLCRunnable runnable) {
> >>          final String name =
> Uri.decode(addressMedia.substring(addressMedia.lastIndexOf('/')+1));
> >> +        return  deleteMedia(context, addressMedia, name, runnable);
> >> +    }
> >> +
> >> +    public static AlertDialog deleteMedia(final Context context,
> >> +                                          final String addressMedia,
> >> +                                          final String name,
> >> +                                          final VLCRunnable runnable) {
> >>
> >>          return confirmDialog(
> >>                  context,
> >> diff --git
> a/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserFragment.java
> b/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserFragment.java
> >> index ab1bb53..663c62e 100644
> >> ---
> a/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserFragment.java
> >> +++
> b/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserFragment.java
> >> @@ -56,6 +56,7 @@ import org.videolan.libvlc.LibVLC;
> >>  import org.videolan.libvlc.LibVlcUtil;
> >>  import org.videolan.libvlc.Media;
> >>  import org.videolan.libvlc.util.MediaBrowser;
> >> +import org.videolan.vlc.MediaDatabase;
> >>  import org.videolan.vlc.MediaLibrary;
> >>  import org.videolan.vlc.MediaWrapper;
> >>  import org.videolan.vlc.R;
> >> @@ -66,6 +67,7 @@ import org.videolan.vlc.gui.MainActivity;
> >>  import org.videolan.vlc.gui.SecondaryActivity;
> >>  import org.videolan.vlc.util.AndroidDevices;
> >>  import org.videolan.vlc.util.Util;
> >> +import org.videolan.vlc.util.VLCInstance;
> >>  import org.videolan.vlc.util.VLCRunnable;
> >>  import org.videolan.vlc.util.WeakHandler;
> >>  import org.videolan.vlc.widget.SwipeRefreshLayout;
> >> @@ -352,8 +354,14 @@ public class AudioBrowserFragment extends
> BrowserFragment implements SwipeRefres
> >>      OnItemClickListener playlistListener = new OnItemClickListener() {
> >>          @Override
> >>          public void onItemClick(AdapterView<?> av, View v, int p, long
> id) {
> >> -            String mediaLocation =
> mPlaylistAdapter.getItem(p).mMediaList.get(0).getLocation();
> >> -            mAudioController.load(mediaLocation, true);
> >> +            ArrayList<MediaWrapper> mediaList =
> mPlaylistAdapter.getItem(p).mMediaList;
> >> +            if (mediaList.size() == 1) {
> >> +                String mediaLocation = mediaList.get(0).getLocation();
> >> +                mAudioController.load(mediaLocation, true);
> >> +            } else {
> >> +                ArrayList<String> mediaLocations =
> mPlaylistAdapter.getLocations(p);
> >> +                mAudioController.load(mediaLocations, 0, true);
> >> +            }
> >>          }
> >>      };
> >>
> >> @@ -374,6 +382,8 @@ public class AudioBrowserFragment extends
> BrowserFragment implements SwipeRefres
> >>              MenuItem play =
> menu.findItem(R.id.audio_list_browser_play);
> >>              play.setVisible(true);
> >>          }
> >> +        if (pos != MODE_SONG && pos != MODE_PLAYLIST)
> >> +
> menu.findItem(R.id.audio_list_browser_delete).setVisible(false);
> >>          if (!AndroidDevices.isPhone())
> >>              menu.setGroupVisible(R.id.phone_only, false);
> >>      }
> >> @@ -394,6 +404,7 @@ public class AudioBrowserFragment extends
> BrowserFragment implements SwipeRefres
> >>
> >>          int startPosition;
> >>          int groupPosition;
> >> +        int mode = mViewPager.getCurrentItem();
> >>          List<String> medias;
> >>          int id = item.getItemId();
> >>
> >> @@ -408,17 +419,29 @@ public class AudioBrowserFragment extends
> BrowserFragment implements SwipeRefres
> >>              groupPosition = position;
> >>
> >>          if (id == R.id.audio_list_browser_delete) {
> >> +            AudioBrowserListAdapter adapter;
> >> +            if (mode == MODE_SONG){
> >> +                adapter = mSongsAdapter;
> >> +            } else if (mode == MODE_PLAYLIST) {
> >> +                adapter = mPlaylistAdapter;
> >> +            } else
> >> +                return false;
> >>              AlertDialog alertDialog = CommonDialogs.deleteMedia(
> >>                      getActivity(),
> >> -                    mSongsAdapter.getLocations(groupPosition).get(0),
> >> -                    new
> VLCRunnable(mSongsAdapter.getItem(groupPosition)) {
> >> +                    adapter.getLocations(groupPosition).get(0),
> >> +                    adapter.getItem(groupPosition).mTitle,
> >> +                    new VLCRunnable(adapter.getItem(groupPosition)) {
> >>                          @Override
> >>                          public void run(Object o) {
> >>                              AudioBrowserListAdapter.ListItem listItem
> = (AudioBrowserListAdapter.ListItem)o;
> >> -                            MediaWrapper media =
> listItem.mMediaList.get(0);
> >> -
> mMediaLibrary.getMediaItems().remove(media);
> >> -                            if
> (mAudioController.getMediaLocations().contains(media.getLocation()))
> >> -
> mAudioController.removeLocation(media.getLocation());
> >> +                            if
> (!MediaDatabase.getInstance().playlistExists(listItem.mTitle)) {
> >> +                                MediaWrapper media =
> listItem.mMediaList.get(0);
> >> +
> mMediaLibrary.getMediaItems().remove(media);
> >> +                                if
> (mAudioController.getMediaLocations().contains(media.getLocation()))
> >> +
> mAudioController.removeLocation(media.getLocation());
> >> +                            } else {
> >> +
> MediaDatabase.getInstance().playlistDelete(listItem.mTitle);
> >> +                            }
> >>                              updateLists();
> >>                          }
> >>                      });
> >> @@ -437,7 +460,7 @@ public class AudioBrowserFragment extends
> BrowserFragment implements SwipeRefres
> >>          }
> >>          else {
> >>              startPosition = 0;
> >> -            switch (mViewPager.getCurrentItem())
> >> +            switch (mode)
> >>              {
> >>                  case MODE_SONG:
> >>                      medias = mSongsAdapter.getLocations(groupPosition);
> >> @@ -451,11 +474,15 @@ public class AudioBrowserFragment extends
> BrowserFragment implements SwipeRefres
> >>                  case MODE_GENRE:
> >>                      medias =
> mGenresAdapter.getLocations(groupPosition);
> >>                      break;
> >> -                case MODE_PLAYLIST: //For playlist, we browse tracks
> with mediabrowser, and add them in callbacks onMediaAdded and onBrowseEnd
> >> -                    if (mMediaBrowser == null)
> >> -                        mMediaBrowser = new
> MediaBrowser(LibVLC.getInstance(), this);
> >> -
> mMediaBrowser.browse(mPlaylistAdapter.getMedia(groupPosition).get(0).getLocation());
> >> -                    return true;
> >> +                case MODE_PLAYLIST: //For file playlist, we browse
> tracks with mediabrowser, and add them in callbacks onMediaAdded and
> onBrowseEnd
> >> +                    medias =
> mPlaylistAdapter.getLocations(groupPosition);
> >> +                    if (medias.size() <2) {
> >> +                        if (mMediaBrowser == null)
> >> +                            mMediaBrowser = new
> MediaBrowser(VLCInstance.get(), this);
> >> +
> mMediaBrowser.browse(mPlaylistAdapter.getMedia(groupPosition).get(0).getLocation());
> >> +                        return true;
> >> +                    }
> >> +                    break;
> >>                  default:
> >>                      return true;
> >>              }
> >> @@ -678,8 +705,13 @@ public class AudioBrowserFragment extends
> BrowserFragment implements SwipeRefres
> >>      Runnable updatePlaylists = new Runnable() {
> >>          @Override
> >>          public void run() {
> >> -            ArrayList<MediaWrapper> playlists =
> mMediaLibrary.getPlaylistItems();
> >> +            //File playlists
> >> +            ArrayList<MediaWrapper> playlists =
> mMediaLibrary.getPlaylistFilesItems();
> >>              mPlaylistAdapter.addAll(playlists,
> AudioBrowserListAdapter.TYPE_PLAYLISTS);
> >> +            //DB playlists
> >> +            ArrayList<AudioBrowserListAdapter.ListItem> dbPlaylists =
> mMediaLibrary.getPlaylistDbItems();
> >> +            mPlaylistAdapter.addAll(dbPlaylists);
> >> +
> >>              mAdaptersToNotify.add(mPlaylistAdapter);
> >>              if (mReadyToDisplay && !mDisplaying)
> >>                  display();
> >> diff --git
> a/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserListAdapter.java
> b/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserListAdapter.java
> >> index 33bc575..7f35b86 100644
> >> ---
> a/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserListAdapter.java
> >> +++
> b/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserListAdapter.java
> >> @@ -22,6 +22,7 @@ package org.videolan.vlc.gui.audio;
> >>
> >>  import java.util.ArrayList;
> >>  import java.util.Collections;
> >> +import java.util.Comparator;
> >>  import java.util.HashMap;
> >>  import java.util.LinkedList;
> >>  import java.util.List;
> >> @@ -83,7 +84,7 @@ public class AudioBrowserListAdapter extends
> BaseAdapter implements SectionIndex
> >>      private ContextPopupMenuListener mContextPopupMenuListener;
> >>
> >>      // An item of the list: a media or a separator.
> >> -    static class ListItem {
> >> +    public static class ListItem {
> >>          final public String mTitle;
> >>          final public String mSubTitle;
> >>          final public ArrayList<MediaWrapper> mMediaList;
> >> @@ -112,6 +113,14 @@ public class AudioBrowserListAdapter extends
> BaseAdapter implements SectionIndex
> >>          mAlignMode =
> Integer.valueOf(preferences.getString("audio_title_alignment", "0"));
> >>      }
> >>
> >> +    public void addAll(List<ListItem> items) {
> >> +        for (ListItem item : items) {
> >> +            mMediaItemMap.put(item.mTitle, item);
> >> +            mItems.add(item);
> >> +        }
> >> +        Collections.sort(mItems, mItemsComparator);
> >> +    }
> >> +
> >>      public void add(String title, String subTitle, MediaWrapper media)
> {
> >>          if(title == null) return;
> >>          title = title.trim();
> >> @@ -338,13 +347,16 @@ public class AudioBrowserListAdapter extends
> BaseAdapter implements SectionIndex
> >>
> holder.footer.setVisibility(isMediaItemAboveASeparator(position) ?
> View.GONE : View.VISIBLE);
> >>
> >>          final int pos = position;
> >> -        holder.more.setOnClickListener(new OnClickListener() {
> >> -            @Override
> >> -            public void onClick(View v) {
> >> -                if (mContextPopupMenuListener != null)
> >> -                    mContextPopupMenuListener.onPopupMenu(v, pos);
> >> -            }
> >> -        });
> >> +        if (mContextPopupMenuListener != null)
> >> +            holder.more.setOnClickListener(new OnClickListener() {
> >> +                @Override
> >> +                public void onClick(View v) {
> >> +                    if (mContextPopupMenuListener != null)
> >> +                        mContextPopupMenuListener.onPopupMenu(v, pos);
> >> +                }
> >> +            });
> >> +        else
> >> +            holder.more.setVisibility(View.GONE);
> >>
> >>          return v;
> >>      }
> >> @@ -544,4 +556,11 @@ public class AudioBrowserListAdapter extends
> BaseAdapter implements SectionIndex
> >>          if (observer != null)
> >>              super.unregisterDataSetObserver(observer);
> >>      }
> >> +
> >> +    private Comparator<ListItem> mItemsComparator = new
> Comparator<ListItem>() {
> >> +        @Override
> >> +        public int compare(ListItem lhs, ListItem rhs) {
> >> +            return String.CASE_INSENSITIVE_ORDER.compare(lhs.mTitle,
> rhs.mTitle);
> >> +        }
> >> +    };
> >>  }
> >> diff --git
> a/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.java
> b/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.java
> >> index d3655a6..34bb0df 100644
> >> --- a/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.java
> >> +++ b/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlayer.java
> >> @@ -34,6 +34,7 @@ import org.videolan.vlc.gui.MainActivity;
> >>  import org.videolan.vlc.gui.CommonDialogs.MenuType;
> >>  import org.videolan.vlc.gui.audio.widget.CoverMediaSwitcher;
> >>  import org.videolan.vlc.gui.audio.widget.HeaderMediaSwitcher;
> >> +import org.videolan.vlc.gui.dialogs.SavePlaylist;
> >>  import org.videolan.vlc.interfaces.IAudioPlayer;
> >>  import org.videolan.vlc.util.Strings;
> >>  import org.videolan.vlc.util.Util;
> >> @@ -42,9 +43,11 @@ import
> org.videolan.vlc.widget.AudioMediaSwitcher.AudioMediaSwitcherListener;
> >>  import android.media.AudioManager;
> >>  import android.os.Bundle;
> >>  import android.os.Handler;
> >> +import android.os.Parcelable;
> >>  import android.preference.PreferenceManager;
> >>  import android.support.v4.app.Fragment;
> >>  import android.support.v4.app.FragmentActivity;
> >> +import android.support.v4.app.FragmentManager;
> >>  import android.util.Log;
> >>  import android.view.ContextMenu;
> >>  import android.view.LayoutInflater;
> >> @@ -65,7 +68,7 @@ import android.widget.ViewSwitcher;
> >>  import android.widget.AdapterView.OnItemClickListener;
> >>  import android.widget.SeekBar.OnSeekBarChangeListener;
> >>
> >> -public class AudioPlayer extends Fragment implements IAudioPlayer {
> >> +public class AudioPlayer extends Fragment implements IAudioPlayer,
> View.OnClickListener {
> >>      public static final String TAG = "VLC/AudioPlayer";
> >>
> >>      private ProgressBar mProgressBar;
> >> @@ -81,7 +84,7 @@ public class AudioPlayer extends Fragment implements
> IAudioPlayer {
> >>      private ImageButton mShuffle;
> >>      private ImageButton mRepeat;
> >>      private ImageButton mAdvFunc;
> >> -    private ImageButton mPlaylistSwitch;
> >> +    private ImageButton mPlaylistSwitch, mPlaylistSave;
> >>      private SeekBar mTimeline;
> >>      private AudioPlaylistView mSongsList;
> >>
> >> @@ -134,6 +137,7 @@ public class AudioPlayer extends Fragment
> implements IAudioPlayer {
> >>          mRepeat = (ImageButton) v.findViewById(R.id.repeat);
> >>          mAdvFunc = (ImageButton) v.findViewById(R.id.adv_function);
> >>          mPlaylistSwitch = (ImageButton)
> v.findViewById(R.id.playlist_switch);
> >> +        mPlaylistSave = (ImageButton)
> v.findViewById(R.id.playlist_save);
> >>          mTimeline = (SeekBar) v.findViewById(R.id.timeline);
> >>
> >>          mSongsList = (AudioPlaylistView)
> v.findViewById(R.id.songs_list);
> >> @@ -212,6 +216,7 @@ public class AudioPlayer extends Fragment
> implements IAudioPlayer {
> >>                  showAdvancedOptions(v);
> >>              }
> >>          });
> >> +        mPlaylistSave.setOnClickListener(this);
> >>          mPlaylistSwitch.setOnClickListener(new View.OnClickListener() {
> >>              @Override
> >>              public void onClick(View v) {
> >> @@ -577,6 +582,20 @@ public class AudioPlayer extends Fragment
> implements IAudioPlayer {
> >>          public void onTouchClick() {}
> >>      };
> >>
> >> +    @Override
> >> +    public void onClick(View v) {
> >> +        switch (v.getId()){
> >> +            case R.id.playlist_save:
> >> +                FragmentManager fm =
> getActivity().getSupportFragmentManager();
> >> +                SavePlaylist savePlaylistDialog = new SavePlaylist();
> >> +                Bundle args = new Bundle();
> >> +                args.putParcelableArrayList(SavePlaylist.KEY_TRACKS,
> mSongsListAdapter.getItems());
> >> +                savePlaylistDialog.setArguments(args);
> >> +                savePlaylistDialog.show(fm, "fragment_save_playlist");
> >> +                break;
> >> +        }
> >> +    }
> >> +
> >>      class LongSeekListener implements View.OnTouchListener {
> >>          boolean forward;
> >>          int normal, pressed;
> >> diff --git
> a/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlaylistAdapter.java
> b/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlaylistAdapter.java
> >> index e0f5fd6..5ebfb50 100644
> >> ---
> a/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlaylistAdapter.java
> >> +++
> b/vlc-android/src/org/videolan/vlc/gui/audio/AudioPlaylistAdapter.java
> >> @@ -174,6 +174,10 @@ public class AudioPlaylistAdapter extends
> ArrayAdapter<MediaWrapper> {
> >>          return locations;
> >>      }
> >>
> >> +    public ArrayList<MediaWrapper> getItems(){
> >> +        return mMediaList;
> >> +    }
> >> +
> >>      static class ViewHolder {
> >>          int position;
> >>          TextView title;
> >> diff --git
> a/vlc-android/src/org/videolan/vlc/gui/dialogs/SavePlaylist.java
> b/vlc-android/src/org/videolan/vlc/gui/dialogs/SavePlaylist.java
> >> new file mode 100644
> >> index 0000000..73f39bf
> >> --- /dev/null
> >> +++ b/vlc-android/src/org/videolan/vlc/gui/dialogs/SavePlaylist.java
> >> @@ -0,0 +1,120 @@
> >> +/*
> >> + *
> *************************************************************************
> >> + *  SavePlaylist.java
> >> + *
> **************************************************************************
> >> + *  Copyright © 2015 VLC authors and VideoLAN
> >> + *
> >> + *  This program is free software; you can redistribute it and/or
> modify
> >> + *  it under the terms of the GNU General Public License as published
> by
> >> + *  the Free Software Foundation; either version 2 of the License, or
> >> + *  (at your option) any later version.
> >> + *
> >> + *  This program is distributed in the hope that it will be useful,
> >> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> >> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >> + *  GNU General Public License for more details.
> >> + *
> >> + *  You should have received a copy of the GNU General Public License
> >> + *  along with this program; if not, write to the Free Software
> >> + *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA
> 02110-1301, USA.
> >> + *
> ***************************************************************************
> >> + */
> >> +
> >> +package org.videolan.vlc.gui.dialogs;
> >> +
> >> +import android.os.Bundle;
> >> +import android.support.annotation.Nullable;
> >> +import android.support.v4.app.DialogFragment;
> >> +import android.view.KeyEvent;
> >> +import android.view.LayoutInflater;
> >> +import android.view.View;
> >> +import android.view.ViewGroup;
> >> +import android.view.Window;
> >> +import android.view.inputmethod.EditorInfo;
> >> +import android.widget.AdapterView;
> >> +import android.widget.Button;
> >> +import android.widget.EditText;
> >> +import android.widget.ListView;
> >> +import android.widget.TextView;
> >> +
> >> +import org.videolan.vlc.MediaDatabase;
> >> +import org.videolan.vlc.MediaLibrary;
> >> +import org.videolan.vlc.MediaWrapper;
> >> +import org.videolan.vlc.R;
> >> +import org.videolan.vlc.gui.audio.AudioBrowserListAdapter;
> >> +
> >> +import java.util.ArrayList;
> >> +
> >> +public class SavePlaylist extends DialogFragment implements
> AdapterView.OnItemClickListener, View.OnClickListener,
> TextView.OnEditorActionListener {
> >> +
> >> +    public final static String TAG = "VLC/SavePlaylist";
> >> +
> >> +    public static final String KEY_TRACKS = "PLAYLIST_TRACKS";
> >> +
> >> +    EditText mEditText;
> >> +    ListView mListView;
> >> +    TextView mEmptyView;
> >> +    Button mSaveButton;
> >> +    AudioBrowserListAdapter mAdapter;
> >> +    ArrayList<MediaWrapper> mTracks;
> >> +
> >> +    public SavePlaylist(){}
> >> +
> >> +    @Override
> >> +    public void onCreate(Bundle savedInstanceState) {
> >> +        super.onCreate(savedInstanceState);
> >> +        mAdapter = new AudioBrowserListAdapter(getActivity(),
> AudioBrowserListAdapter.ITEM_WITHOUT_COVER);
> >> +
> mAdapter.addAll(MediaLibrary.getInstance().getPlaylistDbItems());
> >> +        mTracks = getArguments().getParcelableArrayList(KEY_TRACKS);
> >> +    }
> >> +
> >> +    @Override
> >> +    public View onCreateView(LayoutInflater inflater, @Nullable
> ViewGroup container, @Nullable Bundle savedInstanceState) {
> >> +
> getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
> >> +        View view = inflater.inflate(R.layout.dialog_playlist,
> container);
> >> +
> >> +        mListView = (ListView) view.findViewById(android.R.id.list);
> >> +        mSaveButton = (Button)
> view.findViewById(R.id.dialog_playlist_save);
> >> +        mEmptyView = (TextView) view.findViewById(android.R.id.empty);
> >> +        mEditText = (EditText)
> view.findViewById(R.id.dialog_playlist_name);
> >> +        mListView.setOnItemClickListener(this);
> >> +        mSaveButton.setOnClickListener(this);
> >> +
> >> +        mEditText.setOnEditorActionListener(this);
> >> +        mListView.setEmptyView(mEmptyView);
> >> +        mListView.setAdapter(mAdapter);
> >> +        return view;
> >> +    }
> >> +
> >> +    @Override
> >> +    public void onItemClick(AdapterView<?> parent, View view, int
> position, long id) {
> >> +        mEditText.setText(mAdapter.getItem(position).mTitle);
> >> +    }
> >> +
> >> +    @Override
> >> +    public void onClick(View v) {
> >> +        savePlaylist();
> >> +    }
> >> +
> >> +    @Override
> >> +    public boolean onEditorAction(TextView v, int actionId, KeyEvent
> event) {
> >> +        if (actionId == EditorInfo.IME_ACTION_SEND) {
> >> +            savePlaylist();
> >> +        }
> >> +        return false;
> >> +    }
> >> +
> >> +    private void savePlaylist() {
> >> +        final MediaDatabase db = MediaDatabase.getInstance();
> >> +        final String name = mEditText.getText().toString().trim();
> >> +        if (db.playlistExists(name))
> >> +            db.playlistDelete(name);
> >> +        db.playlistAdd(name);
> >> +        MediaWrapper mw;
> >> +        for (int i = 0 ; i< mTracks.size() ; ++i){
> >> +            mw = mTracks.get(i);
> >> +            db.playlistInsertItem(name, i, mw.getLocation());
> >> +        }
> >> +        dismiss();
> >> +    }
> >> +}
> >> --
> >> 2.1.0
> >>
> >>
> >> _______________________________________________
> >> Android mailing list
> >> Android at videolan.org
> >> https://mailman.videolan.org/listinfo/android
> >
> > --
> > With my kindest regards,
> >
> > --
> > Jean-Baptiste Kempf
> > http://www.jbkempf.com/ - +33 672 704 734
> > Sent from my Electronic Device
> >
> > _______________________________________________
> > Android mailing list
> > Android at videolan.org
> > https://mailman.videolan.org/listinfo/android
> >
>
> _______________________________________________
> Android mailing list
> Android at videolan.org
> https://mailman.videolan.org/listinfo/android
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/android/attachments/20150324/b2e9622e/attachment-0001.html>


More information about the Android mailing list