Compare commits

...

145 Commits

Author SHA1 Message Date
Geoffrey Métais
cedc1837f6 Bump version to v3.0.5-2
(cherry picked from commit 71485e6f22)
2018-04-05 10:50:54 +02:00
Geoffrey Métais
31d29925b9 Update NEWS 2018-04-05 10:48:47 +02:00
Geoffrey Métais
5c00b79dff Deactivate Android Auto
Google blocked 3.0.5 becasue of it.
We need the upgrade to AppCOmpat 27 to fix it.
2018-04-05 09:53:55 +02:00
Geoffrey Métais
7e1cf58998 Bump version to 3.0.5-1 2018-04-04 12:20:29 +02:00
Geoffrey Métais
b3b809ebb9 Update NEWS 2018-04-04 12:17:50 +02:00
Geoffrey Métais
8def943103 Update VLC HASH
(cherry picked from commit 3ccee3ba68)
2018-04-04 11:27:07 +02:00
Geoffrey Métais
6cf57665f4 Delay storages check
Ensure app is foreground when we start service

(cherry picked from commit f32739cf57)
2018-04-04 11:27:07 +02:00
Geoffrey Métais
89e755fdf8 Browsers: init preferences with correct context
(cherry picked from commit 54e4a06693)
2018-04-04 11:27:07 +02:00
Geoffrey Métais
3fa6a9909d Prevent NPE in menu preparation
(cherry picked from commit cb9cb1b3ba)
2018-04-04 11:27:06 +02:00
Geoffrey Métais
1ddbb3edff Bump version to 3.0.5
(cherry picked from commit f0004698ce)
2018-03-30 16:50:07 +02:00
Geoffrey Métais
0f00ad0ebf Update NEWS 2018-03-30 16:50:07 +02:00
Geoffrey Métais
deb6b64035 Prevent crash on Oreo when app is in background
(cherry picked from commit 73845dd1d2)
2018-03-30 16:32:52 +02:00
Geoffrey Métais
8556a04813 Fix audio player started twice on device rotation
(cherry picked from commit e2aa54c7fd)
2018-03-30 16:32:52 +02:00
Geoffrey Métais
d38b4e23c0 Udpate VLC HASH
(cherry picked from commit d3308f79ab)
2018-03-30 16:32:52 +02:00
Geoffrey Métais
c7625a61c0 Update Medialibrary HASH
(cherry picked from commit 7000f6d97a)
2018-03-30 16:32:48 +02:00
Alexandre Perraud
fe0ab425cc Add new passtrough icon
(cherry picked from commit e4aef37502)
2018-03-30 16:31:31 +02:00
Alexandre Perraud
0e6bdb54fb Fix repeat icons
(cherry picked from commit 8f40a8dfdc)
2018-03-30 16:31:31 +02:00
Geoffrey Métais
3716dc558c Audio adapter: fix logic fail
(cherry picked from commit b1b1ae7c14)
2018-03-30 16:31:31 +02:00
Geoffrey Métais
7b6bccf549 Do not filter DOWN remote input events
Close #526

(cherry picked from commit d533f12966)
2018-03-30 16:31:31 +02:00
Thomas Guillem
f98519d590 Audio passthrough setting
(cherry picked from commit 4471bcc940)
2018-03-30 16:31:05 +02:00
Thomas Guillem
4ca7102a7e PlayerController: add setAudioDigitalOutputEnabled
(cherry picked from commit d68b95d310)
2018-03-30 16:31:05 +02:00
Thomas Guillem
cfdbb072a3 LibVLC: MediaPlayer: add forceAudioDigitalEncodings()
(cherry picked from commit b8fd87d284)
2018-03-30 16:31:05 +02:00
Thomas Guillem
4b484911ea LibVLC: MediaPlayer: add setAudioDigitalOutputEnabled
(cherry picked from commit c5cb324dee)
2018-03-30 16:31:04 +02:00
Thomas Guillem
3e81856de9 LibVLC: Mediaplayer: re-indent comments
(cherry picked from commit bfa84f3c0f)
2018-03-30 16:31:04 +02:00
Thomas Guillem
f5c48430ee LibVLC: MediaPlayer: fix plug events thread safety
Unregister it before selecting a new output/device.
Register it after selecting a new output/device.

