Compare commits
145 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cedc1837f6 | ||
|
|
31d29925b9 | ||
|
|
5c00b79dff | ||
|
|
7e1cf58998 | ||
|
|
b3b809ebb9 | ||
|
|
8def943103 | ||
|
|
6cf57665f4 | ||
|
|
89e755fdf8 | ||
|
|
3fa6a9909d | ||
|
|
1ddbb3edff | ||
|
|
0f00ad0ebf | ||
|
|
deb6b64035 | ||
|
|
8556a04813 | ||
|
|
d38b4e23c0 | ||
|
|
c7625a61c0 | ||
|
|
fe0ab425cc | ||
|
|
0e6bdb54fb | ||
|
|
3716dc558c | ||
|
|
7b6bccf549 | ||
|
|
f98519d590 | ||
|
|
4ca7102a7e | ||
|
|
cfdbb072a3 | ||
|
|
4b484911ea | ||
|
|
3e81856de9 | ||
|
|
f5c48430ee | ||
|
|
5d98ec27c2 | ||
|
|
d3e6d26af9 | ||
|
|
1c1a42c4c9 | ||
|
|
1f51895854 | ||
|
|
a20eb7a71d | ||
|
|
5a6c4cddcb | ||
|
|
aba394305a | ||
|
|
ce72cc1b44 | ||
|
|
fd841ff564 | ||
|
|
e94cc5a320 | ||
|
|
55394a3773 | ||
|
|
dc56cd7dbb | ||
|
|
8a5b8b8ffe | ||
|
|
cfc68a9ee6 | ||
|
|
d09ee78b02 | ||
|
|
7ac64ace58 | ||
|
|
821b790200 | ||
|
|
495b1b93b9 | ||
|
|
0d4ed78392 | ||
|
|
3d7f476bad | ||
|
|
db7f481005 | ||
|
|
7f7e1cc028 | ||
|
|
3c79824d4b | ||
|
|
86d31810d7 | ||
|
|
ea6b9f604a | ||
|
|
b333e99fe2 | ||
|
|
5ae3d0bc6c | ||
|
|
746a1b711d | ||
|
|
8676a19930 | ||
|
|
51da943300 | ||
|
|
7dedf17a6b | ||
|
|
43b011eb6f | ||
|
|
3d08646df1 | ||
|
|
157074b08c | ||
|
|
99de86a838 | ||
|
|
d884268eb4 | ||
|
|
5e4bd5b878 | ||
|
|
1b0f1a5a8b | ||
|
|
dfa3bf10f8 | ||
|
|
fdbb708da3 | ||
|
|
fbee081409 | ||
|
|
b16c0c2cd0 | ||
|
|
65e17298ee | ||
|
|
48ee977295 | ||
|
|
055c986534 | ||
|
|
9fb2c7d8e0 | ||
|
|
2d603de7ce | ||
|
|
a48f838506 | ||
|
|
bf5aeddf6d | ||
|
|
94a66434bf | ||
|
|
3127236c3d | ||
|
|
b4f9adf6a0 | ||
|
|
165f628ead | ||
|
|
d2cc25317a | ||
|
|
45bef07589 | ||
|
|
fd481d1666 | ||
|
|
3129b510f6 | ||
|
|
6924073b0f | ||
|
|
e36f3a6e1e | ||
|
|
c67883d4d1 | ||
|
|
5b9c94da47 | ||
|
|
c3b48fc9f4 | ||
|
|
4d514eb727 | ||
|
|
cbda133cd9 | ||
|
|
2fde878007 | ||
|
|
55cfdfce1b | ||
|
|
faa0bfbc31 | ||
|
|
78b21d5bbb | ||
|
|
232c06f896 | ||
|
|
410531fe29 | ||
|
|
2a948279cd | ||
|
|
047fe044cc | ||
|
|
a6c1699c65 | ||
|
|
bbcfed1de1 | ||
|
|
3c012459f7 | ||
|
|
6389c6c7d1 | ||
|
|
c6cfc6c3fc | ||
|
|
20ca3b3f4e | ||
|
|
43abbbb4b3 | ||
|
|
dcc31d62a0 | ||
|
|
ec2f18db98 | ||
|
|
693b5017a3 | ||
|
|
664cbb6ad9 | ||
|
|
b782d5408a | ||
|
|
1dbf788aea | ||
|
|
2ae98f99e0 | ||
|
|
fd89c16a05 | ||
|
|
594a0c8479 | ||
|
|
2b436fb557 | ||
|
|
01fca5d2f8 | ||
|
|
5fce552a8a | ||
|
|
cecf7b489c | ||
|
|
c04710ce98 | ||
|
|
470ee065ff | ||
|
|
5dd734a84c | ||
|
|
c7b1f739f2 | ||
|
|
2360517f2e | ||
|
|
721d85246b | ||
|
|
2015dbef4e | ||
|
|
8e8696f11d | ||
|
|
3569c2d410 | ||
|
|
08b3551d83 | ||
|
|
3a408aed94 | ||
|
|
8d1c52f5fa | ||
|
|
3fa8735553 | ||
|
|
c7a4fab1fd | ||
|
|
5a0541de42 | ||
|
|
82844b852d | ||
|
|
cb6994e597 | ||
|
|
1edbc1cab4 | ||
|
|
011e872e74 | ||
|
|
ec342b73f3 | ||
|
|
21ca209561 | ||
|
|
7bb86946ce | ||
|
|
73c2214b5a | ||
|
|
32866f8718 | ||
|
|
f956b4869b | ||
|
|
65716ff340 | ||
|
|
845a4c1f93 | ||
|
|
6d9331353f |
66
NEWS
@@ -1,3 +1,69 @@
|
||||
Changes between 3.0.5 and 3.0.5-2:
|
||||
----------------------------------
|
||||
|
||||
Application:
|
||||
* Deactivate Android Auto
|
||||
|
||||
VLC:
|
||||
* Fix crash on Android 4
|
||||
|
||||
Changes between 3.0.4 and 3.0.5:
|
||||
----------------------------------
|
||||
|
||||
Application:
|
||||
* Audio digital output (passthrough) is now disabled by default
|
||||
* Fix video seek at wrong time on playback resume
|
||||
* Fix renderer staying 'connected' when wifi is turned off
|
||||
* Video tracks selector in video player
|
||||
* Fix load last playlist from headset on Android 2-4
|
||||
* Misc. fixes
|
||||
|
||||
VLC:
|
||||
* Chromecast improvements
|
||||
* stabilization
|
||||
|
||||
Changes between 3.0.2 and 3.0.4:
|
||||
----------------------------------
|
||||
|
||||
Application:
|
||||
* Fix medialibrary missing some media
|
||||
* Fix last playlist restoration
|
||||
|
||||
TV:
|
||||
* Fix History display
|
||||
|
||||
|
||||
Changes between 3.0.1 and 3.0.2:
|
||||
----------------------------------
|
||||
|
||||
Application:
|
||||
* Support of external equalizers (for Android 5+)
|
||||
* Fix video player restore from background playback
|
||||
* Deactivate PiP feature in DeX mode
|
||||
* Restore DVD menu navigation on TV
|
||||
* Misc. fixes
|
||||
|
||||
VLC:
|
||||
* Improve Chromecast loading and playback
|
||||
* Improve mpeg2 files playback
|
||||
|
||||
Changes between 3.0.0 and 3.0.1:
|
||||
----------------------------------
|
||||
|
||||
Application:
|
||||
* Show real SDCard/USB storages name
|
||||
* Fix video playlist lost on app switch
|
||||
* Fix renderers dialog
|
||||
* Fix filter/search obstructed by options icons
|
||||
* Fix playback resume after phone calls
|
||||
* Fix shuffle mode being systematically erased
|
||||
* Fix browsing in medialibrary options
|
||||
* Do not stop when other apps play sounds while Chromecasting
|
||||
* New options to disable remote controls shortcuts
|
||||
* Fix video player controls on RTL devices
|
||||
* Fix network media saving in history
|
||||
* Misc. fixes
|
||||
|
||||
Changes between 2.9.1 and 3.0.0:
|
||||
----------------------------------
|
||||
|
||||
|
||||
86
assets/images/svg/ic_passthrough_normal.svg
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24"
|
||||
height="24"
|
||||
id="svg4682"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||
sodipodi:docname="ic_passthrough_normal.svg"
|
||||
inkscape:export-filename="/home/corbax/Dev/android/Icons/Test 1/ic_play_normal.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4684" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="15.839192"
|
||||
inkscape:cx="9.3499037"
|
||||
inkscape:cy="20.749633"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1052"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
inkscape:snap-text-baseline="true"
|
||||
inkscape:snap-page="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3002" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata4687">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1028.3622)">
|
||||
<g
|
||||
id="g5269"
|
||||
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Roboto;-inkscape-font-specification:Roboto"
|
||||
transform="translate(-64,740.00002)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#212121;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 3.5,1033.3622 c -0.831,0 -1.5,0.669 -1.5,1.5 v 11 c 0,0.831 0.669,1.5 1.5,1.5 h 13 c 0.831,0 1.5,-0.669 1.5,-1.5 v -3 h -1.5 v 3 h -13 v -11 h 13 v 3 H 18 v -3 c 0,-0.831 -0.669,-1.5 -1.5,-1.5 z m 10.03516,3.4668 -0.88477,0.8848 a 3.75,3.75 0 0 1 1.09961,2.6484 3.75,3.75 0 0 1 -1.09961,2.6523 l 0.88281,0.8829 A 5,5 0 0 0 15,1040.3622 5,5 0 0 0 13.53516,1036.829 Z m -7.06836,0 A 5,5 0 0 0 5,1040.3622 a 5,5 0 0 0 1.4668,3.5352 l 0.88476,-0.8848 A 3.75,3.75 0 0 1 6.25,1040.3622 3.75,3.75 0 0 1 7.34961,1037.7138 Z M 19,1037.3642 v 2 h -2.5 v 2 H 19 v 2 l 3,-3 z m -9,0.498 a 2.5,2.5 0 0 0 -2.5,2.5 2.5,2.5 0 0 0 2.5,2.5 2.5,2.5 0 0 0 2.5,-2.5 2.5,2.5 0 0 0 -2.5,-2.5 z m 0,1.25 a 1.25,1.25 0 0 1 1.25,1.25 1.25,1.25 0 0 1 -1.25,1.25 1.25,1.25 0 0 1 -1.25,-1.25 1.25,1.25 0 0 1 1.25,-1.25 z"
|
||||
id="path4897" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
86
assets/images/svg/ic_passthrough_normal_o.svg
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24"
|
||||
height="24"
|
||||
id="svg4682"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||
sodipodi:docname="ic_passthrough_normal_o.svg"
|
||||
inkscape:export-filename="/home/corbax/Dev/android/Icons/Test 1/ic_play_normal.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4684" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="15.839192"
|
||||
inkscape:cx="9.3499037"
|
||||
inkscape:cy="20.749633"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1052"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
inkscape:snap-text-baseline="true"
|
||||
inkscape:snap-page="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3002" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata4687">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1028.3622)">
|
||||
<g
|
||||
id="g5269"
|
||||
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Roboto;-inkscape-font-specification:Roboto"
|
||||
transform="translate(-64,740.00002)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ff8800;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 3.5,1033.3622 c -0.831,0 -1.5,0.669 -1.5,1.5 v 11 c 0,0.831 0.669,1.5 1.5,1.5 h 13 c 0.831,0 1.5,-0.669 1.5,-1.5 v -3 h -1.5 v 3 h -13 v -11 h 13 v 3 H 18 v -3 c 0,-0.831 -0.669,-1.5 -1.5,-1.5 z m 10.03516,3.4668 -0.88477,0.8848 a 3.75,3.75 0 0 1 1.09961,2.6484 3.75,3.75 0 0 1 -1.09961,2.6523 l 0.88281,0.8829 A 5,5 0 0 0 15,1040.3622 5,5 0 0 0 13.53516,1036.829 Z m -7.06836,0 A 5,5 0 0 0 5,1040.3622 a 5,5 0 0 0 1.4668,3.5352 l 0.88476,-0.8848 A 3.75,3.75 0 0 1 6.25,1040.3622 3.75,3.75 0 0 1 7.34961,1037.7138 Z M 19,1037.3642 v 2 h -2.5 v 2 H 19 v 2 l 3,-3 z m -9,0.498 a 2.5,2.5 0 0 0 -2.5,2.5 2.5,2.5 0 0 0 2.5,2.5 2.5,2.5 0 0 0 2.5,-2.5 2.5,2.5 0 0 0 -2.5,-2.5 z m 0,1.25 a 1.25,1.25 0 0 1 1.25,1.25 1.25,1.25 0 0 1 -1.25,1.25 1.25,1.25 0 0 1 -1.25,-1.25 1.25,1.25 0 0 1 1.25,-1.25 z"
|
||||
id="path4897" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
86
assets/images/svg/ic_passthrough_normal_w.svg
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24"
|
||||
height="24"
|
||||
id="svg4682"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||
sodipodi:docname="ic_passthrough_normal_w.svg"
|
||||
inkscape:export-filename="/home/corbax/Dev/android/Icons/Test 1/ic_play_normal.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4684" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="15.839192"
|
||||
inkscape:cx="9.3499037"
|
||||
inkscape:cy="20.749633"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1052"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
inkscape:snap-text-baseline="true"
|
||||
inkscape:snap-page="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3002" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata4687">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1028.3622)">
|
||||
<g
|
||||
id="g5269"
|
||||
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#fafafa;fill-opacity:1;stroke:none;font-family:Roboto;-inkscape-font-specification:Roboto"
|
||||
transform="translate(-64,740.00002)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fafafa;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 3.5,1033.3622 c -0.831,0 -1.5,0.669 -1.5,1.5 v 11 c 0,0.831 0.669,1.5 1.5,1.5 h 13 c 0.831,0 1.5,-0.669 1.5,-1.5 v -3 h -1.5 v 3 h -13 v -11 h 13 v 3 H 18 v -3 c 0,-0.831 -0.669,-1.5 -1.5,-1.5 z m 10.03516,3.4668 -0.88477,0.8848 a 3.75,3.75 0 0 1 1.09961,2.6484 3.75,3.75 0 0 1 -1.09961,2.6523 l 0.88281,0.8829 A 5,5 0 0 0 15,1040.3622 5,5 0 0 0 13.53516,1036.829 Z m -7.06836,0 A 5,5 0 0 0 5,1040.3622 a 5,5 0 0 0 1.4668,3.5352 l 0.88476,-0.8848 A 3.75,3.75 0 0 1 6.25,1040.3622 3.75,3.75 0 0 1 7.34961,1037.7138 Z M 19,1037.3642 v 2 h -2.5 v 2 H 19 v 2 l 3,-3 z m -9,0.498 a 2.5,2.5 0 0 0 -2.5,2.5 2.5,2.5 0 0 0 2.5,2.5 2.5,2.5 0 0 0 2.5,-2.5 2.5,2.5 0 0 0 -2.5,-2.5 z m 0,1.25 a 1.25,1.25 0 0 1 1.25,1.25 1.25,1.25 0 0 1 -1.25,1.25 1.25,1.25 0 0 1 -1.25,-1.25 1.25,1.25 0 0 1 1.25,-1.25 z"
|
||||
id="path4897" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
86
assets/images/svg/ic_passthrough_pressed.svg
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24"
|
||||
height="24"
|
||||
id="svg4682"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||
sodipodi:docname="ic_passthrough_pressed.svg"
|
||||
inkscape:export-filename="/home/corbax/Dev/android/Icons/Test 1/ic_play_normal.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4684" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="22.4"
|
||||
inkscape:cx="9.8468043"
|
||||
inkscape:cy="10.389602"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1052"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
inkscape:snap-text-baseline="true"
|
||||
inkscape:snap-page="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3002" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata4687">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1028.3622)">
|
||||
<g
|
||||
id="g5269"
|
||||
style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Roboto;-inkscape-font-specification:Roboto"
|
||||
transform="translate(-64,740.00002)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffb54c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 3.5,1033.3622 c -0.831,0 -1.5,0.669 -1.5,1.5 v 11 c 0,0.831 0.669,1.5 1.5,1.5 h 13 c 0.831,0 1.5,-0.669 1.5,-1.5 v -3 h -1.5 v 3 h -13 v -11 h 13 v 3 H 18 v -3 c 0,-0.831 -0.669,-1.5 -1.5,-1.5 z m 10.03516,3.4668 -0.88477,0.8848 a 3.75,3.75 0 0 1 1.09961,2.6484 3.75,3.75 0 0 1 -1.09961,2.6523 l 0.88281,0.8829 A 5,5 0 0 0 15,1040.3622 5,5 0 0 0 13.53516,1036.829 Z m -7.06836,0 A 5,5 0 0 0 5,1040.3622 a 5,5 0 0 0 1.4668,3.5352 l 0.88476,-0.8848 A 3.75,3.75 0 0 1 6.25,1040.3622 3.75,3.75 0 0 1 7.34961,1037.7138 Z M 19,1037.3642 v 2 h -2.5 v 2 H 19 v 2 l 3,-3 z m -9,0.498 a 2.5,2.5 0 0 0 -2.5,2.5 2.5,2.5 0 0 0 2.5,2.5 2.5,2.5 0 0 0 2.5,-2.5 2.5,2.5 0 0 0 -2.5,-2.5 z m 0,1.25 a 1.25,1.25 0 0 1 1.25,1.25 1.25,1.25 0 0 1 -1.25,1.25 1.25,1.25 0 0 1 -1.25,-1.25 1.25,1.25 0 0 1 1.25,-1.25 z"
|
||||
id="path4897" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
@@ -9,11 +9,11 @@
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="544"
|
||||
height="640"
|
||||
width="272"
|
||||
height="320"
|
||||
id="svg5199"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.1 r15371"
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||
sodipodi:docname="renderer_background_cone.svg">
|
||||
<defs
|
||||
id="defs5201" />
|
||||
@@ -24,22 +24,33 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.7"
|
||||
inkscape:cx="243.05353"
|
||||
inkscape:cy="145.14267"
|
||||
inkscape:zoom="2"
|
||||
inkscape:cx="30.692463"
|
||||
inkscape:cy="181.32624"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:snap-grids="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1027"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-height="1052"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="80"
|
||||
fit-margin-left="80"
|
||||
fit-margin-right="80"
|
||||
fit-margin-bottom="80">
|
||||
fit-margin-bottom="80"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid5236"
|
||||
@@ -58,7 +69,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@@ -66,11 +77,12 @@
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-108,-332.36273)">
|
||||
transform="translate(-108,-652.36273)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#ff8800;fill-opacity:0.8509804;fill-rule:evenodd;stroke:none;stroke-width:32.00007248;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4.19999981;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="m 339.99947,412.36163 c -13.29603,0 -24.00006,10.70402 -24.00006,24.00005 v 56.00013 h 24.00006 v -56.00013 h 208.00048 v 176.00041 h -88.00021 v 24.00005 h 88.00021 C 561.29598,636.36214 572,625.65812 572,612.36209 V 436.36168 c 0,-13.29603 -10.70402,-24.00005 -24.00005,-24.00005 z m 24.00005,48.00011 v 40.43769 c 40.89978,14.49924 73.08065,46.66811 87.59396,87.5626 h 72.40641 V 460.36174 Z m -48.00011,56.00013 v 24.00005 c 53.01949,0 96.00022,42.9809 96.00022,96.00022 h 24.00006 c 0,-66.27535 -53.72588,-120.00027 -120.00028,-120.00027 z m 0,48.00011 v 24.00005 c 26.50966,0 48.00011,21.48965 48.00011,48.00011 h 24.00006 c 0,-39.76489 -32.2356,-72.00016 -72.00017,-72.00016 z m 0,49.97691 c -3.30152,0 -6.97429,0.384 -9.61722,2.35921 -5.22689,3.91281 -7.33914,10.19202 -11.89063,23.75805 -4.55149,13.56603 -4.75001,14.25003 -4.75001,14.25003 19.01065,9.50523 32.8116,10.39363 52.51572,0 0,0 -0.216,-0.7364 -4.75001,-14.25003 -4.53385,-13.51323 -6.63233,-19.75124 -11.89062,-23.75805 -2.62601,-2.00081 -6.3157,-2.35921 -9.61723,-2.35921 z m -42.89073,90.27341 v 0 l -19.00785,57.02333 -0.04,0.132 c 0.0848,-0.04 0.1488,-0.056 0.2344,-0.076 35.64488,30.89367 87.92572,30.89967 123.57061,0 0.024,0 0.0412,0.04 0.0624,0.04 l -0.032,-0.096 -19.00785,-57.01573 c -0.012,0 -0.028,0.04 -0.04,0.04 -28.82958,21.52725 -57.22649,21.33605 -85.74239,-0.056 z m -48.5548,85.547 c -6.31869,0 -12.19262,4.76561 -14.03907,11.06282 l -11.07034,37.66409 c -3.61681,12.35803 -7.20262,24.62445 -10.83599,37.04688 -1.52092,5.19201 3.2e-4,9.00882 2.45313,11.64843 1.51972,1.6344 3.39844,2.82201 5.12505,3.60961 1.72772,0.7676 2.90457,1.1716 4.26561,1.1716 3.17305,0 58.57445,-0.04 115.54714,-0.04 56.97269,0 112.37406,0.04 115.54715,0.04 1.361,0 2.5378,-0.404 4.26561,-1.1716 1.7266,-0.7876 3.60533,-1.97521 5.12505,-3.60961 2.45237,-2.63961 3.97401,-6.45642 2.45313,-11.64843 -3.63341,-12.42243 -7.21922,-24.68885 -10.83599,-37.04688 l -11.07034,-37.66409 c -1.84645,-6.29721 -7.72038,-11.06282 -14.03908,-11.06282 h -20.04692 c -0.008,0.04 -0.02,0.04 -0.032,0.064 0,0 3.1674,9.49642 4.75001,14.25003 2.29648,6.89841 3.43273,10.31362 0,14.26563 -16.70796,16.70804 -43.37042,25.61966 -70.61736,26.65606 -30.88267,1.184 -62.31975,-7.92562 -81.46111,-26.65606 -3.58453,-3.50761 -2.37729,-7.13602 0,-14.26563 1.58456,-4.75201 4.56249,-14.31283 4.56249,-14.31283 z"
|
||||
id="path8877" />
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;vector-effect:none;fill:#ff8800;fill-opacity:0.85098039;fill-rule:evenodd;stroke:none;stroke-width:16.00003433;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4.19999981;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="m 223.99957,692.36274 c -6.64804,0 -12.00006,5.352 -12.00006,11.99999 v 28.00001 h 12.00006 V 704.36273 H 328 v 88.00001 h -44.00019 v 11.99999 H 328 c 6.64802,0 12.00004,-5.35199 12.00004,-11.99999 v -88.00001 c 0,-6.64799 -5.35202,-11.99999 -12.00004,-11.99999 z m 12.00004,24 v 20.2188 c 20.44993,7.24961 36.54039,23.334 43.79706,43.7812 h 36.20328 v -64 z m -24.0001,28 v 11.99999 c 26.50979,0 48.0002,21.4904 48.0002,48 h 12.00006 c 0,-33.13759 -26.863,-59.99999 -60.00026,-59.99999 z m 0,24 v 12 c 13.25486,0 24.0001,10.74479 24.0001,23.99999 h 12.00005 c 0,-19.88239 -16.11783,-35.99999 -36.00015,-35.99999 z m 0,23.99999 c -1.65076,0 -3.48716,0.19337 -4.80862,1.18798 -2.61346,1.97033 -3.66958,5.13223 -5.94533,11.96346 -2.27574,6.83124 -2.375,7.17567 -2.375,7.17567 9.50534,4.7864 16.40582,5.23374 26.25791,0 0,0 -0.10801,-0.37083 -2.37502,-7.17567 -2.26693,-6.80464 -3.31616,-9.94581 -5.94532,-11.96346 -1.31301,-1.00751 -3.15786,-1.18798 -4.80862,-1.18798 z m -21.44541,45.45753 v 0 l -9.50394,28.71433 -0.02,0.0665 c 0.0424,-0.0201 0.0744,-0.0282 0.1172,-0.0383 17.82248,15.55662 43.96295,15.55964 61.78542,0 0.012,0 0.0206,0.0201 0.0312,0.0201 l -0.016,-0.0483 -9.50394,-28.7105 c -0.006,0 -0.014,0.0201 -0.02,0.0201 -14.41481,10.84013 -28.6133,10.74385 -42.87128,-0.0282 z m -24.27744,43.07753 c -3.15935,0 -6.09632,2.39975 -7.01955,5.57072 l -5.53518,18.96591 c -1.80841,6.22294 -3.60132,12.39974 -5.41801,18.65511 -0.76046,2.61445 1.6e-4,4.53643 1.22658,5.8656 0.75985,0.82301 1.69922,1.42104 2.56252,1.81764 0.86386,0.38653 1.45229,0.58997 2.13281,0.58997 1.58653,0 29.28728,-0.0201 57.77368,-0.0201 28.4864,0 56.18714,0.0201 57.77368,0.0201 0.6805,0 1.2689,-0.20344 2.13281,-0.58997 0.86331,-0.3966 1.80267,-0.99463 2.56253,-1.81764 1.22619,-1.32917 1.98701,-3.25115 1.22657,-5.8656 -1.81671,-6.25537 -3.60962,-12.43217 -5.41801,-18.65511 l -5.53518,-18.96591 c -0.92322,-3.17097 -3.8602,-5.57072 -7.01955,-5.57072 h -10.02348 c -0.004,0.0202 -0.01,0.0202 -0.016,0.0322 0,0 1.58371,4.78196 2.37502,7.17567 1.14824,3.47373 1.71637,5.19347 0,7.18351 -8.354,8.4134 -21.68525,12.90089 -35.30875,13.42277 -15.44136,0.59621 -31.15993,-3.99099 -40.73063,-13.42277 -1.79227,-1.76626 -1.18864,-3.59336 0,-7.18351 0.79228,-2.3929 2.28125,-7.20728 2.28125,-7.20728 z"
|
||||
id="path8877"
|
||||
sodipodi:nodetypes="sscccccccsssssccccccccccccccccsccccccsccccccccccccccccccssscccccsccccccccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 5.1 KiB |
@@ -25,13 +25,13 @@ allprojects {
|
||||
|
||||
ext {
|
||||
appCompatVersion = '25.2.0'
|
||||
constraintLayoutVersion = '1.1.0-beta4'
|
||||
constraintLayoutVersion = '1.1.0-beta6'
|
||||
buildToolsVersion = "27.0.2"
|
||||
compileSdkVersion = 26
|
||||
minSdkVersion = 9
|
||||
targetSdkVersion = 26
|
||||
versionName = '3.0.0'
|
||||
versionCode = 3000000
|
||||
versionName = '3.0.5'
|
||||
versionCode = 3000520
|
||||
// versionCode scheme is T M NN RR AA
|
||||
// T: Target/Flavour (1 for Android, 2 for Chrome?)
|
||||
// M: Major version from 0 to 9
|
||||
|
||||
@@ -16,7 +16,7 @@ checkfail()
|
||||
# ARGUMENTS #
|
||||
#############
|
||||
|
||||
MEDIALIBRARY_HASH=5be920a
|
||||
MEDIALIBRARY_HASH=69d9ea1
|
||||
|
||||
BUILD_ML=1
|
||||
RELEASE=0
|
||||
@@ -774,6 +774,7 @@ if [ ! -d "${MEDIALIBRARY_MODULE_DIR}/medialibrary" ]; then
|
||||
git clone http://code.videolan.org/videolan/medialibrary.git "${SRC_DIR}/medialibrary/medialibrary"
|
||||
checkfail "medialibrary source: git clone failed"
|
||||
cd ${MEDIALIBRARY_MODULE_DIR}/medialibrary
|
||||
git checkout 0.3.x
|
||||
git submodule update --init libvlcpp
|
||||
else
|
||||
cd ${MEDIALIBRARY_MODULE_DIR}/medialibrary
|
||||
|
||||
@@ -233,7 +233,7 @@ fi
|
||||
# Fetch VLC source #
|
||||
####################
|
||||
|
||||
TESTED_HASH=ef4c265
|
||||
TESTED_HASH=ed58f0c
|
||||
if [ ! -d "vlc" ]; then
|
||||
diagnostic "VLC source not found, cloning"
|
||||
git clone https://git.videolan.org/git/vlc/vlc-3.0.git vlc
|
||||
|
||||
@@ -32,12 +32,10 @@ android {
|
||||
def manifestParser = new DefaultManifestParser(android.sourceSets.main.manifest.srcFile)
|
||||
// get the version code of each flavor
|
||||
def vlcVersion = manifestParser.getVersionName()
|
||||
manifestParser = new DefaultManifestParser(file('../vlc-android/AndroidManifest.xml'))
|
||||
def androidVersion = manifestParser.getVersionName()
|
||||
//Custom APK name
|
||||
variant.outputs.all { output ->
|
||||
if (outputFileName != null && outputFileName.endsWith('.aar')) {
|
||||
outputFileName = "libvlc-${vlcVersion}-${androidVersion}.aar"
|
||||
outputFileName = "libvlc-${vlcVersion}.aar"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,12 @@ public interface IVLCVout {
|
||||
* LayoutsParams accordingly. If width and height are 0, LayoutParams should be reset to the
|
||||
* initial state (MATCH_PARENT).
|
||||
*
|
||||
* By default, "android-display" is used when doing HW decoding and if Video and Subtitles
|
||||
* surfaces are correctly attached. You could force "--vout=android-display" from LibVLC
|
||||
* arguments if you want to use this module without subtitles. Otherwise, the "opengles2"
|
||||
* module will be used (for SW and HW decoding) and this callback will always send a size of
|
||||
* 0.
|
||||
*
|
||||
* @param vlcVout vlcVout
|
||||
* @param width Frame width
|
||||
* @param height Frame height
|
||||
|
||||
@@ -417,6 +417,9 @@ public class Media extends VLCObject<Media.Event> {
|
||||
private int mState = -1;
|
||||
private int mType = -1;
|
||||
private boolean mCodecOptionSet = false;
|
||||
private boolean mFileCachingSet = false;
|
||||
private boolean mNetworkCachingSet = false;
|
||||
|
||||
|
||||
/**
|
||||
* Create a Media from libVLC and a local path starting with '/'.
|
||||
@@ -757,8 +760,10 @@ public class Media extends VLCObject<Media.Event> {
|
||||
* for 320x170 H.264, a few packets less on higher resolutions.
|
||||
* On Nexus S, the decoder latency seems to be about 7 packets.
|
||||
*/
|
||||
addOption(":file-caching=1500");
|
||||
addOption(":network-caching=1500");
|
||||
if (!mFileCachingSet)
|
||||
addOption(":file-caching=1500");
|
||||
if (!mNetworkCachingSet)
|
||||
addOption(":network-caching=1500");
|
||||
|
||||
final StringBuilder sb = new StringBuilder(":codec=");
|
||||
if (decoder == HWDecoderUtil.Decoder.MEDIACODEC || decoder == HWDecoderUtil.Decoder.ALL)
|
||||
@@ -781,6 +786,11 @@ public class Media extends VLCObject<Media.Event> {
|
||||
}
|
||||
if (!codecOptionSet)
|
||||
setHWDecoderEnabled(true, false);
|
||||
|
||||
/* dvdnav need to be explicitly forced for network playbacks */
|
||||
if (mUri != null && mUri.getScheme() != null && !mUri.getScheme().equalsIgnoreCase("file") &&
|
||||
mUri.getLastPathSegment() != null && mUri.getLastPathSegment().toLowerCase().endsWith(".iso"))
|
||||
addOption(":demux=dvdnav,any");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -792,6 +802,10 @@ public class Media extends VLCObject<Media.Event> {
|
||||
synchronized (this) {
|
||||
if (!mCodecOptionSet && option.startsWith(":codec="))
|
||||
mCodecOptionSet = true;
|
||||
if (!mNetworkCachingSet && option.startsWith(":network-caching="))
|
||||
mNetworkCachingSet = true;
|
||||
if (!mFileCachingSet && option.startsWith(":file-caching="))
|
||||
mFileCachingSet = true;
|
||||
}
|
||||
nativeAddOption(option);
|
||||
}
|
||||
|
||||
@@ -362,13 +362,14 @@ public class MediaPlayer extends VLCObject<MediaPlayer.Event> {
|
||||
private Media mMedia = null;
|
||||
private boolean mPlaying = false;
|
||||
private boolean mPlayRequested = false;
|
||||
private boolean mAudioDeviceFromUser = false;
|
||||
private boolean mListenAudioPlug = true;
|
||||
private int mVoutCount = 0;
|
||||
private boolean mAudioReset = false;
|
||||
private String mAudioOutput = "android_audiotrack";
|
||||
private String mAudioOutputDevice = null;
|
||||
|
||||
private boolean mAudioPlugRegistered = false;
|
||||
private boolean mAudioDigitalOutputEnabled = false;
|
||||
private String mAudioPlugOutputDevice = "stereo";
|
||||
|
||||
private final AWindow mWindow = new AWindow(new AWindow.SurfaceCallback() {
|
||||
@@ -400,8 +401,8 @@ public class MediaPlayer extends VLCObject<MediaPlayer.Event> {
|
||||
}
|
||||
});
|
||||
|
||||
private void updateAudioOutputDevice(long encodingFlags, String defaultDevice) {
|
||||
final String newDeviceId = encodingFlags != 0 ? "encoded:" + encodingFlags : defaultDevice;
|
||||
private synchronized void updateAudioOutputDevice(long encodingFlags, String defaultDevice) {
|
||||
final String newDeviceId = mAudioDigitalOutputEnabled && encodingFlags != 0 ? "encoded:" + encodingFlags : defaultDevice;
|
||||
if (!newDeviceId.equals(mAudioPlugOutputDevice)) {
|
||||
mAudioPlugOutputDevice = newDeviceId;
|
||||
setAudioOutputDeviceInternal(mAudioPlugOutputDevice, false);
|
||||
@@ -615,7 +616,7 @@ public class MediaPlayer extends VLCObject<MediaPlayer.Event> {
|
||||
nativeSetAudioOutputDevice(mAudioOutputDevice);
|
||||
mAudioReset = false;
|
||||
}
|
||||
if (!mAudioDeviceFromUser)
|
||||
if (mListenAudioPlug)
|
||||
registerAudioPlug(true);
|
||||
mPlayRequested = true;
|
||||
if (mWindow.areSurfacesWaiting())
|
||||
@@ -690,6 +691,10 @@ public class MediaPlayer extends VLCObject<MediaPlayer.Event> {
|
||||
nativeSetAspectRatio(aspect);
|
||||
}
|
||||
|
||||
private boolean isAudioTrack() {
|
||||
return mAudioOutput != null && mAudioOutput.equals("android_audiotrack");
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the video viewpoint information
|
||||
*
|
||||
@@ -717,50 +722,108 @@ public class MediaPlayer extends VLCObject<MediaPlayer.Event> {
|
||||
*
|
||||
* @return true on success.
|
||||
*/
|
||||
public boolean setAudioOutput(String aout) {
|
||||
public synchronized boolean setAudioOutput(String aout) {
|
||||
mAudioOutput = aout;
|
||||
/* If The user forced an output different than AudioTrack, don't listen to audio
|
||||
* plug events and let the user decide */
|
||||
mListenAudioPlug = isAudioTrack();
|
||||
if (!mListenAudioPlug)
|
||||
registerAudioPlug(false);
|
||||
|
||||
final boolean ret = nativeSetAudioOutput(aout);
|
||||
if (ret) {
|
||||
synchronized (this) {
|
||||
mAudioOutput = aout;
|
||||
/* The user forced an output, don't listen to audio plug events and let the user decide */
|
||||
mAudioDeviceFromUser = true;
|
||||
|
||||
if (!ret) {
|
||||
mAudioOutput = null;
|
||||
mListenAudioPlug = false;
|
||||
}
|
||||
|
||||
if (mListenAudioPlug)
|
||||
registerAudioPlug(true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable Digital Output
|
||||
*
|
||||
* Works only with AudioTrack AudioOutput.
|
||||
* If {@link #setAudioOutputDevice} was previously called, this method won't have any effects.
|
||||
*
|
||||
* @param enabled true to enable Digital Output
|
||||
* @return true on success
|
||||
*/
|
||||
public synchronized boolean setAudioDigitalOutputEnabled(boolean enabled) {
|
||||
if (enabled == mAudioDigitalOutputEnabled)
|
||||
return true;
|
||||
if (!mListenAudioPlug || !isAudioTrack())
|
||||
return false;
|
||||
|
||||
registerAudioPlug(false);
|
||||
mAudioDigitalOutputEnabled = enabled;
|
||||
registerAudioPlug(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Convenient method for {@link #setAudioOutputDevice}
|
||||
*
|
||||
* @param encodings list of encodings to play via passthrough (see AudioFormat.ENCODING_*),
|
||||
* null to don't force any.
|
||||
* @return true on success
|
||||
*/
|
||||
public synchronized boolean forceAudioDigitalEncodings(int []encodings) {
|
||||
if (!isAudioTrack())
|
||||
return false;
|
||||
|
||||
if (encodings.length == 0)
|
||||
setAudioOutputDeviceInternal(null, true);
|
||||
else {
|
||||
final String newDeviceId = "encoded:" + getEncodingFlags(encodings);
|
||||
if (!newDeviceId.equals(mAudioPlugOutputDevice)) {
|
||||
mAudioPlugOutputDevice = newDeviceId;
|
||||
setAudioOutputDeviceInternal(mAudioPlugOutputDevice, true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private synchronized boolean setAudioOutputDeviceInternal(String id, boolean fromUser) {
|
||||
mAudioOutputDevice = id;
|
||||
if (fromUser) {
|
||||
/* The user forced a device, don't listen to audio plug events and let the user decide */
|
||||
mListenAudioPlug = mAudioOutputDevice == null && isAudioTrack();
|
||||
if (!mListenAudioPlug)
|
||||
registerAudioPlug(false);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private boolean setAudioOutputDeviceInternal(String id, boolean fromUser) {
|
||||
final boolean ret = nativeSetAudioOutputDevice(id);
|
||||
if (ret) {
|
||||
synchronized (this) {
|
||||
mAudioOutputDevice = id;
|
||||
if (fromUser) {
|
||||
/* The user forced a device, don't listen to audio plug events and let the user decide */
|
||||
mAudioDeviceFromUser = true;
|
||||
registerAudioPlug(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
mAudioOutputDevice = null;
|
||||
mListenAudioPlug = false;
|
||||
}
|
||||
|
||||
if (mListenAudioPlug)
|
||||
registerAudioPlug(true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures an explicit audio output device.
|
||||
* Audio output will be moved to the device specified by the device identifier string.
|
||||
*
|
||||
* Available devices for the "android_audiotrack" module (the default) are
|
||||
* "stereo": Up to 2 channels (compat mode).
|
||||
* "pcm": Up to 8 channels.
|
||||
* "encoded": Up to 8 channels, passthrough for every encodings if available.
|
||||
* "encoded:ENCODING_FLAGS_MASK": passthrough for every encodings specified by
|
||||
* ENCODING_FLAGS_MASK. This extra value is a long that contains binary-shifted
|
||||
* AudioFormat.ENCODING_* values.
|
||||
*
|
||||
* Calling this method will disable the encoding detection (see {@link #setAudioOutput}).
|
||||
*
|
||||
* @return true on success.
|
||||
*/
|
||||
/**
|
||||
* Configures an explicit audio output device.
|
||||
* Audio output will be moved to the device specified by the device identifier string.
|
||||
*
|
||||
* Available devices for the "android_audiotrack" module (the default) are
|
||||
* "stereo": Up to 2 channels (compat mode).
|
||||
* "pcm": Up to 8 channels.
|
||||
* "encoded": Up to 8 channels, passthrough for every encodings if available.
|
||||
* "encoded:ENCODING_FLAGS_MASK": passthrough for every encodings specified by
|
||||
* ENCODING_FLAGS_MASK. This extra value is a long that contains binary-shifted
|
||||
* AudioFormat.ENCODING_* values.
|
||||
*
|
||||
* Calling this method will disable the encoding detection (see {@link #setAudioOutput} and {@link #setAudioDigitalOutputEnabled(boolean)}).
|
||||
*
|
||||
* @return true on success.
|
||||
*/
|
||||
public boolean setAudioOutputDevice(String id) {
|
||||
return setAudioOutputDeviceInternal(id, true);
|
||||
}
|
||||
|
||||
@@ -113,12 +113,11 @@ public class Medialibrary {
|
||||
}
|
||||
|
||||
public boolean addDevice(@NonNull String uuid, @NonNull String path, boolean removable) {
|
||||
return nativeAddDevice(VLCUtil.encodeVLCString(uuid), Tools.encodeVLCMrl(path), removable);
|
||||
return nativeAddDevice(Tools.encodeVLCMrl(uuid), Tools.encodeVLCMrl(path), removable);
|
||||
}
|
||||
|
||||
public void discover(@NonNull String path) {
|
||||
if (mIsInitiated)
|
||||
nativeDiscover(Tools.encodeVLCMrl(path));
|
||||
if (mIsInitiated) nativeDiscover(Tools.encodeVLCMrl(path));
|
||||
}
|
||||
|
||||
public void removeFolder(@NonNull String mrl) {
|
||||
@@ -138,7 +137,7 @@ public class Medialibrary {
|
||||
}
|
||||
|
||||
public boolean removeDevice(String uuid) {
|
||||
return mIsInitiated && !TextUtils.isEmpty(uuid) && nativeRemoveDevice(VLCUtil.encodeVLCString(uuid));
|
||||
return mIsInitiated && !TextUtils.isEmpty(uuid) && nativeRemoveDevice(Tools.encodeVLCMrl(uuid));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -264,7 +263,7 @@ public class Medialibrary {
|
||||
}
|
||||
|
||||
public boolean addToHistory(String mrl, String title) {
|
||||
return mIsInitiated && nativeAddToHistory(Tools.encodeVLCMrl(mrl), VLCUtil.encodeVLCString(title));
|
||||
return mIsInitiated && nativeAddToHistory(Tools.encodeVLCMrl(mrl), Tools.encodeVLCMrl(title));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -274,13 +273,13 @@ public class Medialibrary {
|
||||
|
||||
@Nullable
|
||||
public MediaWrapper getMedia(Uri uri) {
|
||||
final String vlcMrl = Tools.encodeVLCMrl(Uri.decode(uri.toString()));
|
||||
final String vlcMrl = Tools.encodeVLCMrl(uri.toString());
|
||||
return mIsInitiated && !TextUtils.isEmpty(vlcMrl) ? nativeGetMediaFromMrl(vlcMrl) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MediaWrapper getMedia(String mrl) {
|
||||
final String vlcMrl = Tools.encodeVLCMrl(Uri.decode(mrl));
|
||||
final String vlcMrl = Tools.encodeVLCMrl(mrl);
|
||||
return mIsInitiated && !TextUtils.isEmpty(vlcMrl) ? nativeGetMediaFromMrl(vlcMrl) : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.os.Environment;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.videolan.libvlc.util.VLCUtil;
|
||||
import org.videolan.medialibrary.media.MediaLibraryItem;
|
||||
import org.videolan.medialibrary.media.MediaWrapper;
|
||||
|
||||
@@ -38,8 +37,7 @@ public class Tools {
|
||||
}
|
||||
public static String getProgressText(MediaWrapper media) {
|
||||
long lastTime = media.getTime();
|
||||
if (lastTime == 0L)
|
||||
return "";
|
||||
if (lastTime == 0L) return "";
|
||||
return String.format("%s / %s",
|
||||
millisToString(lastTime, true, false),
|
||||
millisToString(media.getLength(), true, false));
|
||||
@@ -71,10 +69,10 @@ public class Tools {
|
||||
|
||||
public static void setMediaDescription (MediaLibraryItem item) {
|
||||
if (item.getItemType() == MediaLibraryItem.TYPE_MEDIA) {
|
||||
MediaWrapper mw = (MediaWrapper) item;
|
||||
final MediaWrapper mw = (MediaWrapper) item;
|
||||
if (mw.getType() == MediaWrapper.TYPE_VIDEO) {
|
||||
String progress = getProgressText(mw);
|
||||
String resolution = getResolution(mw);
|
||||
final String progress = mw.getLength() == 0L ? null : mw.getTime() == 0L ? Tools.millisToString(mw.getLength()) : getProgressText(mw);
|
||||
final String resolution = getResolution(mw);
|
||||
boolean hasprogress = !TextUtils.isEmpty(progress), hasResolution = !TextUtils.isEmpty(resolution);
|
||||
if (hasprogress && hasResolution)
|
||||
item.setDescription(resolution+" - "+progress);
|
||||
@@ -126,8 +124,7 @@ public class Tools {
|
||||
}
|
||||
|
||||
static String encodeVLCMrl(String mrl) {
|
||||
if (mrl.startsWith("/"))
|
||||
mrl = "file://"+mrl;
|
||||
return VLCUtil.encodeVLCString(Uri.encode(mrl, ":/"));
|
||||
if (mrl.startsWith("/")) mrl = "file://"+mrl;
|
||||
return Uri.encode(Uri.decode(mrl), ".-_~/()&!$*+,;='@:");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,11 +66,6 @@
|
||||
<meta-data android:name="com.samsung.android.sdk.multiwindow.enable" android:value="true" />
|
||||
<!-- Enable VLC in LG split window mode -->
|
||||
<meta-data android:name="com.lge.support.SPLIT_WINDOW" android:value="true" />
|
||||
<!-- Android auto -->
|
||||
<meta-data android:name="com.google.android.gms.car.application"
|
||||
android:resource="@xml/automotive_app_desc"/>
|
||||
<meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
|
||||
android:resource="@drawable/icon" />
|
||||
<meta-data
|
||||
android:name="android.max_aspect"
|
||||
android:value="2.1" />
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<body id="top" style="background-color: #EBEBEE">
|
||||
<h1>VLC for Android</h1>
|
||||
<p>Copyleft © 1996-2017 VideoLAN, VLC authors</p>
|
||||
<p>Copyleft © 1996-2018 VideoLAN, VLC authors</p>
|
||||
<div>
|
||||
<h2>License</h2>
|
||||
<p>VLC for Android is licensed under the <a href="#gpl">GNU General Public License, version 3 or later</a> (herein referred to as GPL).</p>
|
||||
|
||||
@@ -136,6 +136,8 @@ android {
|
||||
// make per-variant version code
|
||||
applicationVariants.all { variant ->
|
||||
|
||||
def generatedCode = variant.productFlavors.get(0).versionCode * 10000000 + defaultConfig.versionCode + variant.productFlavors.get(1).versionCode
|
||||
variant.mergedFlavor.versionCode = generatedCode
|
||||
//Custom APK name
|
||||
variant.outputs.all { output ->
|
||||
def outputName = "VLC-Android-"
|
||||
@@ -145,7 +147,6 @@ android {
|
||||
outputFileName = outputName
|
||||
output.processManifest.doLast {
|
||||
// set the composite code
|
||||
def generatedCode = variant.productFlavors.get(0).versionCode * 10000000 + defaultConfig.versionCode + variant.productFlavors.get(1).versionCode
|
||||
String manifestPath = "$manifestOutputDirectory/AndroidManifest.xml"
|
||||
def manifestContent = file(manifestPath).getText()
|
||||
manifestContent = manifestContent.replace('android:versionCode="1"',
|
||||
|
||||
BIN
vlc-android/res/drawable-hdpi/ic_passthrough_normal.png
Normal file
|
After Width: | Height: | Size: 593 B |
BIN
vlc-android/res/drawable-hdpi/ic_passthrough_normal_o.png
Normal file
|
After Width: | Height: | Size: 600 B |
BIN
vlc-android/res/drawable-hdpi/ic_passthrough_normal_w.png
Normal file
|
After Width: | Height: | Size: 618 B |
BIN
vlc-android/res/drawable-hdpi/ic_passthrough_pressed.png
Normal file
|
After Width: | Height: | Size: 600 B |
|
Before Width: | Height: | Size: 417 B After Width: | Height: | Size: 402 B |
|
Before Width: | Height: | Size: 415 B After Width: | Height: | Size: 402 B |
|
Before Width: | Height: | Size: 416 B After Width: | Height: | Size: 402 B |
|
Before Width: | Height: | Size: 494 B After Width: | Height: | Size: 467 B |
|
Before Width: | Height: | Size: 500 B After Width: | Height: | Size: 464 B |
|
Before Width: | Height: | Size: 413 B After Width: | Height: | Size: 402 B |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 5.2 KiB |
BIN
vlc-android/res/drawable-ldpi/ic_passthrough_normal.png
Normal file
|
After Width: | Height: | Size: 409 B |
BIN
vlc-android/res/drawable-ldpi/ic_passthrough_normal_o.png
Normal file
|
After Width: | Height: | Size: 404 B |
BIN
vlc-android/res/drawable-ldpi/ic_passthrough_normal_w.png
Normal file
|
After Width: | Height: | Size: 412 B |
BIN
vlc-android/res/drawable-ldpi/ic_passthrough_pressed.png
Normal file
|
After Width: | Height: | Size: 400 B |
|
Before Width: | Height: | Size: 318 B After Width: | Height: | Size: 319 B |
|
Before Width: | Height: | Size: 313 B After Width: | Height: | Size: 319 B |
|
Before Width: | Height: | Size: 322 B After Width: | Height: | Size: 320 B |
|
Before Width: | Height: | Size: 345 B After Width: | Height: | Size: 352 B |
|
Before Width: | Height: | Size: 350 B After Width: | Height: | Size: 352 B |
|
Before Width: | Height: | Size: 323 B After Width: | Height: | Size: 315 B |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 2.3 KiB |
BIN
vlc-android/res/drawable-mdpi/ic_passthrough_normal.png
Normal file
|
After Width: | Height: | Size: 520 B |
BIN
vlc-android/res/drawable-mdpi/ic_passthrough_normal_o.png
Normal file
|
After Width: | Height: | Size: 495 B |
BIN
vlc-android/res/drawable-mdpi/ic_passthrough_normal_w.png
Normal file
|
After Width: | Height: | Size: 508 B |
BIN
vlc-android/res/drawable-mdpi/ic_passthrough_pressed.png
Normal file
|
After Width: | Height: | Size: 485 B |
|
Before Width: | Height: | Size: 325 B After Width: | Height: | Size: 376 B |
|
Before Width: | Height: | Size: 322 B After Width: | Height: | Size: 376 B |
|
Before Width: | Height: | Size: 324 B After Width: | Height: | Size: 376 B |
|
Before Width: | Height: | Size: 366 B After Width: | Height: | Size: 432 B |
|
Before Width: | Height: | Size: 366 B After Width: | Height: | Size: 434 B |
|
Before Width: | Height: | Size: 320 B After Width: | Height: | Size: 365 B |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 3.7 KiB |
BIN
vlc-android/res/drawable-xhdpi/ic_passthrough_normal.png
Normal file
|
After Width: | Height: | Size: 682 B |
BIN
vlc-android/res/drawable-xhdpi/ic_passthrough_normal_o.png
Normal file
|
After Width: | Height: | Size: 680 B |
BIN
vlc-android/res/drawable-xhdpi/ic_passthrough_normal_w.png
Normal file
|
After Width: | Height: | Size: 685 B |
BIN
vlc-android/res/drawable-xhdpi/ic_passthrough_pressed.png
Normal file
|
After Width: | Height: | Size: 659 B |
|
Before Width: | Height: | Size: 488 B After Width: | Height: | Size: 457 B |
|
Before Width: | Height: | Size: 485 B After Width: | Height: | Size: 457 B |
|
Before Width: | Height: | Size: 487 B After Width: | Height: | Size: 457 B |
|
Before Width: | Height: | Size: 570 B After Width: | Height: | Size: 542 B |
|
Before Width: | Height: | Size: 571 B After Width: | Height: | Size: 523 B |
|
Before Width: | Height: | Size: 488 B After Width: | Height: | Size: 457 B |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 6.8 KiB |
7
vlc-android/res/drawable/ic_passthrough.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_passthrough_normal" android:state_focused="true" android:state_pressed="true"/>
|
||||
<item android:drawable="@drawable/ic_passthrough_pressed" android:state_focused="true"/>
|
||||
<item android:drawable="@drawable/ic_passthrough_pressed" android:state_pressed="true"/>
|
||||
<item android:drawable="@drawable/ic_passthrough_normal"/>
|
||||
</selector>
|
||||
7
vlc-android/res/drawable/ic_passthrough_on.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_passthrough_normal_o" android:state_focused="true" android:state_pressed="true"/>
|
||||
<item android:drawable="@drawable/ic_passthrough_pressed" android:state_focused="true"/>
|
||||
<item android:drawable="@drawable/ic_passthrough_pressed" android:state_pressed="true"/>
|
||||
<item android:drawable="@drawable/ic_passthrough_normal_o"/>
|
||||
</selector>
|
||||
7
vlc-android/res/drawable/ic_passthrough_w.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_passthrough_normal_w" android:state_focused="true" android:state_pressed="true"/>
|
||||
<item android:drawable="@drawable/ic_passthrough_pressed" android:state_focused="true"/>
|
||||
<item android:drawable="@drawable/ic_passthrough_pressed" android:state_pressed="true"/>
|
||||
<item android:drawable="@drawable/ic_passthrough_normal_w"/>
|
||||
</selector>
|
||||
@@ -61,10 +61,8 @@
|
||||
android:layout_marginStart="@dimen/half_default_margin"
|
||||
android:layout_marginLeft="@dimen/half_default_margin"
|
||||
vlc:layout_constraintBottom_toTopOf="@+id/subtitle"
|
||||
android:singleLine="true"
|
||||
android:maxLines="1"
|
||||
android:maxLines="2"
|
||||
android:gravity="center_vertical"
|
||||
android:ellipsize="end"
|
||||
vlc:alignMode="@{alignMode}"
|
||||
android:text="@{item.title}"
|
||||
android:fontFamily="sans-serif-light"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="448dp">
|
||||
android:minWidth="384dp">
|
||||
<TextView
|
||||
android:id="@+id/renderers_title"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -23,10 +23,12 @@
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/renderers_list"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintHeight_default="wrap"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/renderers_title"
|
||||
app:layout_constraintBottom_toTopOf="@+id/renderers_disconnect"
|
||||
tools:listitem="@layout/item_renderer"/>
|
||||
<Button
|
||||
android:id="@+id/renderers_disconnect"
|
||||
@@ -34,9 +36,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/renderers_list"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:text="Disconnect"
|
||||
android:text="@string/renderers_disconnect"
|
||||
tools:targetApi="11"
|
||||
style="?android:attr/borderlessButtonStyle"
|
||||
android:textColor="@color/orange800"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:vlc="http://schemas.android.com/apk/res-auto">
|
||||
xmlns:vlc="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<data>
|
||||
<import type="org.videolan.medialibrary.Tools" />
|
||||
<variable
|
||||
@@ -20,7 +21,8 @@
|
||||
android:background="@drawable/rounded_corners"
|
||||
android:paddingTop="@dimen/overlay_padding_top"
|
||||
android:paddingBottom="@dimen/overlay_padding_bottom"
|
||||
android:visibility="invisible" >
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible" >
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/player_overlay_seekbar"
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/video_menu_video_track"
|
||||
android:title="@string/track_video" />
|
||||
<item
|
||||
android:id="@+id/video_menu_audio_track"
|
||||
android:title="@string/track_audio" />
|
||||
|
||||
@@ -261,7 +261,7 @@
|
||||
<string name="video_min_group_length_first">Première lettre seulement</string>
|
||||
<string name="video_min_group_length_short">Courte suite de lettre (6)</string>
|
||||
<string name="video_min_group_length_long">Longue suite de lettres (9)</string>
|
||||
<string name="media_fast_seek">Activer l\'option de recherche rapide</string>
|
||||
<string name="media_fast_seek">Activer l\'option de chargement rapide</string>
|
||||
<string name="media_seen">Afficher le marqueur de vidéo vue</string>
|
||||
<string name="media_seen_summary">Marquer une vidéo comme vue lorsque vous la regardez jusqu\'à la fin</string>
|
||||
<string name="force_list_portrait">Pas de grille en mode portrait</string>
|
||||
@@ -337,8 +337,8 @@
|
||||
<string name="casting_quality_lowcpu">Le plus bas</string>
|
||||
<string name="cast_performance_warning">Diffuser cette vidéo requiert une conversion. Cette conversion risque d\'utiliser toute la puissance disponible et rapidement vider votre batterie.</string>
|
||||
<string name="casting_connected_renderer">Connecté au moteur de rendu \'%1$s\'</string>
|
||||
<string name="artists_show_all_title">Montrer tout les artistes</string>
|
||||
<string name="artists_show_all_summary">Montrer tout les artistes dans la liste des artistes, pas seulement les artistes de l\'album</string>
|
||||
<string name="artists_show_all_title">Montrer tous les artistes</string>
|
||||
<string name="artists_show_all_summary">Montrer tous les artistes dans la liste des artistes, pas seulement les artistes de l\'album</string>
|
||||
<string name="extensions_prefs_category">Extensions</string>
|
||||
<string name="extensions_enable_category">Choisissez les extensions à activer</string>
|
||||
<string name="extensions_empty">Aucune extension détectée</string>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<item quantity="other">%d sub pastas</item>
|
||||
</plurals>
|
||||
<plurals name="mediafiles_quantity">
|
||||
<item quantity="one">$d arquivo de mídia</item>
|
||||
<item quantity="one">%d arquivo de mídia</item>
|
||||
<item quantity="other">%d arquivos de mídia</item>
|
||||
</plurals>
|
||||
<plurals name="videos_quantity">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="default_content_width">800dp</dimen>
|
||||
<dimen name="file_picker_width">720dp</dimen>
|
||||
</resources>
|
||||
@@ -65,6 +65,7 @@
|
||||
<attr name="ic_playasaudio_on" format="reference" />
|
||||
<attr name="ic_popup_expand" format="reference" />
|
||||
<attr name="ic_popup_dim" format="reference" />
|
||||
<attr name="ic_passthrough" format="reference" />
|
||||
|
||||
<attr name="shadow_top_9patch" format="reference"/>
|
||||
<attr name="shadow_bottom_9patch" format="reference"/>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
<dimen name="listview_side_padding">5dp</dimen>
|
||||
<dimen name="grid_card_thumb_width">160dp</dimen>
|
||||
<dimen name="grid_card_thumb_height">100dp</dimen>
|
||||
<dimen name="tv_grid_card_thumb_width">256dp</dimen>
|
||||
<dimen name="tv_grid_card_thumb_height">160dp</dimen>
|
||||
<dimen name="tv_grid_card_thumb_width">192dp</dimen>
|
||||
<dimen name="tv_grid_card_thumb_height">120dp</dimen>
|
||||
<dimen name="grid_card_title_text_size">12sp</dimen>
|
||||
<dimen name="grid_card_subtitle_text_size">10sp</dimen>
|
||||
<dimen name="grid_card_vertical_spacing">0dp</dimen>
|
||||
|
||||
@@ -246,7 +246,7 @@
|
||||
<string name="about_text">VLC for Android™ is a port of VLC media player, the popular open source media player. The Android™ version can read most files and network streams.</string>
|
||||
<string name="compiled_by">This version of VLC is compiled by:</string>
|
||||
<string name="vlc_authors">and VLC Authors.</string>
|
||||
<string name="about_link" translatable="false"> <a href="http://www.videolan.org/vlc/">http://www.videolan.org/vlc/</a></string>
|
||||
<string name="about_link" translatable="false"> <a href="https://www.videolan.org/vlc/">https://www.videolan.org/vlc/</a></string>
|
||||
<string name="about_copyright" translatable="false">Copyleft © 1996–2018 by VideoLAN.\n</string>
|
||||
<string name="authors" translatable="false">Edward Wang, Sébastien Toque, Adrien Maglo, Jean-Baptiste Kempf, Ludovic Fauvet, Rafaël Carré, Alexandre Perraud, Michael Merg, Martin Storsjö, Rémi Duraffort, Dominique Martinet, Jean-Philippe André, Felix Abecassis, Christoph Miebach, Hugo Beauzée-Luyssen, Felix Paul Kühne, John Mooring, Pavol Rusnak, Rohit Yadav, Tanguy Pruvot, Thomas Clavier, Asad Mehmood, Garret Kelly, Philipp Dreimann, Walter Heck, Thomas Guillem, Geoffrey Métais.</string>
|
||||
|
||||
@@ -359,6 +359,8 @@
|
||||
<string name="headset_prefs_category">Headset</string>
|
||||
<string name="enable_headset_detection">Detect headset</string>
|
||||
<string name="enable_headset_detection_summary">Detect headset insertion and removal</string>
|
||||
<string name="enable_headset_actions_title">Remote Control shortcuts</string>
|
||||
<string name="enable_headset_actions_summary">Double press on \'Play\' to skip to next and long press on it to skip to previous track</string>
|
||||
<string name="enable_play_on_headset_insertion">Resume on headset insertion</string>
|
||||
<string name="enable_play_on_headset_insertion_summary">Pause otherwise</string>
|
||||
<string name="enable_steal_remote_control">Exclusive headset remote control</string>
|
||||
@@ -413,6 +415,8 @@
|
||||
<string name="save_video_always">Save speed across sessions</string>
|
||||
<string name="auto_rescan">Auto rescan</string>
|
||||
<string name="auto_rescan_summary">Automatically scan device for new or deleted media at application startup</string>
|
||||
<string name="dump_media_db">Dump media database</string>
|
||||
<string name="dump_media_db_summary">Copy database to internal storage root</string>
|
||||
<string name="clear_media_db">Clear media database</string>
|
||||
<string name="clear_media_db_summary">Access Android VLC info to clear data</string>
|
||||
<string name="clear_history">Clear search history</string>
|
||||
@@ -592,4 +596,9 @@
|
||||
<string name="sdcard_permission_dialog_title">You have to grant VLC write access to your SD Card</string>
|
||||
<string name="sdcard_permission_dialog_message">VLC cannot delete this file without write access permission.\nPlease go to your SD Card and click on \"Select\".\nYou may have to click on \"Show SD card\" first in the top-right menu</string>
|
||||
<string name="dialog_sd_wizard">Show me</string>
|
||||
<string name="renderers_disconnect">Disconnect</string>
|
||||
<string name="audio_digital_failed">Failed to change Audio Digital Output state</string>
|
||||
<string name="audio_digital_output_enabled">Audio Digital Output enabled</string>
|
||||
<string name="audio_digital_output_disabled">Audio Digital Output disabled</string>
|
||||
<string name="audio_digital_title">Digital audio output (passthrough)</string>
|
||||
</resources>
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
<item name="ic_equalizer_normal_style">@drawable/ic_equalizer</item>
|
||||
<item name="ic_audiodelay">@drawable/ic_audiodelay</item>
|
||||
<item name="ic_subtitledelay">@drawable/ic_subtitledelay</item>
|
||||
<item name="ic_passthrough">@drawable/ic_passthrough</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.VLC.PickerDialog" parent="Theme.AppCompat.Light.Dialog">
|
||||
@@ -179,6 +180,7 @@
|
||||
<item name="ic_equalizer_normal_style">@drawable/ic_equalizer_w</item>
|
||||
<item name="ic_audiodelay">@drawable/ic_audiodelay_w</item>
|
||||
<item name="ic_subtitledelay">@drawable/ic_subtitledelay_w</item>
|
||||
<item name="ic_passthrough">@drawable/ic_passthrough_w</item>
|
||||
</style>
|
||||
<style name="Theme.VLC.TV" parent="Theme.Leanback">
|
||||
<item name="colorPrimary">@color/orange800</item>
|
||||
@@ -254,6 +256,7 @@
|
||||
<item name="ic_equalizer_normal_style">@drawable/ic_equalizer_w</item>
|
||||
<item name="ic_audiodelay">@drawable/ic_audiodelay_w</item>
|
||||
<item name="ic_subtitledelay">@drawable/ic_subtitledelay_w</item>
|
||||
<item name="ic_passthrough">@drawable/ic_passthrough_w</item>
|
||||
<item name="ic_repeat">@drawable/ic_repeat_w</item>
|
||||
<item name="ic_shuffle">@drawable/ic_shuffle_w</item>
|
||||
<item name="ic_trash">@drawable/ic_trash_w</item>
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
android:summary="@string/network_caching_summary"
|
||||
android:title="@string/network_caching" />
|
||||
|
||||
<Preference
|
||||
android:enabled="true"
|
||||
android:key="dump_media_db"
|
||||
android:summary="@string/dump_media_db_summary"
|
||||
android:title="@string/dump_media_db" />
|
||||
|
||||
<Preference
|
||||
android:enabled="true"
|
||||
android:key="clear_media_db"
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
android:key="audio_category"
|
||||
android:title="@string/audio_prefs_category">
|
||||
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="audio_digital_output"
|
||||
android:title="@string/audio_digital_title" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="artists_show_all"
|
||||
@@ -31,6 +34,11 @@
|
||||
<PreferenceCategory
|
||||
android:title="@string/headset_prefs_category"
|
||||
android:key="headset_prefs_category">
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="enable_headset_actions"
|
||||
android:summary="@string/enable_headset_actions_summary"
|
||||
android:title="@string/enable_headset_actions_title" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="enable_headset_detection"
|
||||
|
||||
@@ -76,13 +76,17 @@ public class ExternalMonitor extends BroadcastReceiver {
|
||||
storageFilter.addDataScheme("file");
|
||||
ctx.registerReceiver(instance, networkFilter);
|
||||
ctx.registerReceiver(instance, storageFilter);
|
||||
if (AndroidUtil.isICSOrLater)
|
||||
checkNewStorages(ctx);
|
||||
checkNewStorages(ctx);
|
||||
}
|
||||
|
||||
private static void checkNewStorages(final Context ctx) {
|
||||
if (VLCApplication.getMLInstance().isInitiated())
|
||||
ctx.startService(new Intent(Constants.ACTION_CHECK_STORAGES, null,ctx, MediaParsingService.class));
|
||||
if (AndroidUtil.isICSOrLater && VLCApplication.getMLInstance().isInitiated())
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ctx.startService(new Intent(Constants.ACTION_CHECK_STORAGES, null,ctx, MediaParsingService.class));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void unregister(Context ctx) {
|
||||
|
||||
@@ -217,7 +217,7 @@ public class MediaParsingService extends Service implements DevicesDiscoveryCb {
|
||||
shouldInit |= initCode == Medialibrary.ML_INIT_DB_RESET;
|
||||
if (initCode != Medialibrary.ML_INIT_FAILED) {
|
||||
final List<String> devices = new ArrayList<>();
|
||||
Collections.addAll(devices, AndroidDevices.getMediaDirectories());
|
||||
Collections.addAll(devices, AndroidDevices.getMediaDirectories(context));
|
||||
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
for (final String device : devices) {
|
||||
final boolean isMainStorage = TextUtils.equals(device, AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
package org.videolan.vlc;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
@@ -35,6 +36,7 @@ import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioManager.OnAudioFocusChangeListener;
|
||||
import android.net.Uri;
|
||||
@@ -89,6 +91,7 @@ import org.videolan.vlc.util.Constants;
|
||||
import org.videolan.vlc.util.Permissions;
|
||||
import org.videolan.vlc.util.Util;
|
||||
import org.videolan.vlc.util.VLCInstance;
|
||||
import org.videolan.vlc.util.VLCOptions;
|
||||
import org.videolan.vlc.util.VoiceSearchParams;
|
||||
import org.videolan.vlc.util.WeakHandler;
|
||||
import org.videolan.vlc.widget.VLCAppWidgetProvider;
|
||||
@@ -112,8 +115,8 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
private static final int SHOW_TOAST = 1;
|
||||
private static final int END_MEDIASESSION = 2;
|
||||
|
||||
private static final int DELAY_DOUBLE_CLICK = 800;
|
||||
private static final int DELAY_LONG_CLICK = 1000;
|
||||
private static final long DELAY_DOUBLE_CLICK = 800L;
|
||||
private static final long DELAY_LONG_CLICK = 1000L;
|
||||
|
||||
public interface Callback {
|
||||
void update();
|
||||
@@ -187,7 +190,7 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
|
||||
// Make sure the audio player will acquire a wake-lock while playing. If we don't do
|
||||
// that, the CPU might go to sleep while the song is playing, causing playback to stop.
|
||||
final PowerManager pm = (PowerManager) VLCApplication.getAppContext().getSystemService(Context.POWER_SERVICE);
|
||||
final PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
||||
|
||||
updateHasWidget();
|
||||
@@ -273,11 +276,12 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mHandler.removeCallbacksAndMessages(null);
|
||||
stop(true);
|
||||
if (mMediaSession != null) {
|
||||
mMediaSession.release();
|
||||
mMediaSession = null;
|
||||
}
|
||||
//Call it once mMediaSession is null, to not publish playback state
|
||||
stop(true);
|
||||
|
||||
if (!AndroidDevices.hasTsp && !AndroidDevices.hasPlayServices)
|
||||
AndroidDevices.setRemoteControlReceiverEnabled(false);
|
||||
@@ -287,7 +291,6 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
mRemoteControlClientReceiver = null;
|
||||
}
|
||||
playlistManager.onServiceDestroyed();
|
||||
updateWidget();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -301,10 +304,10 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
|
||||
private final OnAudioFocusChangeListener mAudioFocusListener = createOnAudioFocusChangeListener();
|
||||
|
||||
private volatile boolean mLossTransient = false;
|
||||
private OnAudioFocusChangeListener createOnAudioFocusChangeListener() {
|
||||
return new OnAudioFocusChangeListener() {
|
||||
int audioDuckLevel = -1;
|
||||
private boolean mLossTransient = false;
|
||||
private int mLossTransientVolume = -1;
|
||||
private boolean wasPlaying = false;
|
||||
|
||||
@@ -370,12 +373,37 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
if (mLossTransient) return;
|
||||
mLossTransient = true;
|
||||
wasPlaying = isPlaying();
|
||||
if (wasPlaying)
|
||||
pause();
|
||||
if (wasPlaying) pause();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void sendStartSessionIdIntent() {
|
||||
int sessionId = VLCOptions.getAudiotrackSessionId();
|
||||
if (sessionId == 0)
|
||||
return;
|
||||
|
||||
Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, sessionId);
|
||||
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
|
||||
if (isVideoPlaying())
|
||||
intent.putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MOVIE);
|
||||
else
|
||||
intent.putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MUSIC);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
|
||||
private void sendStopSessionIdIntent() {
|
||||
int sessionId = VLCOptions.getAudiotrackSessionId();
|
||||
if (sessionId == 0)
|
||||
return;
|
||||
|
||||
Intent intent = new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, sessionId);
|
||||
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
|
||||
private AudioManager mAudioManager = null;
|
||||
private void changeAudioFocus(boolean acquire) {
|
||||
if (mAudioManager == null)
|
||||
@@ -383,7 +411,7 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
if (mAudioManager == null)
|
||||
return;
|
||||
|
||||
if (acquire) {
|
||||
if (acquire && !hasRenderer()) {
|
||||
if (!mHasAudioFocus) {
|
||||
final int result = mAudioManager.requestAudioFocus(mAudioFocusListener,
|
||||
AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
|
||||
@@ -392,12 +420,10 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
mHasAudioFocus = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mHasAudioFocus) {
|
||||
mAudioManager.abandonAudioFocus(mAudioFocusListener);
|
||||
mAudioManager.setParameters("bgm_state=false");
|
||||
mHasAudioFocus = false;
|
||||
}
|
||||
} else if (mHasAudioFocus) {
|
||||
mAudioManager.abandonAudioFocus(mAudioFocusListener);
|
||||
mAudioManager.setParameters("bgm_state=false");
|
||||
mHasAudioFocus = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,7 +435,7 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
final int state = intent.getIntExtra("state", 0);
|
||||
|
||||
// skip all headsets events if there is a call
|
||||
final TelephonyManager telManager = (TelephonyManager) VLCApplication.getAppContext().getSystemService(Context.TELEPHONY_SERVICE);
|
||||
final TelephonyManager telManager = (TelephonyManager) PlaybackService.this.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
|
||||
if (telManager != null && telManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) return;
|
||||
|
||||
/*
|
||||
@@ -425,9 +451,8 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
* Remote / headset control events
|
||||
*/
|
||||
if (action.equalsIgnoreCase(Constants.ACTION_REMOTE_PLAYPAUSE)) {
|
||||
if (!playlistManager.hasCurrentMedia())
|
||||
loadLastAudioPlaylist();
|
||||
if (isPlaying()) pause();
|
||||
if (!playlistManager.hasCurrentMedia()) loadLastAudioPlaylist();
|
||||
else if (isPlaying()) pause();
|
||||
else play();
|
||||
} else if (action.equalsIgnoreCase(Constants.ACTION_REMOTE_PLAY)) {
|
||||
if (!isPlaying() && playlistManager.hasCurrentMedia())
|
||||
@@ -662,7 +687,7 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
mw.hasFlag(MediaWrapper.MEDIA_FORCE_AUDIO), title, artist, album,
|
||||
cover, playing, sessionToken, getSessionPendingIntent());
|
||||
if (isPlayingPopup()) return;
|
||||
if (!AndroidUtil.isLolliPopOrLater || playing) {
|
||||
if (!AndroidUtil.isLolliPopOrLater || playing || mLossTransient) {
|
||||
if (!mIsForeground) {
|
||||
PlaybackService.this.startForeground(3, notification);
|
||||
mIsForeground = true;
|
||||
@@ -778,11 +803,12 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
}
|
||||
|
||||
private final class MediaSessionCallback extends MediaSessionCompat.Callback {
|
||||
private long mHeadsetDownTime = 0;
|
||||
private long mHeadsetUpTime = 0;
|
||||
private long mHeadsetDownTime = 0L;
|
||||
private long mHeadsetUpTime = 0L;
|
||||
|
||||
@Override
|
||||
public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
|
||||
if (!mSettings.getBoolean("enable_headset_actions", true) || VLCApplication.showTvUi()) return false;
|
||||
final KeyEvent event = mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
|
||||
if (event != null && !isVideoPlaying()) {
|
||||
final int keyCode = event.getKeyCode();
|
||||
@@ -791,8 +817,7 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
final long time = SystemClock.uptimeMillis();
|
||||
switch (event.getAction()) {
|
||||
case KeyEvent.ACTION_DOWN:
|
||||
if (event.getRepeatCount() <= 0)
|
||||
mHeadsetDownTime = time;
|
||||
if (event.getRepeatCount() <= 0) mHeadsetDownTime = time;
|
||||
if (!hasMedia()) {
|
||||
loadLastAudioPlaylist();
|
||||
return true;
|
||||
@@ -832,10 +857,8 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
|
||||
@Override
|
||||
public void onPlay() {
|
||||
if (hasMedia())
|
||||
play();
|
||||
else
|
||||
loadLastAudioPlaylist();
|
||||
if (hasMedia()) play();
|
||||
else loadLastAudioPlaylist();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1057,9 +1080,17 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
if (playlistManager.hasPlaylist())
|
||||
pscb.addCustomAction("shuffle", getString(R.string.shuffle_title), isShuffling() ? R.drawable.ic_auto_shuffle_pressed : R.drawable.ic_auto_shuffle_normal);
|
||||
pscb.addCustomAction("repeat", getString(R.string.repeat_title), repeatResId);
|
||||
|
||||
boolean mediaIsActive = state != PlaybackStateCompat.STATE_STOPPED;
|
||||
|
||||
mMediaSession.setPlaybackState(pscb.build());
|
||||
mMediaSession.setActive(state != PlaybackStateCompat.STATE_STOPPED);
|
||||
mMediaSession.setActive(mediaIsActive);
|
||||
mMediaSession.setQueueTitle(getString(R.string.music_now_playing));
|
||||
|
||||
if (mediaIsActive)
|
||||
sendStartSessionIdIntent();
|
||||
else
|
||||
sendStopSessionIdIntent();
|
||||
}
|
||||
|
||||
private void notifyTrackChanged() {
|
||||
@@ -1694,6 +1725,16 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
return playlistManager.getPlayer().setAudioTrack(index);
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public boolean setAudioDigitalOutputEnabled(boolean enabled) {
|
||||
return playlistManager.getPlayer().setAudioDigitalOutputEnabled(enabled);
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public boolean setVideoTrack(int index) {
|
||||
return playlistManager.getPlayer().setVideoTrack(index);
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public int getVideoTracksCount() {
|
||||
return hasMedia() ? playlistManager.getPlayer().getVideoTracksCount() : 0;
|
||||
@@ -1770,6 +1811,8 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
if (wasOnRenderer && !hasRenderer() && canSwitchToVideo()) VideoPlayerActivity.startOpened(VLCApplication.getAppContext(),
|
||||
playlistManager.getCurrentMedia().getUri(), playlistManager.getCurrentIndex());
|
||||
playlistManager.getPlayer().setRenderer(item);
|
||||
if (!wasOnRenderer && item != null) changeAudioFocus(false);
|
||||
else if (wasOnRenderer && item == null && isPlaying()) changeAudioFocus(true);
|
||||
}
|
||||
|
||||
@MainThread
|
||||
@@ -1845,7 +1888,8 @@ public class PlaybackService extends MediaBrowserServiceCompat{
|
||||
public void connect() {
|
||||
if (mBound) throw new IllegalStateException("already connected");
|
||||
final Intent serviceIntent = getServiceIntent(mContext);
|
||||
Util.startService(mContext, serviceIntent);
|
||||
if (mContext instanceof Activity) mContext.startService(serviceIntent);
|
||||
else Util.startService(mContext, serviceIntent);
|
||||
mBound = mContext.bindService(serviceIntent, mServiceConnection, BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,14 +44,20 @@ public class RemoteControlClientReceiver extends MediaButtonReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (action == null) return;
|
||||
|
||||
final KeyEvent event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
|
||||
if (event != null && action.equalsIgnoreCase(Intent.ACTION_MEDIA_BUTTON)) {
|
||||
|
||||
if (event.getKeyCode() != KeyEvent.KEYCODE_HEADSETHOOK &&
|
||||
event.getKeyCode() != KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE &&
|
||||
event.getAction() != KeyEvent.ACTION_DOWN) {
|
||||
super.onReceive(context, intent);
|
||||
event.getKeyCode() != KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
|
||||
if (!AndroidUtil.isOOrLater || VLCApplication.isForeground()) super.onReceive(context, intent);
|
||||
else if (event.getAction() == KeyEvent.ACTION_DOWN &&
|
||||
event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY) {
|
||||
intent = new Intent(context, PlaybackService.class);
|
||||
intent.setAction(Constants.ACTION_REMOTE_PLAYPAUSE);
|
||||
Util.startService(context, intent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -103,8 +109,7 @@ public class RemoteControlClientReceiver extends MediaButtonReceiver {
|
||||
break;
|
||||
}
|
||||
|
||||
if (isOrderedBroadcast())
|
||||
abortBroadcast();
|
||||
if (isOrderedBroadcast()) abortBroadcast();
|
||||
if (i != null) {
|
||||
Util.startService(context, i);
|
||||
return;
|
||||
|
||||
@@ -4,9 +4,9 @@ import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.videolan.medialibrary.Medialibrary;
|
||||
import org.videolan.medialibrary.media.MediaLibraryItem;
|
||||
import org.videolan.vlc.gui.DiffUtilAdapter;
|
||||
import org.videolan.vlc.util.MediaItemDiffCallback;
|
||||
import org.videolan.vlc.util.MediaLibraryItemComparator;
|
||||
import org.videolan.vlc.util.Util;
|
||||
|
||||
@@ -38,8 +38,8 @@ public abstract class SortableAdapter<T extends MediaLibraryItem, VH extends Rec
|
||||
}
|
||||
|
||||
public void updateIfSortChanged() {
|
||||
if (!hasPendingUpdates() && hasSortChanged())
|
||||
update(new ArrayList<>(getDataset()));
|
||||
final Medialibrary ml = VLCApplication.getMLInstance();
|
||||
if (ml.isInitiated() && !ml.isWorking() && !hasPendingUpdates() && hasSortChanged()) update(new ArrayList<>(peekLast()));
|
||||
}
|
||||
|
||||
private boolean hasSortChanged() {
|
||||
|
||||
@@ -71,7 +71,7 @@ public class VLCApplication extends Application {
|
||||
private static SimpleArrayMap<String, WeakReference<Object>> sDataMap = new SimpleArrayMap<>();
|
||||
|
||||
/* Up to 2 threads maximum, inactive threads are killed after 2 seconds */
|
||||
private final int maxThreads = Math.max(AndroidUtil.isJellyBeanMR1OrLater ? Runtime.getRuntime().availableProcessors() : 2, 1);
|
||||
private static final int maxThreads = Math.max(AndroidUtil.isJellyBeanMR1OrLater ? Runtime.getRuntime().availableProcessors() : 2, 1);
|
||||
public static final ThreadFactory THREAD_FACTORY = new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable runnable) {
|
||||
@@ -80,9 +80,9 @@ public class VLCApplication extends Application {
|
||||
return thread;
|
||||
}
|
||||
};
|
||||
private final ThreadPoolExecutor mThreadPool = new ThreadPoolExecutor(Math.min(2, maxThreads), maxThreads, 30, TimeUnit.SECONDS,
|
||||
private static final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(Math.min(2, maxThreads), maxThreads, 30, TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(), THREAD_FACTORY);
|
||||
private Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private static final Handler handler = new Handler(Looper.getMainLooper());
|
||||
|
||||
private static int sDialogCounter = 0;
|
||||
|
||||
@@ -98,7 +98,7 @@ public class VLCApplication extends Application {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (AndroidUtil.isOOrLater) NotificationHelper.createNotificationChannels();
|
||||
if (AndroidUtil.isOOrLater) NotificationHelper.createNotificationChannels(VLCApplication.this);
|
||||
// Prepare cache folder constants
|
||||
AudioUtil.prepareCacheFolder(instance);
|
||||
|
||||
@@ -167,16 +167,16 @@ public class VLCApplication extends Application {
|
||||
|
||||
public static void runBackground(Runnable runnable) {
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) runnable.run();
|
||||
else instance.mThreadPool.execute(runnable);
|
||||
else threadPool.execute(runnable);
|
||||
}
|
||||
|
||||
public static void runOnMainThread(Runnable runnable) {
|
||||
if (Looper.myLooper() == Looper.getMainLooper()) runnable.run();
|
||||
else instance.mHandler.post(runnable);
|
||||
else handler.post(runnable);
|
||||
}
|
||||
|
||||
public static boolean removeTask(Runnable runnable) {
|
||||
return instance.mThreadPool.remove(runnable);
|
||||
return threadPool.remove(runnable);
|
||||
}
|
||||
|
||||
public static void storeData(String key, Object data) {
|
||||
|
||||
@@ -113,7 +113,6 @@ public class AudioPlayerContainerActivity extends BaseActivity implements Playba
|
||||
private void initAudioPlayer() {
|
||||
((ViewStubCompat)findViewById(R.id.audio_player_stub)).inflate();
|
||||
mAudioPlayer = (AudioPlayer) getSupportFragmentManager().findFragmentById(R.id.audio_player);
|
||||
mAudioPlayer.setUserVisibleHint(false);
|
||||
mBottomSheetBehavior = BottomSheetBehavior.from(mAudioPlayerContainer);
|
||||
mBottomSheetBehavior.setPeekHeight(getResources().getDimensionPixelSize(R.dimen.player_peek_height));
|
||||
mBottomSheetBehavior.setBottomSheetCallback(mAudioPlayerBottomSheetCallback);
|
||||
@@ -313,13 +312,12 @@ public class AudioPlayerContainerActivity extends BaseActivity implements Playba
|
||||
|
||||
private void updateProgressVisibility(int visibility) {
|
||||
boolean show = visibility == View.VISIBLE;
|
||||
if ((mScanProgressLayout == null && !show) ||
|
||||
(mScanProgressLayout != null && mScanProgressLayout.getVisibility() == visibility))
|
||||
return;
|
||||
if (show)
|
||||
mActivityHandler.sendEmptyMessageDelayed(ACTION_DISPLAY_PROGRESSBAR, 1000);
|
||||
else if (mScanProgressLayout != null)
|
||||
mScanProgressLayout.setVisibility(visibility);
|
||||
if (mScanProgressLayout != null && mScanProgressLayout.getVisibility() == visibility) return;
|
||||
if (show) mActivityHandler.sendEmptyMessageDelayed(ACTION_DISPLAY_PROGRESSBAR, 1000);
|
||||
else {
|
||||
mActivityHandler.removeMessages(ACTION_DISPLAY_PROGRESSBAR);
|
||||
UiTools.setViewVisibility(mScanProgressLayout, visibility);
|
||||
}
|
||||
}
|
||||
|
||||
private void showProgressBar() {
|
||||
@@ -333,8 +331,7 @@ public class AudioPlayerContainerActivity extends BaseActivity implements Playba
|
||||
updateContainerPadding(true);
|
||||
applyMarginToProgressBar(mBottomSheetBehavior.getPeekHeight());
|
||||
}
|
||||
} else if (mScanProgressLayout != null)
|
||||
mScanProgressLayout.setVisibility(View.VISIBLE);
|
||||
} else if (mScanProgressLayout != null) mScanProgressLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void updateContainerPadding(boolean show) {
|
||||
|
||||
@@ -24,74 +24,40 @@
|
||||
package org.videolan.vlc.gui;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.content.ClipData;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.widget.SearchView;
|
||||
import android.support.v7.widget.SnapHelper;
|
||||
import android.view.DragAndDropPermissions;
|
||||
import android.view.DragEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import org.videolan.libvlc.RendererItem;
|
||||
import org.videolan.libvlc.util.AndroidUtil;
|
||||
import org.videolan.medialibrary.media.MediaWrapper;
|
||||
import org.videolan.vlc.R;
|
||||
import org.videolan.vlc.RendererDelegate;
|
||||
import org.videolan.vlc.gui.audio.AudioBrowserFragment;
|
||||
import org.videolan.vlc.gui.audio.EqualizerFragment;
|
||||
import org.videolan.vlc.gui.browser.ExtensionBrowser;
|
||||
import org.videolan.vlc.gui.browser.SortableFragment;
|
||||
import org.videolan.vlc.gui.dialogs.RenderersDialog;
|
||||
import org.videolan.vlc.gui.helpers.UiTools;
|
||||
import org.videolan.vlc.gui.video.VideoGridFragment;
|
||||
import org.videolan.vlc.interfaces.Filterable;
|
||||
import org.videolan.vlc.media.MediaUtils;
|
||||
import org.videolan.vlc.util.AndroidDevices;
|
||||
|
||||
public class ContentActivity extends AudioPlayerContainerActivity implements SearchView.OnQueryTextListener, MenuItemCompat.OnActionExpandListener, RendererDelegate.RendererListener, RendererDelegate.RendererPlayer {
|
||||
public static final String TAG = "VLC/ContentActivity";
|
||||
|
||||
protected Menu mMenu;
|
||||
private SearchView mSearchView;
|
||||
private boolean showRenderers = !RendererDelegate.INSTANCE.getRenderers().isEmpty();
|
||||
private boolean showRenderers = !AndroidDevices.isChromeBook && !RendererDelegate.INSTANCE.getRenderers().isEmpty();
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
final View view = AndroidUtil.isNougatOrLater ? getWindow().peekDecorView() : null;
|
||||
if (view != null) view.setOnDragListener(new View.OnDragListener() {
|
||||
@Override
|
||||
public boolean onDrag(View v, DragEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case DragEvent.ACTION_DRAG_STARTED:
|
||||
return true;
|
||||
case DragEvent.ACTION_DROP:
|
||||
final ClipData clipData = event.getClipData();
|
||||
if (clipData == null) return false;
|
||||
final int itemsCount = clipData.getItemCount();
|
||||
for (int i = 0; i < itemsCount; i++) {
|
||||
final DragAndDropPermissions permissions = requestDragAndDropPermissions(event);
|
||||
if (permissions != null) {
|
||||
final ClipData.Item item = clipData.getItemAt(i);
|
||||
if (item.getUri() != null) MediaUtils.openUri(ContentActivity.this, item.getUri());
|
||||
else if (item.getText() != null) {
|
||||
final Uri uri = Uri.parse(item.getText().toString());
|
||||
final MediaWrapper media = new MediaWrapper(uri);
|
||||
if (!"file".equals(uri.getScheme())) media.setType(MediaWrapper.TYPE_STREAM);
|
||||
MediaUtils.openMedia(ContentActivity.this, media);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
UiTools.setOnDragListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -121,15 +87,19 @@ public class ContentActivity extends AudioPlayerContainerActivity implements Sea
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
RendererDelegate.INSTANCE.addListener(this);
|
||||
RendererDelegate.INSTANCE.addPlayerListener(this);
|
||||
if (!AndroidDevices.isChromeBook) {
|
||||
RendererDelegate.INSTANCE.addListener(this);
|
||||
RendererDelegate.INSTANCE.addPlayerListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
RendererDelegate.INSTANCE.removeListener(this);
|
||||
RendererDelegate.INSTANCE.removePlayerListener(this);
|
||||
if (!AndroidDevices.isChromeBook) {
|
||||
RendererDelegate.INSTANCE.removeListener(this);
|
||||
RendererDelegate.INSTANCE.removePlayerListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -197,9 +167,23 @@ public class ContentActivity extends AudioPlayerContainerActivity implements Sea
|
||||
}
|
||||
|
||||
private void setSearchVisibility(boolean visible) {
|
||||
Fragment current = getCurrentFragment();
|
||||
if (current instanceof Filterable)
|
||||
final Fragment current = getCurrentFragment();
|
||||
if (current instanceof Filterable) {
|
||||
((Filterable) current).setSearchVisibility(visible);
|
||||
makeRoomForSearch(current, visible);
|
||||
}
|
||||
}
|
||||
|
||||
// Hide options menu items to make room for filter EditText
|
||||
protected void makeRoomForSearch(Fragment current, boolean hide) {
|
||||
final Menu menu = mToolbar.getMenu();
|
||||
menu.findItem(R.id.ml_menu_renderers).setVisible(!hide && showRenderers);
|
||||
if (current instanceof SortableFragment) {
|
||||
menu.findItem(R.id.ml_menu_sortby).setVisible(!hide && ((SortableFragment)current).isSortEnabled());
|
||||
}
|
||||
if (current instanceof VideoGridFragment || current instanceof AudioBrowserFragment) {
|
||||
menu.findItem(R.id.ml_menu_last_playlist).setVisible(!hide);
|
||||
}
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
@@ -208,8 +192,7 @@ public class ContentActivity extends AudioPlayerContainerActivity implements Sea
|
||||
}
|
||||
|
||||
public void closeSearchView() {
|
||||
if (mMenu != null)
|
||||
MenuItemCompat.collapseActionView(mMenu.findItem(R.id.ml_menu_filter));
|
||||
if (mMenu != null) MenuItemCompat.collapseActionView(mMenu.findItem(R.id.ml_menu_filter));
|
||||
}
|
||||
|
||||
public void restoreCurrentList() {
|
||||
@@ -221,7 +204,12 @@ public class ContentActivity extends AudioPlayerContainerActivity implements Sea
|
||||
|
||||
@Override
|
||||
public void onRenderersChanged(boolean empty) {
|
||||
if (showRenderers != empty) return;
|
||||
showRenderers = !empty;
|
||||
if (empty && !AndroidDevices.isChromeBook) {
|
||||
RendererDelegate.INSTANCE.selectRenderer(null);
|
||||
if (mService != null) mService.setRenderer(null);
|
||||
}
|
||||
supportInvalidateOptionsMenu();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import kotlinx.coroutines.experimental.channels.Channel
|
||||
import kotlinx.coroutines.experimental.channels.actor
|
||||
import kotlinx.coroutines.experimental.launch
|
||||
import kotlinx.coroutines.experimental.newSingleThreadContext
|
||||
import kotlinx.coroutines.experimental.withContext
|
||||
import java.util.*
|
||||
|
||||
abstract class DiffUtilAdapter<D, VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH>() {
|
||||
@@ -32,11 +33,11 @@ abstract class DiffUtilAdapter<D, VH : RecyclerView.ViewHolder> : RecyclerView.A
|
||||
private suspend fun internalUpdate(list: List<D>) {
|
||||
val finalList = prepareList(list)
|
||||
val result = DiffUtil.calculateDiff(diffCallback.apply { update(dataset, finalList) }, detectMoves())
|
||||
launch(UI) {
|
||||
withContext(UI) {
|
||||
dataset = finalList
|
||||
result.dispatchUpdatesTo(this@DiffUtilAdapter)
|
||||
onUpdateFinished()
|
||||
}.join()
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun prepareList(list: List<D>) : List<D> = ArrayList(list)
|
||||
|
||||
@@ -66,14 +66,12 @@ import org.videolan.vlc.gui.browser.ExtensionBrowser;
|
||||
import org.videolan.vlc.gui.browser.FileBrowserFragment;
|
||||
import org.videolan.vlc.gui.browser.MediaBrowserFragment;
|
||||
import org.videolan.vlc.gui.browser.NetworkBrowserFragment;
|
||||
import org.videolan.vlc.gui.dialogs.RenderersDialog;
|
||||
import org.videolan.vlc.gui.helpers.UiTools;
|
||||
import org.videolan.vlc.gui.network.MRLPanelFragment;
|
||||
import org.videolan.vlc.gui.preferences.PreferencesActivity;
|
||||
import org.videolan.vlc.gui.preferences.PreferencesFragment;
|
||||
import org.videolan.vlc.gui.video.VideoGridFragment;
|
||||
import org.videolan.vlc.gui.view.HackyDrawerLayout;
|
||||
import org.videolan.vlc.interfaces.Filterable;
|
||||
import org.videolan.vlc.interfaces.IRefreshable;
|
||||
import org.videolan.vlc.media.MediaUtils;
|
||||
import org.videolan.vlc.util.Constants;
|
||||
@@ -197,8 +195,7 @@ public class MainActivity extends ContentActivity implements FilterQueryProvider
|
||||
ft.remove(fragment);
|
||||
} else if ((fragment instanceof MediaBrowserFragment)) {
|
||||
mFragmentsStack.put(fragment.getTag(), new WeakReference<>(fragment));
|
||||
if (fragment != displayed)
|
||||
ft.hide(fragment);
|
||||
if (!TextUtils.equals(fragment.getTag(), displayed.getTag())) ft.hide(fragment);
|
||||
}
|
||||
}
|
||||
ft.commit();
|
||||
@@ -211,7 +208,6 @@ public class MainActivity extends ContentActivity implements FilterQueryProvider
|
||||
MenuItem item = mNavigationView.getMenu().findItem(R.id.nav_directories);
|
||||
item.setTitle(R.string.open);
|
||||
}
|
||||
|
||||
mNavigationView.getMenu().findItem(R.id.nav_history).setVisible(mSettings.getBoolean(PreferencesFragment.PLAYBACK_HISTORY, true));
|
||||
}
|
||||
|
||||
|
||||
@@ -118,8 +118,12 @@ public class PlaylistActivity extends AudioPlayerContainerActivity implements IE
|
||||
mBinding.fab.setVisibility(fabVisibility);
|
||||
}
|
||||
});
|
||||
} else
|
||||
fabFallback();
|
||||
} else VLCApplication.runOnMainThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fabFallback();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else
|
||||
@@ -130,7 +134,7 @@ public class PlaylistActivity extends AudioPlayerContainerActivity implements IE
|
||||
private void fabFallback() {
|
||||
mBinding.appbar.setExpanded(false);
|
||||
ViewCompat.setNestedScrollingEnabled(mBinding.songs, false);
|
||||
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) mBinding.fab.getLayoutParams();
|
||||
final CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) mBinding.fab.getLayoutParams();
|
||||
lp.setAnchorId(R.id.container_list);
|
||||
lp.anchorGravity = Gravity.BOTTOM|Gravity.RIGHT|Gravity.END;
|
||||
lp.bottomMargin = getResources().getDimensionPixelSize(R.dimen.default_margin);
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
@@ -349,7 +350,9 @@ public class AudioAlbumsSongsFragment extends BaseAudioBrowser implements SwipeR
|
||||
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (activity == null) return;
|
||||
activity.supportInvalidateOptionsMenu();
|
||||
mFastScroller.setRecyclerView(mLists[tab.getPosition()]);
|
||||
}
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ public class AudioBrowserAdapter extends SortableAdapter<MediaLibraryItem, Audio
|
||||
}
|
||||
|
||||
private boolean isPositionValid(int position) {
|
||||
return position >= 0 || position < getDataset().size();
|
||||
return position >= 0 && position < getDataset().size();
|
||||
}
|
||||
|
||||
public List<MediaLibraryItem> getAll() {
|
||||
|
||||
@@ -74,11 +74,11 @@ import java.util.Random;
|
||||
public class AudioBrowserFragment extends BaseAudioBrowser implements SwipeRefreshLayout.OnRefreshListener, ViewPager.OnPageChangeListener, Medialibrary.ArtistsAddedCb, Medialibrary.ArtistsModifiedCb, Medialibrary.AlbumsAddedCb, Medialibrary.AlbumsModifiedCb, MediaAddedCb, MediaUpdatedCb, TabLayout.OnTabSelectedListener {
|
||||
public final static String TAG = "VLC/AudioBrowserFragment";
|
||||
|
||||
private final AudioBrowserAdapter mSongsAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_MEDIA, this, true);
|
||||
private final AudioBrowserAdapter mArtistsAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_ARTIST, this, true);
|
||||
private final AudioBrowserAdapter mAlbumsAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_ALBUM, this, true);
|
||||
private final AudioBrowserAdapter mGenresAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_GENRE, this, true);
|
||||
private final AudioBrowserAdapter mPlaylistAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_PLAYLIST, this, true);
|
||||
private AudioBrowserAdapter mSongsAdapter;
|
||||
private AudioBrowserAdapter mArtistsAdapter;
|
||||
private AudioBrowserAdapter mAlbumsAdapter;
|
||||
private AudioBrowserAdapter mGenresAdapter;
|
||||
private AudioBrowserAdapter mPlaylistAdapter;
|
||||
|
||||
private ViewPager mViewPager;
|
||||
private TabLayout mTabLayout;
|
||||
@@ -103,6 +103,11 @@ public class AudioBrowserFragment extends BaseAudioBrowser implements SwipeRefre
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mSongsAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_MEDIA, this, true);
|
||||
mArtistsAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_ARTIST, this, true);
|
||||
mAlbumsAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_ALBUM, this, true);
|
||||
mGenresAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_GENRE, this, true);
|
||||
mPlaylistAdapter = new AudioBrowserAdapter(MediaLibraryItem.TYPE_PLAYLIST, this, true);
|
||||
mAdapters = new AudioBrowserAdapter[]{mArtistsAdapter, mAlbumsAdapter, mSongsAdapter, mGenresAdapter, mPlaylistAdapter};
|
||||
}
|
||||
|
||||
@@ -167,6 +172,8 @@ public class AudioBrowserFragment extends BaseAudioBrowser implements SwipeRefre
|
||||
} else {
|
||||
mMediaLibrary.removeMediaUpdatedCb();
|
||||
mMediaLibrary.removeMediaAddedCb();
|
||||
mMediaLibrary.setArtistsAddedCb(null);
|
||||
mMediaLibrary.setAlbumsAddedCb(null);
|
||||
for (View rv : mLists)
|
||||
unregisterForContextMenu(rv);
|
||||
mViewPager.removeOnPageChangeListener(this);
|
||||
|
||||
@@ -61,32 +61,32 @@ public class BaseBrowserAdapter extends SortableAdapter<MediaLibraryItem, BaseBr
|
||||
protected static final String TAG = "VLC/BaseBrowserAdapter";
|
||||
|
||||
private static int FOLDER_RES_ID = R.drawable.ic_menu_folder;
|
||||
|
||||
private static final BitmapDrawable IMAGE_FOLDER = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), FOLDER_RES_ID));
|
||||
private static final BitmapDrawable IMAGE_AUDIO = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_audio_normal));
|
||||
private static final BitmapDrawable IMAGE_VIDEO = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_video_normal));
|
||||
private static final BitmapDrawable IMAGE_SUBTITLE = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_subtitle_normal));
|
||||
private static final BitmapDrawable IMAGE_UNKNOWN = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_unknown_normal));
|
||||
|
||||
private static final BitmapDrawable IMAGE_QA_MOVIES = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_movies_normal));
|
||||
private static final BitmapDrawable IMAGE_QA_MUSIC = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_music_normal));
|
||||
private static final BitmapDrawable IMAGE_QA_PODCASTS = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_podcasts_normal));
|
||||
private static final BitmapDrawable IMAGE_QA_DOWNLOAD = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_download_normal));
|
||||
|
||||
private List<MediaLibraryItem> mOriginalData = null;
|
||||
protected final BaseBrowserFragment fragment;
|
||||
private int mTop = 0, mMediaCount = 0, mSelectionCount = 0;
|
||||
private ItemFilter mFilter = new ItemFilter();
|
||||
private final boolean mFilesRoot, mNetworkRoot, mSpecialIcons;
|
||||
private final boolean mNetworkRoot, mSpecialIcons;
|
||||
|
||||
private static class Images {
|
||||
private static final BitmapDrawable IMAGE_FOLDER = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), FOLDER_RES_ID));
|
||||
private static final BitmapDrawable IMAGE_AUDIO = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_audio_normal));
|
||||
private static final BitmapDrawable IMAGE_VIDEO = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_video_normal));
|
||||
private static final BitmapDrawable IMAGE_SUBTITLE = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_subtitle_normal));
|
||||
private static final BitmapDrawable IMAGE_UNKNOWN = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_unknown_normal));
|
||||
private static final BitmapDrawable IMAGE_QA_MOVIES = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_movies_normal));
|
||||
private static final BitmapDrawable IMAGE_QA_MUSIC = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_music_normal));
|
||||
private static final BitmapDrawable IMAGE_QA_PODCASTS = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_podcasts_normal));
|
||||
private static final BitmapDrawable IMAGE_QA_DOWNLOAD = new BitmapDrawable(VLCApplication.getAppResources(), BitmapFactory.decodeResource(VLCApplication.getAppResources(), R.drawable.ic_browser_download_normal));
|
||||
}
|
||||
|
||||
BaseBrowserAdapter(BaseBrowserFragment fragment) {
|
||||
this.fragment = fragment;
|
||||
final boolean root = fragment.isRootDirectory();
|
||||
final boolean fileBrowser = fragment instanceof FileBrowserFragment;
|
||||
mFilesRoot = root && fileBrowser;
|
||||
final boolean filesRoot = root && fileBrowser;
|
||||
mNetworkRoot = root && fragment instanceof NetworkBrowserFragment;
|
||||
final String mrl = fragment.mMrl;
|
||||
mSpecialIcons = mFilesRoot || fileBrowser && mrl != null && mrl.endsWith(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY);
|
||||
mSpecialIcons = filesRoot || fileBrowser && mrl != null && mrl.endsWith(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,8 +111,7 @@ public class BaseBrowserAdapter extends SortableAdapter<MediaLibraryItem, BaseBr
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
|
||||
if (payloads.isEmpty())
|
||||
onBindViewHolder(holder, position);
|
||||
if (payloads.isEmpty()) onBindViewHolder(holder, position);
|
||||
else if (payloads.get(0) instanceof CharSequence){
|
||||
((MediaViewHolder) holder).binding.text.setVisibility(View.VISIBLE);
|
||||
((MediaViewHolder) holder).binding.text.setText((CharSequence) payloads.get(0));
|
||||
@@ -124,8 +123,7 @@ public class BaseBrowserAdapter extends SortableAdapter<MediaLibraryItem, BaseBr
|
||||
final MediaWrapper media = (MediaWrapper) getItem(position);
|
||||
vh.binding.setItem(media);
|
||||
vh.binding.setHasContextMenu(true);
|
||||
if (mNetworkRoot)
|
||||
vh.binding.setProtocol(getProtocol(media));
|
||||
if (mNetworkRoot) vh.binding.setProtocol(getProtocol(media));
|
||||
vh.binding.setCover(getIcon(media, mSpecialIcons));
|
||||
vh.selectView(media.hasStateFlags(FLAG_SELECTED));
|
||||
}
|
||||
@@ -201,7 +199,7 @@ public class BaseBrowserAdapter extends SortableAdapter<MediaLibraryItem, BaseBr
|
||||
|
||||
public boolean onLongClick(View v) {
|
||||
int position = getLayoutPosition();
|
||||
if (getItem(position).getItemType() == TYPE_STORAGE) {
|
||||
if (getItem(position).getItemType() == TYPE_STORAGE && VLCApplication.showTvUi()) {
|
||||
binding.browserCheckbox.toggle();
|
||||
onCheckBoxClick(binding.browserCheckbox);
|
||||
return true;
|
||||
@@ -310,27 +308,27 @@ public class BaseBrowserAdapter extends SortableAdapter<MediaLibraryItem, BaseBr
|
||||
BitmapDrawable getIcon(MediaWrapper media, boolean specialFolders) {
|
||||
switch (media.getType()){
|
||||
case MediaWrapper.TYPE_AUDIO:
|
||||
return IMAGE_AUDIO;
|
||||
return Images.IMAGE_AUDIO;
|
||||
case MediaWrapper.TYPE_DIR:
|
||||
if (specialFolders) {
|
||||
final Uri uri = media.getUri();
|
||||
if (AndroidDevices.MediaFolders.EXTERNAL_PUBLIC_MOVIES_DIRECTORY_URI.equals(uri)
|
||||
|| AndroidDevices.MediaFolders.WHATSAPP_VIDEOS_FILE_URI.equals(uri))
|
||||
return IMAGE_QA_MOVIES;
|
||||
return Images.IMAGE_QA_MOVIES;
|
||||
if (AndroidDevices.MediaFolders.EXTERNAL_PUBLIC_MUSIC_DIRECTORY_URI.equals(uri))
|
||||
return IMAGE_QA_MUSIC;
|
||||
return Images.IMAGE_QA_MUSIC;
|
||||
if (AndroidDevices.MediaFolders.EXTERNAL_PUBLIC_PODCAST_DIRECTORY_URI.equals(uri))
|
||||
return IMAGE_QA_PODCASTS;
|
||||
return Images.IMAGE_QA_PODCASTS;
|
||||
if (AndroidDevices.MediaFolders.EXTERNAL_PUBLIC_DOWNLOAD_DIRECTORY_URI.equals(uri))
|
||||
return IMAGE_QA_DOWNLOAD;
|
||||
return Images.IMAGE_QA_DOWNLOAD;
|
||||
}
|
||||
return IMAGE_FOLDER;
|
||||
return Images.IMAGE_FOLDER;
|
||||
case MediaWrapper.TYPE_VIDEO:
|
||||
return IMAGE_VIDEO;
|
||||
return Images.IMAGE_VIDEO;
|
||||
case MediaWrapper.TYPE_SUBTITLE:
|
||||
return IMAGE_SUBTITLE;
|
||||
return Images.IMAGE_SUBTITLE;
|
||||
default:
|
||||
return IMAGE_UNKNOWN;
|
||||
return Images.IMAGE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
String getProtocol(MediaWrapper media) {
|
||||
|
||||
@@ -24,6 +24,7 @@ package org.videolan.vlc.gui.browser;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -106,7 +107,7 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
protected int mSavedPosition = -1, mFavorites = 0;
|
||||
public boolean mRoot;
|
||||
protected boolean goBack = false;
|
||||
private final boolean mShowHiddenFiles;
|
||||
private boolean mShowHiddenFiles;
|
||||
|
||||
private SimpleArrayMap<MediaLibraryItem, List<MediaLibraryItem>> mFoldersContentLists;
|
||||
public int mCurrentParsedPosition = 0;
|
||||
@@ -131,30 +132,24 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
handlerThread.start();
|
||||
mBrowserHandler = new Handler(handlerThread.getLooper());
|
||||
}
|
||||
mShowHiddenFiles = PreferenceManager.getDefaultSharedPreferences(VLCApplication.getAppContext()).getBoolean("browser_show_hidden_files", false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
if (bundle == null)
|
||||
bundle = getArguments();
|
||||
if (bundle == null) bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
if (VLCApplication.hasData(KEY_CONTENT_LIST))
|
||||
mFoldersContentLists = (SimpleArrayMap<MediaLibraryItem, List<MediaLibraryItem>>) VLCApplication.getData(KEY_CONTENT_LIST);
|
||||
mCurrentMedia = bundle.getParcelable(KEY_MEDIA);
|
||||
if (mCurrentMedia != null)
|
||||
mMrl = mCurrentMedia.getLocation();
|
||||
else
|
||||
mMrl = bundle.getString(KEY_MRL);
|
||||
if (mCurrentMedia != null) mMrl = mCurrentMedia.getLocation();
|
||||
else mMrl = bundle.getString(KEY_MRL);
|
||||
mSavedPosition = bundle.getInt(KEY_POSITION);
|
||||
} else if (getActivity().getIntent() != null){
|
||||
mMrl = getActivity().getIntent().getDataString();
|
||||
getActivity().setIntent(null);
|
||||
}
|
||||
mShowHiddenFiles = PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("browser_show_hidden_files", false);
|
||||
mRoot = defineIsRoot();
|
||||
if (mFoldersContentLists == null)
|
||||
mFoldersContentLists = new SimpleArrayMap<>();
|
||||
if (mFoldersContentLists == null) mFoldersContentLists = new SimpleArrayMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -187,23 +182,21 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
if (mAdapter == null)
|
||||
mAdapter = new BaseBrowserAdapter(this);
|
||||
if (mAdapter == null) mAdapter = new BaseBrowserAdapter(this);
|
||||
mLayoutManager = new LinearLayoutManager(getActivity());
|
||||
mRecyclerView.setLayoutManager(mLayoutManager);
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
registerForContextMenu(mRecyclerView);
|
||||
mSwipeRefreshLayout.setOnRefreshListener(this);
|
||||
|
||||
VLCApplication.storeData(KEY_CONTENT_LIST+mMrl, mFoldersContentLists);
|
||||
@SuppressWarnings("unchecked")
|
||||
final SimpleArrayMap<MediaLibraryItem, List<MediaLibraryItem>> content = (SimpleArrayMap<MediaLibraryItem, List<MediaLibraryItem>>) VLCApplication.getData(KEY_CONTENT_LIST + mMrl);
|
||||
if (content != null)
|
||||
mFoldersContentLists = content;
|
||||
if (content != null) mFoldersContentLists = content;
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<MediaLibraryItem> mediaList = mRoot ? null : (List<MediaLibraryItem>) VLCApplication.getData(KEY_MEDIA_LIST + mMrl);
|
||||
if (!Util.isListEmpty(mediaList)) mAdapter.update(mediaList);
|
||||
else mHandler.sendEmptyMessage(BrowserFragmentHandler.MSG_REFRESH);
|
||||
if (!Util.isListEmpty(mediaList)) {
|
||||
mAdapter.update(mediaList);
|
||||
parseSubDirectories();
|
||||
} else mHandler.sendEmptyMessage(BrowserFragmentHandler.MSG_REFRESH);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,10 +204,8 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
super.onResume();
|
||||
if (mCurrentMedia != null)
|
||||
setSearchVisibility(false);
|
||||
if (goBack)
|
||||
goBack();
|
||||
else
|
||||
restoreList();
|
||||
if (goBack) goBack();
|
||||
else restoreList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -276,8 +267,13 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (activity == null) return false;
|
||||
if (!mRoot) {
|
||||
final FragmentManager fm = activity.getSupportFragmentManager();
|
||||
final String tag = fm.getBackStackEntryAt(fm.getBackStackEntryCount()-1).getName();
|
||||
if (!activity.getSupportFragmentManager().popBackStackImmediate() && activity instanceof MainActivity)
|
||||
((MainActivity)activity).showFragment(this instanceof NetworkBrowserFragment ? R.id.nav_network : R.id.nav_directories);
|
||||
final Fragment current = fm.findFragmentByTag(tag);
|
||||
final View view = current != null ? current.getView() : null;
|
||||
if (view != null) view.setVisibility(View.VISIBLE);
|
||||
}
|
||||
return !mRoot;
|
||||
}
|
||||
@@ -329,8 +325,7 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
|
||||
@Override
|
||||
public void onBrowseEnd() {
|
||||
if (!isAdded())
|
||||
return;
|
||||
if (!isAdded()) return;
|
||||
if (refreshing && !mRoot) {
|
||||
refreshing = false;
|
||||
VLCApplication.runOnMainThread(new Runnable() {
|
||||
@@ -347,7 +342,7 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
VLCApplication.runOnMainThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onUpdateFinished(mAdapter);
|
||||
parseSubDirectories();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -470,6 +465,7 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
fragment.mSwipeRefreshLayout.setRefreshing(false);
|
||||
break;
|
||||
case MSG_REFRESH:
|
||||
removeMessages(MSG_REFRESH);
|
||||
if (!fragment.isDetached()) fragment.refresh();
|
||||
}
|
||||
}
|
||||
@@ -612,34 +608,33 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
}
|
||||
|
||||
private void showMediaInfo(MediaWrapper mw) {
|
||||
Intent i = new Intent(getActivity(), InfoActivity.class);
|
||||
final Intent i = new Intent(getActivity(), InfoActivity.class);
|
||||
i.putExtra(InfoActivity.TAG_ITEM, mw);
|
||||
startActivity(i);
|
||||
}
|
||||
|
||||
private void playAll(MediaWrapper mw) {
|
||||
int positionInPlaylist = 0;
|
||||
LinkedList<MediaWrapper> mediaLocations = new LinkedList<>();
|
||||
MediaWrapper media;
|
||||
final LinkedList<MediaWrapper> mediaLocations = new LinkedList<>();
|
||||
for (Object file : mAdapter.getAll())
|
||||
if (file instanceof MediaWrapper) {
|
||||
media = (MediaWrapper) file;
|
||||
final MediaWrapper media = (MediaWrapper) file;
|
||||
if ((AndroidUtil.isHoneycombOrLater && media.getType() == MediaWrapper.TYPE_VIDEO) || media.getType() == MediaWrapper.TYPE_AUDIO) {
|
||||
mediaLocations.add(media);
|
||||
if (mw != null && media.equals(mw))
|
||||
positionInPlaylist = mediaLocations.size() - 1;
|
||||
}
|
||||
}
|
||||
MediaUtils.openList(getActivity(), mediaLocations, positionInPlaylist);
|
||||
if (getActivity() != null) MediaUtils.openList(getActivity(), mediaLocations, positionInPlaylist);
|
||||
}
|
||||
|
||||
List<MediaLibraryItem> currentMediaList = new ArrayList<>();
|
||||
private final List<MediaLibraryItem> currentMediaList = new ArrayList<>();
|
||||
protected void parseSubDirectories() {
|
||||
if ((mRoot && this instanceof NetworkBrowserFragment)
|
||||
|| mCurrentParsedPosition == -1 ||this instanceof FilePickerFragment) return;
|
||||
synchronized (currentMediaList) {
|
||||
currentMediaList = new ArrayList<>(mAdapter.getAll());
|
||||
if ((mRoot && this instanceof NetworkBrowserFragment) || mCurrentParsedPosition == -1 ||
|
||||
currentMediaList.isEmpty() || this instanceof FilePickerFragment)
|
||||
return;
|
||||
currentMediaList.addAll(mAdapter.peekLast());
|
||||
if (currentMediaList.isEmpty()) return;
|
||||
}
|
||||
runOnBrowserThread(new Runnable() {
|
||||
@Override
|
||||
@@ -648,10 +643,9 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
mFoldersContentLists.clear();
|
||||
initMediaBrowser(mFoldersBrowserListener);
|
||||
mCurrentParsedPosition = 0;
|
||||
MediaLibraryItem item;
|
||||
MediaWrapper mw;
|
||||
while (mCurrentParsedPosition < currentMediaList.size()) {
|
||||
item = currentMediaList.get(mCurrentParsedPosition);
|
||||
final MediaLibraryItem item = currentMediaList.get(mCurrentParsedPosition);
|
||||
final MediaWrapper mw;
|
||||
if (item.getItemType() == MediaLibraryItem.TYPE_STORAGE) {
|
||||
mw = new MediaWrapper(((Storage) item).getUri());
|
||||
mw.setType(MediaWrapper.TYPE_DIR);
|
||||
@@ -674,17 +668,17 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
}
|
||||
|
||||
private MediaBrowser.EventListener mFoldersBrowserListener = new MediaBrowser.EventListener(){
|
||||
List<MediaWrapper> directories = new ArrayList<>();
|
||||
List<MediaWrapper> files = new ArrayList<>();
|
||||
final List<MediaWrapper> directories = new ArrayList<>();
|
||||
final List<MediaWrapper> files = new ArrayList<>();
|
||||
Resources res = null;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public void onMediaAdded(int index, final Media media) {
|
||||
final int type = media.getType();
|
||||
final MediaWrapper mw = getMediaWrapper(new MediaWrapper(media));
|
||||
if (type == Media.Type.Directory)
|
||||
directories.add(mw);
|
||||
else if (type == Media.Type.File)
|
||||
files.add(mw);
|
||||
if (type == Media.Type.Directory) directories.add(mw);
|
||||
else if (type == Media.Type.File) files.add(mw);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -702,7 +696,7 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
MediaWrapper mw = null;
|
||||
|
||||
if (!TextUtils.equals(holderText, "")) {
|
||||
MediaLibraryItem item = currentMediaList.get(mCurrentParsedPosition);
|
||||
final MediaLibraryItem item = currentMediaList.get(mCurrentParsedPosition);
|
||||
item.setDescription(holderText);
|
||||
final int position = mCurrentParsedPosition;
|
||||
mRecyclerView.post(new Runnable() {
|
||||
@@ -715,7 +709,7 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
mFoldersContentLists.put(item, new ArrayList<MediaLibraryItem>(directories));
|
||||
}
|
||||
while (++mCurrentParsedPosition < currentMediaList.size()){ //skip media that are not browsable
|
||||
MediaLibraryItem item = currentMediaList.get(mCurrentParsedPosition);
|
||||
final MediaLibraryItem item = currentMediaList.get(mCurrentParsedPosition);
|
||||
if (item.getItemType() == MediaLibraryItem.TYPE_MEDIA) {
|
||||
mw = (MediaWrapper) item;
|
||||
if (mw.getType() == MediaWrapper.TYPE_DIR || mw.getType() == MediaWrapper.TYPE_PLAYLIST)
|
||||
@@ -732,12 +726,12 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
browse(mw.getUri(), 0);
|
||||
} else {
|
||||
mCurrentParsedPosition = -1;
|
||||
currentMediaList = new ArrayList<>();
|
||||
currentMediaList.clear();
|
||||
releaseBrowser();
|
||||
}
|
||||
} else {
|
||||
releaseBrowser();
|
||||
currentMediaList = new ArrayList<>();
|
||||
currentMediaList.clear();
|
||||
}
|
||||
directories .clear();
|
||||
files.clear();
|
||||
@@ -745,35 +739,32 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
}
|
||||
|
||||
private String getDescription(int folderCount, int mediaFileCount) {
|
||||
String holderText = "";
|
||||
if (res == null) res = getResources();
|
||||
sb.setLength(0);
|
||||
if (folderCount > 0) {
|
||||
holderText += VLCApplication.getAppResources().getQuantityString(
|
||||
sb.append(res.getQuantityString(
|
||||
R.plurals.subfolders_quantity, folderCount, folderCount
|
||||
);
|
||||
if (mediaFileCount > 0)
|
||||
holderText += ", ";
|
||||
));
|
||||
if (mediaFileCount > 0) sb.append(", ");
|
||||
}
|
||||
if (mediaFileCount > 0)
|
||||
holderText += VLCApplication.getAppResources().getQuantityString(
|
||||
R.plurals.mediafiles_quantity, mediaFileCount,
|
||||
mediaFileCount);
|
||||
sb.append(res.getQuantityString(
|
||||
R.plurals.mediafiles_quantity, mediaFileCount, mediaFileCount));
|
||||
else if (folderCount == 0 && mediaFileCount == 0)
|
||||
holderText = getString(R.string.directory_empty);
|
||||
return holderText;
|
||||
sb.append(getString(R.string.directory_empty));
|
||||
return sb.toString();
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
private MediaWrapper getMediaWrapper(MediaWrapper media) {
|
||||
MediaWrapper mw = null;
|
||||
Uri uri = media.getUri();
|
||||
final Uri uri = media.getUri();
|
||||
if ((media.getType() == MediaWrapper.TYPE_AUDIO
|
||||
|| media.getType() == MediaWrapper.TYPE_VIDEO)
|
||||
&& "file".equals(uri.getScheme()))
|
||||
mw = mMediaLibrary.getMedia(uri);
|
||||
if (mw == null)
|
||||
return media;
|
||||
return mw;
|
||||
return mw != null ? mw : media;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -875,9 +866,8 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
}
|
||||
|
||||
public boolean onLongClick(View v, int position, MediaLibraryItem item) {
|
||||
if (mActionMode != null)
|
||||
return false;
|
||||
MediaWrapper mediaWrapper = (MediaWrapper) item;
|
||||
if (mActionMode != null || item.getItemType() != MediaLibraryItem.TYPE_MEDIA) return false;
|
||||
final MediaWrapper mediaWrapper = (MediaWrapper) item;
|
||||
if (mediaWrapper.getType() == MediaWrapper.TYPE_AUDIO ||
|
||||
mediaWrapper.getType() == MediaWrapper.TYPE_VIDEO ||
|
||||
mediaWrapper.getType() == MediaWrapper.TYPE_DIR) {
|
||||
@@ -901,14 +891,13 @@ public abstract class BaseBrowserFragment extends SortableFragment<BaseBrowserAd
|
||||
mHandler.sendEmptyMessage(BrowserFragmentHandler.MSG_HIDE_LOADING);
|
||||
updateEmptyView();
|
||||
if (!mAdapter.isEmpty()) {
|
||||
parseSubDirectories();
|
||||
if (mSavedPosition > 0) {
|
||||
mLayoutManager.scrollToPositionWithOffset(mSavedPosition, 0);
|
||||
mSavedPosition = 0;
|
||||
}
|
||||
if (mRoot) parseSubDirectories();
|
||||
}
|
||||
if (!mRoot)
|
||||
updateFab();
|
||||
if (!mRoot) updateFab();
|
||||
}
|
||||
|
||||
private void updateFab() {
|
||||
|
||||
@@ -110,6 +110,10 @@ public class FileBrowserFragment extends BaseBrowserFragment {
|
||||
directory.setType(MediaWrapper.TYPE_DIR);
|
||||
if (TextUtils.equals(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY, mediaDirLocation))
|
||||
directory.setDisplayTitle(internalmemoryTitle);
|
||||
else {
|
||||
final String deviceName = FileUtils.getStorageTag(directory.getTitle());
|
||||
if (deviceName != null) directory.setDisplayTitle(deviceName);
|
||||
}
|
||||
devices.add(directory);
|
||||
}
|
||||
// Set folders shortcuts
|
||||
|
||||
@@ -80,8 +80,10 @@ public class NetworkBrowserFragment extends BaseBrowserFragment implements Exter
|
||||
public void refresh() {
|
||||
if (ExternalMonitor.isConnected())
|
||||
super.refresh();
|
||||
else
|
||||
else {
|
||||
updateEmptyView();
|
||||
mAdapter.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,22 +132,16 @@ public class NetworkBrowserFragment extends BaseBrowserFragment implements Exter
|
||||
|
||||
protected boolean handleContextItemSelected(MenuItem item, final int position) {
|
||||
int id = item.getItemId();
|
||||
if (! (mAdapter.getItem(position) instanceof MediaWrapper))
|
||||
return super.onContextItemSelected(item);
|
||||
if (!(mAdapter.getItem(position) instanceof MediaWrapper)) return false;
|
||||
final MediaWrapper mw = (MediaWrapper) mAdapter.getItem(position);
|
||||
MediaDatabase db;
|
||||
switch (id){
|
||||
case R.id.network_add_favorite:
|
||||
db = MediaDatabase.getInstance();
|
||||
db.addNetworkFavItem(mw.getUri(), mw.getTitle(), mw.getArtworkURL());
|
||||
if (isRootDirectory())
|
||||
updateFavorites();
|
||||
MediaDatabase.getInstance().addNetworkFavItem(mw.getUri(), mw.getTitle(), mw.getArtworkURL());
|
||||
if (isRootDirectory()) updateFavorites();
|
||||
return true;
|
||||
case R.id.network_remove_favorite:
|
||||
db = MediaDatabase.getInstance();
|
||||
db.deleteNetworkFav(mw.getUri());
|
||||
if (isRootDirectory())
|
||||
updateFavorites();
|
||||
MediaDatabase.getInstance().deleteNetworkFav(mw.getUri());
|
||||
if (isRootDirectory()) updateFavorites();
|
||||
return true;
|
||||
case R.id.network_edit_favorite:
|
||||
showAddServerDialog(mw);
|
||||
@@ -156,8 +152,7 @@ public class NetworkBrowserFragment extends BaseBrowserFragment implements Exter
|
||||
|
||||
@Override
|
||||
protected void browseRoot() {
|
||||
if (!isAdded())
|
||||
return;
|
||||
if (!isAdded()) return;
|
||||
updateFavorites();
|
||||
mAdapter.setTop(mAdapter.getItemCount());
|
||||
if (allowLAN())
|
||||
@@ -187,12 +182,12 @@ public class NetworkBrowserFragment extends BaseBrowserFragment implements Exter
|
||||
}
|
||||
|
||||
private void updateFavorites() {
|
||||
updateEmptyView();
|
||||
if (!ExternalMonitor.isConnected()) {
|
||||
if (mFavorites != 0) {
|
||||
mAdapter.clear();
|
||||
mFavorites = 0;
|
||||
}
|
||||
updateEmptyView();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -219,9 +214,10 @@ public class NetworkBrowserFragment extends BaseBrowserFragment implements Exter
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mFavorites != 0 && !mAdapter.isEmpty())
|
||||
for (int i = 1 ; i <= mFavorites ; ++i) //remove former favorites
|
||||
if (mFavorites != 0 && !mAdapter.getAll().isEmpty())
|
||||
for (int i = 1 ; i <= mFavorites ; ++i) {//remove former favorites
|
||||
mAdapter.removeItem(1);
|
||||
}
|
||||
|
||||
if (newSize == 0 && !mAdapter.isEmpty()) {
|
||||
mAdapter.removeItem(0); //also remove separator if no more fav
|
||||
@@ -230,19 +226,19 @@ public class NetworkBrowserFragment extends BaseBrowserFragment implements Exter
|
||||
boolean isEmpty = mAdapter.isEmpty();
|
||||
if (mFavorites == 0 || isEmpty)
|
||||
mAdapter.addItem(new DummyItem(getString(R.string.network_favorites)), false,0); //add header if needed
|
||||
for (int i = 0 ; i < newSize ; )
|
||||
for (int i = 0 ; i < newSize ; ) {
|
||||
mAdapter.addItem(favs.get(i), false, ++i); //add new favorites
|
||||
}
|
||||
if (mFavorites == 0 || isEmpty)
|
||||
mAdapter.addItem(new DummyItem(getString(R.string.network_shared_folders)), false, newSize + 1); //add header if needed
|
||||
}
|
||||
mFavorites = newSize; //update count
|
||||
if (newSize != 0)
|
||||
mHandler.sendEmptyMessage(BrowserFragmentHandler.MSG_HIDE_LOADING);
|
||||
updateEmptyView();
|
||||
}
|
||||
|
||||
public void toggleFavorite() {
|
||||
MediaDatabase db = MediaDatabase.getInstance();
|
||||
final MediaDatabase db = MediaDatabase.getInstance();
|
||||
if (db.networkFavExists(mCurrentMedia.getUri()))
|
||||
db.deleteNetworkFav(mCurrentMedia.getUri());
|
||||
else
|
||||
@@ -254,8 +250,7 @@ public class NetworkBrowserFragment extends BaseBrowserFragment implements Exter
|
||||
* Update views visibility and emptiness info
|
||||
*/
|
||||
protected void updateEmptyView() {
|
||||
if (mEmptyView == null)
|
||||
return;
|
||||
if (mEmptyView == null) return;
|
||||
if (ExternalMonitor.isConnected()) {
|
||||
if (mAdapter.isEmpty()) {
|
||||
if (mSwipeRefreshLayout == null || mSwipeRefreshLayout.isRefreshing()) {
|
||||
@@ -284,17 +279,14 @@ public class NetworkBrowserFragment extends BaseBrowserFragment implements Exter
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (!isRootDirectory())
|
||||
super.onClick(v);
|
||||
else if (v.getId() == R.id.fab)
|
||||
showAddServerDialog(null);
|
||||
if (!isRootDirectory()) super.onClick(v);
|
||||
else if (v.getId() == R.id.fab) showAddServerDialog(null);
|
||||
}
|
||||
|
||||
public void showAddServerDialog(MediaWrapper mw) {
|
||||
FragmentManager fm = getFragmentManager();
|
||||
NetworkServerDialog dialog = new NetworkServerDialog();
|
||||
if (mw != null)
|
||||
dialog.setServer(mw);
|
||||
final FragmentManager fm = getFragmentManager();
|
||||
final NetworkServerDialog dialog = new NetworkServerDialog();
|
||||
if (mw != null) dialog.setServer(mw);
|
||||
dialog.show(fm, "fragment_add_server");
|
||||
}
|
||||
|
||||
@@ -305,18 +297,16 @@ public class NetworkBrowserFragment extends BaseBrowserFragment implements Exter
|
||||
private BroadcastReceiver mLocalReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (isResumed())
|
||||
goBack();
|
||||
else
|
||||
goBack = true;
|
||||
if (isResumed()) goBack();
|
||||
else goBack = true;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onNetworkConnectionChanged(boolean connected) {
|
||||
final boolean isEmpty = mAdapter.isEmpty();
|
||||
refresh();
|
||||
if (!connected && isEmpty) //update() will trigger updateEmptyView
|
||||
updateEmptyView();
|
||||
mHandler.sendEmptyMessage(BrowserFragmentHandler.MSG_REFRESH);
|
||||
//update() will trigger updateEmptyView
|
||||
if (!connected && isEmpty) updateEmptyView();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,14 +52,14 @@ public abstract class SortableFragment<T extends SortableAdapter> extends MediaB
|
||||
public void onHiddenChanged(boolean hidden) {
|
||||
super.onHiddenChanged(hidden);
|
||||
final T adapter = getCurrentAdapter();
|
||||
if (adapter != null)
|
||||
adapter.updateIfSortChanged();
|
||||
if (adapter != null) adapter.updateIfSortChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
menu.findItem(R.id.ml_menu_sortby).setVisible(isSortEnabled());
|
||||
final MenuItem item = menu.findItem(R.id.ml_menu_sortby);
|
||||
if (item != null) item.setVisible(isSortEnabled());
|
||||
UiTools.updateSortTitles(this, menu);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
package org.videolan.vlc.gui.browser;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.MainThread;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
@@ -57,8 +58,7 @@ class StorageBrowserAdapter extends BaseBrowserAdapter {
|
||||
if (storage.getItemType() == MediaLibraryItem.TYPE_MEDIA)
|
||||
storage = new Storage(((MediaWrapper)storage).getUri());
|
||||
String storagePath = ((Storage)storage).getUri().getPath();
|
||||
if (!storagePath.endsWith("/"))
|
||||
storagePath += "/";
|
||||
if (!storagePath.endsWith("/")) storagePath += "/";
|
||||
boolean hasContextMenu = mCustomDirsLocation.contains(storagePath);
|
||||
boolean checked = ((StorageBrowserFragment) fragment).mScannedDirectory || mMediaDirsLocation.contains(storagePath);
|
||||
vh.binding.setItem(storage);
|
||||
@@ -89,18 +89,17 @@ class StorageBrowserAdapter extends BaseBrowserAdapter {
|
||||
}
|
||||
|
||||
void updateMediaDirs() {
|
||||
if (mMediaDirsLocation != null)
|
||||
mMediaDirsLocation.clear();
|
||||
String folders[] = VLCApplication.getMLInstance().getFoldersList();
|
||||
if (mMediaDirsLocation != null) mMediaDirsLocation.clear();
|
||||
final String folders[] = VLCApplication.getMLInstance().getFoldersList();
|
||||
mMediaDirsLocation = new ArrayList<>(folders.length);
|
||||
for (String folder : folders) {
|
||||
mMediaDirsLocation.add(folder.substring(7));
|
||||
mMediaDirsLocation.add(Uri.decode(folder.startsWith("file://") ? folder.substring(7) : folder));
|
||||
}
|
||||
mCustomDirsLocation = new ArrayList<>(Arrays.asList(CustomDirectories.getCustomDirectories()));
|
||||
}
|
||||
|
||||
protected void checkBoxAction(View v, String mrl) {
|
||||
ThreeStatesCheckbox tscb = (ThreeStatesCheckbox) v;
|
||||
final ThreeStatesCheckbox tscb = (ThreeStatesCheckbox) v;
|
||||
int state = tscb.getState();
|
||||
if (state == ThreeStatesCheckbox.STATE_CHECKED)
|
||||
MedialibraryUtils.addDir(mrl);
|
||||
|
||||
@@ -61,6 +61,7 @@ import org.videolan.vlc.interfaces.IPlaybackSettingsController;
|
||||
import org.videolan.vlc.util.AndroidDevices;
|
||||
import org.videolan.vlc.util.Constants;
|
||||
import org.videolan.vlc.util.Strings;
|
||||
import org.videolan.vlc.util.VLCOptions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
@@ -92,6 +93,7 @@ public class AdvOptionsDialog extends DialogFragment implements View.OnClickList
|
||||
private static final int ID_POPUP_VIDEO = 9 ;
|
||||
private static final int ID_REPEAT = 10 ;
|
||||
private static final int ID_SHUFFLE = 11 ;
|
||||
private static final int ID_PASSTHROUGH = 12 ;
|
||||
|
||||
private Activity mActivity;
|
||||
private int mMode = -1;
|
||||
@@ -102,6 +104,7 @@ public class AdvOptionsDialog extends DialogFragment implements View.OnClickList
|
||||
|
||||
private TextView mPlaybackSpeed;
|
||||
private TextView mSleep;
|
||||
private TextView mPassThrough;
|
||||
|
||||
private TextView mJumpTitle;
|
||||
|
||||
@@ -359,7 +362,15 @@ public class AdvOptionsDialog extends DialogFragment implements View.OnClickList
|
||||
? R.drawable.ic_shuffle_on
|
||||
: UiTools.getResourceFromAttribute(mActivity, R.attr.ic_shuffle),
|
||||
0, 0);
|
||||
}
|
||||
|
||||
public void initPassthrough(){
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(AdvOptionsDialog.this.getContext());
|
||||
mPassThrough.setCompoundDrawablesWithIntrinsicBounds(0,
|
||||
VLCOptions.isAudioDigitalOutputEnabled(prefs)
|
||||
? R.drawable.ic_passthrough_on
|
||||
: UiTools.getResourceFromAttribute(mActivity, R.attr.ic_passthrough),
|
||||
0, 0);
|
||||
}
|
||||
|
||||
private void initChapters() {
|
||||
@@ -415,6 +426,10 @@ public class AdvOptionsDialog extends DialogFragment implements View.OnClickList
|
||||
mShuffle = tv;
|
||||
initShuffle();
|
||||
break;
|
||||
case ID_PASSTHROUGH:
|
||||
mPassThrough = tv;
|
||||
initPassthrough();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,14 +481,30 @@ public class AdvOptionsDialog extends DialogFragment implements View.OnClickList
|
||||
mService.shuffle();
|
||||
initShuffle();
|
||||
break;
|
||||
case ID_PASSTHROUGH: {
|
||||
togglePassthrough();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void togglePassthrough() {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(AdvOptionsDialog.this.getContext());
|
||||
boolean enabled = !VLCOptions.isAudioDigitalOutputEnabled(prefs);
|
||||
if (mService.setAudioDigitalOutputEnabled(enabled)) {
|
||||
mPassThrough.setCompoundDrawablesWithIntrinsicBounds(0,
|
||||
enabled ? R.drawable.ic_passthrough_on
|
||||
: UiTools.getResourceFromAttribute(mActivity, R.attr.ic_passthrough)
|
||||
, 0, 0);
|
||||
VLCOptions.setAudioDigitalOutputEnabled(prefs, enabled);
|
||||
mToast.setText(enabled ? getString(R.string.audio_digital_output_enabled) : getString(R.string.audio_digital_output_disabled));
|
||||
} else mToast.setText(R.string.audio_digital_failed);
|
||||
mToast.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (v instanceof TextView)
|
||||
((TextView) v).setTextColor(v.hasFocus() ?
|
||||
UiTools.Resources.ITEM_FOCUS_ON : mTextColor);
|
||||
if (v instanceof TextView) ((TextView) v).setTextColor(v.hasFocus() ? UiTools.Resources.ITEM_FOCUS_ON : mTextColor);
|
||||
mToast.setText(mAdapter.getSelectedAdvOptionHelp());
|
||||
mToast.show();
|
||||
}
|
||||
@@ -511,6 +542,7 @@ public class AdvOptionsDialog extends DialogFragment implements View.OnClickList
|
||||
mService = service;
|
||||
boolean tvUi = VLCApplication.showTvUi();
|
||||
int large_items = 0;
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(AdvOptionsDialog.this.getContext());
|
||||
|
||||
mAdapter.addOption(new Option(ID_SLEEP, R.attr.ic_sleep_normal_style, getString(R.string.sleep_title)));
|
||||
mAdapter.addOption(new Option(ID_PLAYBACK_SPEED, R.attr.ic_speed_normal_style, getString(R.string.playback_speed)));
|
||||
@@ -522,7 +554,7 @@ public class AdvOptionsDialog extends DialogFragment implements View.OnClickList
|
||||
mAdapter.addOption(new Option(ID_PLAY_AS_AUDIO, R.attr.ic_playasaudio_on, getString(R.string.play_as_audio)));
|
||||
mAdapter.addOption(new Option(ID_SPU_DELAY, R.attr.ic_subtitledelay, getString(R.string.spu_delay)));
|
||||
mAdapter.addOption(new Option(ID_AUDIO_DELAY, R.attr.ic_audiodelay, getString(R.string.audio_delay)));
|
||||
if (primary && (!tvUi || AndroidDevices.hasPiP))
|
||||
if (primary && (!tvUi || AndroidDevices.hasPiP) && !AndroidDevices.isDex(getActivity()))
|
||||
mAdapter.addOption(new Option(ID_POPUP_VIDEO, R.attr.ic_popup_dim, getString(R.string.popup_playback_title)));
|
||||
mAdapter.addOption(new Option(ID_REPEAT, R.attr.ic_repeat, getString(R.string.repeat_title)));
|
||||
if (mService.canShuffle())
|
||||
@@ -537,6 +569,8 @@ public class AdvOptionsDialog extends DialogFragment implements View.OnClickList
|
||||
} else {
|
||||
mAdapter.addOption(new Option(ID_SAVE_PLAYLIST, R.attr.ic_save, getString(R.string.playlist_save)));
|
||||
}
|
||||
if ("0".equals(prefs.getString("aout", "0")))
|
||||
mAdapter.addOption(new Option(ID_PASSTHROUGH, R.attr.ic_passthrough, getString(R.string.audio_digital_title)));
|
||||
setDialogDimensions(large_items);
|
||||
}
|
||||
|
||||
@@ -619,8 +653,7 @@ public class AdvOptionsDialog extends DialogFragment implements View.OnClickList
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
final Option option = mList.get(position);
|
||||
final TextView tv = (TextView) holder.itemView;
|
||||
if (mSelection == position)
|
||||
tv.requestFocus();
|
||||
if (mSelection == position) tv.requestFocus();
|
||||
tv.setId(option.id);
|
||||
final int icon = UiTools.getResourceFromAttribute(mActivity, option.icon);
|
||||
if (option.id == ID_CHAPTER_TITLE)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package org.videolan.vlc.gui.dialogs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.DialogFragment
|
||||
@@ -27,6 +28,7 @@ import android.support.v7.widget.LinearLayoutManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import org.videolan.libvlc.RendererItem
|
||||
import org.videolan.vlc.PlaybackService
|
||||
import org.videolan.vlc.R
|
||||
@@ -58,7 +60,17 @@ class RenderersDialog : DialogFragment(), RendererDelegate.RendererListener, Pla
|
||||
RendererDelegate.removeListener(this)
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
mBinding = DialogRenderersBinding.inflate(inflater, null)
|
||||
val dialog = Dialog(context)
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog.setContentView(mBinding.root)
|
||||
return dialog
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
setStyle(DialogFragment.STYLE_NO_FRAME, 0)
|
||||
mBinding = DialogRenderersBinding.inflate(inflater, container, false)
|
||||
return mBinding.root
|
||||
}
|
||||
|
||||