(cherry picked from commit 47b50ec352)
2018-03-30 16:31:04 +02:00
Thomas Guillem
5d98ec27c2 LibVLC: MediaPlayer: rename mAudioDeviceFromUser
(cherry picked from commit c9cf56f200)
2018-03-30 16:30:31 +02:00
Geoffrey Métais
d3e6d26af9 Update ConstraintLayout
(cherry picked from commit 12e39079c1)
2018-03-30 16:30:31 +02:00
Geoffrey Métais
1c1a42c4c9 Prevent NPE when removable storage is not found
(cherry picked from commit 13a123e6e8)
2018-03-30 16:30:12 +02:00
Geoffrey Métais
1f51895854 VideoPlayerActivity: Prevent ClassCastException
On Android 4.0.x

(cherry picked from commit e943418ca5)
2018-03-30 16:30:12 +02:00
Geoffrey Métais
a20eb7a71d Network browser: prevent StackOverflowError
(cherry picked from commit 0df40ab01e)
2018-03-30 16:30:12 +02:00
Geoffrey Métais
5a6c4cddcb VideoPlayer: Fix controls layout after rotation
(cherry picked from commit 1783523496)
2018-03-30 16:30:12 +02:00
Geoffrey Métais
aba394305a BitmapUtil: Prevent NPE on app startup
(cherry picked from commit fd16512869)
2018-03-30 16:30:12 +02:00
Geoffrey Métais
ce72cc1b44 Video player: Hide debug logs from release
(cherry picked from commit b74887c689)
2018-03-30 16:29:29 +02:00
Geoffrey Métais
fd841ff564 Add video tracks selector in video player
(cherry picked from commit c32f99faf6)
2018-03-30 16:29:29 +02:00
Geoffrey Métais
e94cc5a320 Enlarge subs picker on large screens, including TV
(cherry picked from commit 516a2df077)
2018-03-30 16:29:29 +02:00
Geoffrey Métais
55394a3773 Directly start service if context is an activity
(cherry picked from commit df65474f43)
2018-03-30 16:28:28 +02:00
Geoffrey Métais
dc56cd7dbb PlayerController: update 'newMedia' variable
(cherry picked from commit c164267c46)
2018-03-30 16:28:28 +02:00
Geoffrey Métais
8a5b8b8ffe Set https for videolan.org 'about' link
(cherry picked from commit de27fd29a9)
2018-03-30 16:28:28 +02:00
Geoffrey Métais
cfc68a9ee6 Pass context for notifications init
(cherry picked from commit 23819683f7)
2018-03-30 16:28:28 +02:00
Geoffrey Métais
d09ee78b02 ML settings: Decode folders mrl
(cherry picked from commit 0211b8df97)
2018-03-30 16:27:48 +02:00
Geoffrey Métais
7ac64ace58 Avoid using app context from static call
(cherry picked from commit 5924da8014)
2018-03-30 16:27:48 +02:00
Geoffrey Métais
821b790200 Extract OnDragListener from Activity code
(cherry picked from commit 2a2d72dc41)
2018-03-30 16:27:48 +02:00
Geoffrey Métais
495b1b93b9 Filter onRenderersChanged events
(cherry picked from commit 256d9334e6)
2018-03-30 16:27:48 +02:00
Geoffrey Métais
0d4ed78392 Unset any renderer on disconnection
(cherry picked from commit dc8fbd5c27)
2018-03-30 16:27:48 +02:00
Geoffrey Métais
3d7f476bad Switch to medialibrary branch 0.3.x 2018-03-26 14:44:14 +02:00
Geoffrey Métais
db7f481005 Ensure scanning progress bar is well hidden 2018-03-14 14:06:51 +01:00
Geoffrey Métais
7f7e1cc028 Bump version to 3.0.4
(cherry picked from commit ff9b3dddba)
2018-03-07 15:17:44 +01:00
Geoffrey Métais
3c79824d4b Update NEWS 2018-03-07 15:17:44 +01:00
Geoffrey Métais
86d31810d7 Playback: Avoid double call on play/pause
(cherry picked from commit 6553cc4720)
2018-03-07 15:17:44 +01:00
Geoffrey Métais
ea6b9f604a Get telephony manager with service context
(cherry picked from commit 33eb5c6ccf)
2018-03-07 15:17:44 +01:00
Geoffrey Métais
b333e99fe2 Update VLC HASH
(cherry picked from commit ee7d090729)
2018-03-07 15:03:26 +01:00
Geoffrey Métais
5ae3d0bc6c Update medialibrary HASH
(cherry picked from commit 6c81d437f5)
2018-03-07 15:03:26 +01:00
Geoffrey Métais
746a1b711d Disable Chromecast on Chromebooks
(cherry picked from commit 6e9dea0f0a)
2018-03-07 15:03:26 +01:00
Thomas Guillem
8676a19930 LibVLC: Media: don't override options set by the LibVLC user.
(cherry picked from commit 142154e3ab)
2018-03-07 15:03:26 +01:00
Geoffrey Métais
51da943300 TV: Fix History section display
(cherry picked from commit 921090fd6b)
2018-03-07 15:03:26 +01:00
Geoffrey Métais
7dedf17a6b Use withContext to wait for an async operation
(cherry picked from commit 2787624027)
2018-03-07 15:00:56 +01:00
Geoffrey Métais
43b011eb6f Inner class for Browser images
Avoids to access app context too soon

(cherry picked from commit 1c8fa50a2b)
2018-03-06 13:12:59 +01:00
Geoffrey Métais
3d08646df1 Hack to improve browsers restoration
(cherry picked from commit d5ea343938)
2018-03-06 13:12:59 +01:00
Geoffrey Métais
157074b08c Videos grouping: pass context from fragments
(cherry picked from commit bb3b18ab87)
2018-03-06 13:12:59 +01:00
Geoffrey Métais
99de86a838 Allow all supported characters in ML strings
(cherry picked from commit 851762240e)
2018-03-06 13:12:59 +01:00
Geoffrey Métais
d884268eb4 AudioBrowser: clear medialibrary callbacks
(cherry picked from commit 1b29a3360d)
2018-03-06 13:12:59 +01:00
Geoffrey Métais
5e4bd5b878 Allow '@' in VLC mrl
Close #486

(cherry picked from commit 2f830a099d)
2018-03-06 13:12:59 +01:00
Geoffrey Métais
1b0f1a5a8b Disable long-press on ML storage on phone/tablet
(cherry picked from commit ab79e1b1ef)
2018-03-06 13:12:59 +01:00
Geoffrey Métais
dfa3bf10f8 File deletion: prevent crash
Also, normal delete method for pre-Lollipop devices

(cherry picked from commit bd9f84f7f2)
2018-03-06 13:12:59 +01:00
Geoffrey Métais
fdbb708da3 Browser: Prevent NPE on FAB click
(cherry picked from commit fd411dbd5d)
2018-03-06 13:12:59 +01:00
Geoffrey Métais
fbee081409 Ensure last playlist locations encoding is correct
(cherry picked from commit 9172cbfe30)
2018-03-06 13:12:59 +01:00
Geoffrey Métais
b16c0c2cd0 Fix LibVLC aar package name
(cherry picked from commit c150fdc54d)
2018-03-06 13:12:30 +01:00
Geoffrey Métais
65e17298ee Advanced option to dump media library
(cherry picked from commit a5cadec2f5)
2018-03-01 16:30:59 +01:00
Geoffrey Métais
48ee977295 Bump version to 3.0.3-1
(cherry picked from commit 858760b29e)
2018-03-01 13:24:54 +01:00
Geoffrey Métais
055c986534 Update VLC HASH
(cherry picked from commit 9783a68d3d)
2018-03-01 13:24:54 +01:00
Geoffrey Métais
9fb2c7d8e0 Prevent infinite loop in media playback
If no audio track is detected and repeat was activated, we could loop on the same media trying to
skipping it

(cherry picked from commit b3dbb29afa)
2018-03-01 11:51:19 +01:00
Geoffrey Métais
2d603de7ce Prevent file overwrite from external media uri
Thank to Sergey Toshin for pointing this security flaw

(cherry picked from commit ad0d4c8de2)
2018-03-01 11:51:19 +01:00
Geoffrey Métais
a48f838506 Ensure PlaylistActivity view is set in main thread
(cherry picked from commit fe19149b52)
2018-02-28 10:45:10 +01:00
Geoffrey Métais
bf5aeddf6d Update medialibrary HASH
(cherry picked from commit a2c2c18684)
2018-02-27 17:31:36 +01:00
Geoffrey Métais
94a66434bf Fix BuildConfig.VERSION_CODE not set
(cherry picked from commit 676a57c2f6)
2018-02-27 15:35:04 +01:00
Geoffrey Métais
3127236c3d Upgrade to v3.0.3
(cherry picked from commit 9dded1304f)
2018-02-26 17:57:38 +01:00
Geoffrey Métais
b4f9adf6a0 Update VLC HASH
(cherry picked from commit 12981736a4)
2018-02-26 17:57:38 +01:00
Geoffrey Métais
165f628ead Update medialibrary HASH
(cherry picked from commit 8d06f980fc)
2018-02-26 17:57:38 +01:00
Thomas Guillem
d2cc25317a LibVLC: IVLCVout: add more comments for onNewVideoLayout()
(cherry picked from commit cd1762ed3b)
2018-02-26 17:57:38 +01:00
Geoffrey Métais
45bef07589 Create audio adapters within fragment lifecycle
(cherry picked from commit 323a649f9a)
2018-02-26 16:04:56 +01:00
Geoffrey Métais
fd481d1666 Update NEWS 2018-02-23 17:40:30 +01:00
Geoffrey Métais
3129b510f6 Bump version to 3.0.2
(cherry picked from commit 4ee0d159c8)
2018-02-23 17:28:40 +01:00
Geoffrey Métais
6924073b0f Update VLC HASH
(cherry picked from commit 431c110764)
2018-02-23 17:28:40 +01:00
Geoffrey Métais
e36f3a6e1e Update medialibrary HASH
(cherry picked from commit c7f9f11c71)
2018-02-23 17:28:40 +01:00
Alexandre Janniaux
c67883d4d1 PlaybackService: send EFFECT_CONTROL_SESSION on media state update
Send the *_EFFECT_CONTROL_SESSION intent when the state of current media
is updated. It allows external audio effects like equalizer or
visualizer to know the audio session id used by VLC and apply their own
effect.
See android.media.audiofx.AudioEffect.

Signed-off-by: Geoffrey Métais <geoffrey.metais@gmail.com>
(cherry picked from commit 00316e7f12)
2018-02-23 17:28:40 +01:00
Alexandre Janniaux
5b9c94da47 Generate audio session id in VLCOptions for libVLC
Generate an audio session id from AudioManager and pass it to libVLC as
a command line argument so that it creates AudioTrack in this session.

Signed-off-by: Geoffrey Métais <geoffrey.metais@gmail.com>
(cherry picked from commit f3316483e3)
2018-02-23 17:28:40 +01:00
Geoffrey Métais
c3b48fc9f4 PlaylistManager: Save current index before expand
(cherry picked from commit fcb45f4927)
2018-02-22 15:29:32 +01:00
Geoffrey Métais
4d514eb727 PlaylistManager: Use service to get preferences
(cherry picked from commit 8ebdc39063)
2018-02-22 15:29:32 +01:00
Geoffrey Métais
cbda133cd9 Cache player length
Signed-off-by: Geoffrey Métais <geoffrey.metais@gmail.com>
2018-02-21 16:19:32 +01:00
Geoffrey Métais
2fde878007 Cache current playback time value
Signed-off-by: Geoffrey Métais <geoffrey.metais@gmail.com>
2018-02-21 16:19:32 +01:00
Geoffrey Métais
55cfdfce1b Fix mrl encoding passed to medialibrary
Signed-off-by: Geoffrey Métais <geoffrey.metais@gmail.com>
2018-02-21 16:18:44 +01:00
Geoffrey Métais
faa0bfbc31 Improve Network browser empty view
Signed-off-by: Geoffrey Métais <geoffrey.metais@gmail.com>
2018-02-21 16:18:44 +01:00
Thomas Guillem
78b21d5bbb LibVLC: Media: enable dvdnav for .iso on network shares
Signed-off-by: Geoffrey Métais <geoffrey.metais@gmail.com>
2018-02-21 16:18:44 +01:00
Geoffrey Métais
232c06f896 Restore DVD menu navigation 2018-02-21 11:49:17 +01:00
Geoffrey Métais
410531fe29 Fix folder path encoding in medialibrary settings
(cherry picked from commit 3e7196da34)
2018-02-21 11:29:45 +01:00
Geoffrey Métais
2a948279cd Deactivate PiP in DeX mode
(cherry picked from commit 20dcc21f67)
2018-02-21 11:29:45 +01:00
Geoffrey Métais
047fe044cc Add DeX mode detection
(cherry picked from commit 6750db189c)
2018-02-21 11:29:45 +01:00
Rogério Brito
a6c1699c65 Fix formatting in pt-BR string translation.
Signed-off-by: Geoffrey Métais <geoffrey.metais@gmail.com>

Close #518

(cherry picked from commit c632c2f6ec)
2018-02-21 11:29:45 +01:00
Geoffrey Métais
bbcfed1de1 Fix duplicated network favorites
(cherry picked from commit d9d4b9b2c0)
2018-02-21 11:29:45 +01:00
Geoffrey Métais
3c012459f7 (Yet another) fix for video launch/resume/restore
(cherry picked from commit 735997df4e)
2018-02-20 14:46:02 +01:00
Geoffrey Métais
6389c6c7d1 Update version to 3.0.1-1
(cherry picked from commit a1956893db)
2018-02-20 14:46:02 +01:00
Geoffrey Métais
c6cfc6c3fc Storage permission: use activity as context 2018-02-19 14:59:02 +01:00
Geoffrey Métais
20ca3b3f4e AudioAlbumSongsFragment: Fix NPE
(cherry picked from commit 45812a96a9)
2018-02-19 14:57:12 +01:00
Geoffrey Métais
43abbbb4b3 Fix repeat mode not restored
(cherry picked from commit ccc0729b52)
2018-02-19 14:47:18 +01:00
Geoffrey Métais
dcc31d62a0 We do not need app instance to start jobs
(cherry picked from commit 162f0a0bad)
2018-02-19 11:54:31 +01:00
Geoffrey Métais
ec2f18db98 Fix renderers dialog style
(cherry picked from commit a23c50b489)
2018-02-19 11:54:31 +01:00
Geoffrey Métais
693b5017a3 Storages: Check mrl format before saving
(cherry picked from commit 338810a06e)
2018-02-19 11:54:31 +01:00
Geoffrey Métais
664cbb6ad9 Video fragment: Avoid useless refresh
(cherry picked from commit 4ef3217793)
2018-02-19 11:54:09 +01:00
Geoffrey Métais
b782d5408a Do not try to publish playback state on destroy
(cherry picked from commit e3f19870e2)
2018-02-19 11:54:09 +01:00
Geoffrey Métais
1dbf788aea Use correct list in video DiffUtil callbacks
(cherry picked from commit e6d7aa7502)
2018-02-16 16:36:33 +01:00
Geoffrey Métais
2ae98f99e0 Bump version to 3.0.1
(cherry picked from commit f74bd90a5a)
2018-02-16 15:20:31 +01:00
Geoffrey Métais
fd89c16a05 Update VLC HASH
(cherry picked from commit 4aa65b7232)
2018-02-16 15:20:31 +01:00
Geoffrey Métais
594a0c8479 Update NEWS 2018-02-16 15:20:03 +01:00
Geoffrey Métais
2b436fb557 Show real SDCard/USB storage name
Works only for Android 6+

Close #464

(cherry picked from commit 5c7e37ccd6)
2018-02-16 14:56:53 +01:00
Geoffrey Métais
01fca5d2f8 Fix renderers dialog layout
(cherry picked from commit 588c521d6c)
2018-02-15 16:10:57 +01:00
Geoffrey Métais
5fce552a8a Fix logic fail in video playback restoration
(cherry picked from commit 04b12baa26)
2018-02-15 14:51:34 +01:00
Geoffrey Métais
cecf7b489c Fix history media uri encoding 2018-02-15 14:15:19 +01:00
Geoffrey Métais
c04710ce98 Subs dl: Do not show fails if a language succeeds
(cherry picked from commit 632ad6e1d1)
2018-02-15 12:19:34 +01:00
Geoffrey Métais
470ee065ff Auto-Retry on subs download fail 2018-02-15 12:10:12 +01:00
Geoffrey Métais
5dd734a84c Fix videoplayer controls visibility on RTL devices
(cherry picked from commit 16ea561c5a)
2018-02-15 10:57:28 +01:00
Geoffrey Métais
c7b1f739f2 Temporary fix for French strings 2018-02-14 17:41:11 +01:00
Geoffrey Métais
2360517f2e Add an option to disable remote ctrl shortcuts
(cherry picked from commit 5a714e40bf)
2018-02-14 17:36:03 +01:00
Geoffrey Métais
721d85246b Do not require audiofocus when rendering
(cherry picked from commit 117db707bc)
2018-02-14 17:36:03 +01:00
Geoffrey Métais
2015dbef4e Reduce TV cards size
(cherry picked from commit dd9e613668)
2018-02-14 16:57:21 +01:00
Geoffrey Métais
8e8696f11d Browsers: use StringBuilder for folder description
(cherry picked from commit b4abf53a4a)
2018-02-14 16:56:49 +01:00
Geoffrey Métais
3569c2d410 Browsers: Fix directories preparsing
(cherry picked from commit 204e2d2ade)
2018-02-14 16:56:49 +01:00
Geoffrey Métais
08b3551d83 VideoListAdapter: Avoid NPE
(cherry picked from commit 879998f0e6)
2018-02-14 16:56:49 +01:00
Geoffrey Métais
3a408aed94 Allow audio titles to show on 2 lines
(cherry picked from commit 918d874eda)
2018-02-14 16:56:49 +01:00
Geoffrey Métais
8d1c52f5fa Avoid unnecessary updates
(cherry picked from commit 2bcb8ed0b6)
2018-02-14 16:56:24 +01:00
Geoffrey Métais
3fa8735553 Keep playbackservice foreground during phone calls
As audio focus loss is only transient, there is no reason to remove
service from foreground

(cherry picked from commit ce42f46371)
2018-02-14 16:56:24 +01:00
Geoffrey Métais
c7a4fab1fd Add media length to description
(cherry picked from commit 5dc7a3f39a)
2018-02-14 16:56:24 +01:00
Alexandre Perraud
5a0541de42 Resize renderer background image
(cherry picked from commit e6def1b6e4)
2018-02-14 16:56:24 +01:00
Geoffrey Métais
82844b852d PlaylistManager: code cleaning
(cherry picked from commit ad2f5322b2)
2018-02-14 16:55:40 +01:00
Geoffrey Métais
cb6994e597 Fix shuffle mode being systematically erased
(cherry picked from commit 19c480506a)
2018-02-14 16:55:40 +01:00
Geoffrey Métais
1edbc1cab4 Fix crash after phone call
(cherry picked from commit 94b38b61eb)
2018-02-14 16:55:40 +01:00
Geoffrey Métais
011e872e74 Hide option icons on filtering
Leave the whole action bar empty for filter edit text.

(cherry picked from commit 97b402e9d3)
2018-02-14 16:55:40 +01:00
Geoffrey Métais
ec342b73f3 Fix renderers dialog
(cherry picked from commit 8079f20aeb)
2018-02-14 16:55:40 +01:00
Geoffrey Métais
21ca209561 Fix playlist clear on video player resumed
(cherry picked from commit 92a9efb3bf)
2018-02-14 16:55:40 +01:00
Geoffrey Métais
7bb86946ce Execute update on hidden state change
(cherry picked from commit 1e59c419a0)
2018-02-14 16:53:57 +01:00
Geoffrey Métais
73c2214b5a Do not update video list while ML is working
(cherry picked from commit afe6a92290)
2018-02-14 16:53:57 +01:00
Geoffrey Métais
32866f8718 Use correct list for current fragment update
(cherry picked from commit e57e524788)
2018-02-14 16:53:57 +01:00
Geoffrey Métais
f956b4869b Get device directories with current context
(cherry picked from commit 500289eba3)
2018-02-14 16:53:57 +01:00
Geoffrey Métais
65716ff340 Upgrade ConstraintLayout
(cherry picked from commit 642768da2d)
2018-02-09 09:24:50 +01:00
Geoffrey Métais
845a4c1f93 PlaybackService: safer way to access app context
(cherry picked from commit c70ae7c773)
2018-02-09 09:21:36 +01:00
Geoffrey Métais
6d9331353f Update licence to 2018
(cherry picked from commit e5c8994c69)
2018-02-08 18:06:38 +01:00
124 changed files with 1478 additions and 661 deletions

66
NEWS
View File

@@ -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:
----------------------------------

View 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

View 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

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"
}
}
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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), ".-_~/()&!$*+,;='@:");
}
}

View File

@@ -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" />

View File

@@ -9,7 +9,7 @@
<body id="top" style="background-color: #EBEBEE">
<h1>VLC for Android</h1>
<p>Copyleft &copy; 1996-2017 VideoLAN, VLC authors</p>
<p>Copyleft &copy; 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>

View File

@@ -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"',

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 B

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 B

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 494 B

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 B

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 B

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 322 B

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 B

After

Width:  |  Height:  |  Size: 352 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 B

After

Width:  |  Height:  |  Size: 352 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 B

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 322 B

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 B

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 366 B

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 366 B

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 B

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 485 B

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 487 B

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 570 B

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 571 B

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View 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>

View 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>

View 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>

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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">

View File

@@ -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>

View File

@@ -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"/>

View File

@@ -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>

View File

@@ -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"> &lt;a href=&quot;http://www.videolan.org/vlc/&quot;&gt;http://www.videolan.org/vlc/&lt;/a&gt;</string>
<string name="about_link" translatable="false"> &lt;a href=&quot;https://www.videolan.org/vlc/&quot;&gt;https://www.videolan.org/vlc/&lt;/a&gt;</string>
<string name="about_copyright" translatable="false">Copyleft &#169; 1996&#8211;2018 by VideoLAN.\n</string>
<string name="authors" translatable="false">Edward&#160;Wang, Sébastien&#160;Toque, Adrien&#160;Maglo, Jean-Baptiste&#160;Kempf, Ludovic&#160;Fauvet, Rafaël&#160;Carré, Alexandre&#160;Perraud, Michael&#160;Merg, Martin&#160;Storsjö, Rémi&#160;Duraffort, Dominique&#160;Martinet, Jean-Philippe&#160;André, Felix&#160;Abecassis, Christoph&#160;Miebach, Hugo&#160;Beauzée-Luyssen, Felix&#160;Paul&#160;Kühne, John&#160;Mooring, Pavol&#160;Rusnak, Rohit&#160;Yadav, Tanguy&#160;Pruvot, Thomas&#160;Clavier, Asad&#160;Mehmood, Garret&#160;Kelly, Philipp&#160;Dreimann, Walter&#160;Heck, Thomas&#160;Guillem, Geoffrey&#160;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>

View File

@@ -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>

View File

@@ -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"

View File

@@ -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"

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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();
}

View File

@@ -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)

View File

@@ -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));
}

View File

@@ -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);

View File

@@ -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()]);
}

View File

@@ -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() {

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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() {

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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
}

Some files were not shown because too many files have changed in this diff Show More