Skip to content

Commit 2b019c8

Browse files
authored
v4 (cast to device, additional vlc helper methods, bug fixes)
1 parent af3373d commit 2b019c8

File tree

21 files changed

+2073
-460
lines changed

21 files changed

+2073
-460
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,5 @@ app.*.symbols
114114
!**/ios/**/default.pbxuser
115115
!**/ios/**/default.perspectivev3
116116
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
117-
!/dev/ci/**/Gemfile.lock
117+
!/dev/ci/**/Gemfile.lock
118+
/example/ios/Runner.xcodeproj/project.pbxproj

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## 4.0.0
2+
* Improved structure (see example for breaking changes). Example code updated also.
3+
* Fix android black screen issue
4+
* Support playing local media/subtitle file
5+
* Support casting media to external device
6+
* Updated changing audio/subtitle method
7+
* Support audio/subtitle delay
8+
credits to Alireza Setayesh (https://github.com/alr2413) and Mitch Ross (https://github.com/mitchross)
9+
110
## 3.0.7
211
* Updates MobileVLC to allow for changing of subtitles and adding subtiles .
312
credits to @rikaweb(https://github.com/rikaweb) and Mitch Ross (https://github.com/mitchross)

README.md

Lines changed: 242 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,55 @@
11
# VLC Player Plugin
22
A VLC-powered alternative to Flutter's video_player that supports iOS and Android.
33

4-
<img src="https://github.com/solid-software/flutter_vlc_player/blob/master/imgpsh_mobile_save.jfif?raw=true" width="200">
4+
<p float="left">
5+
<img src="img_example_v4.jpg" height="400">
6+
<img src="imgpsh_mobile_save.jfif?raw=true" height="400">
7+
</p>
8+
9+
510

611
## Installation
712

8-
### Version 3.0 Upgrade For Existing Apps
9-
For migration to version 3, the project is based in swift. Your existing project will need to migratate
13+
### Version 4.0 Upgrade For Existing Apps
14+
To upgrade to version 4.0 (or v3.0), first you need to migrate the existing project to swift.
1015

1116
Delete existing ios folder from root of flutter project.
1217
Run this command flutter create -i swift .
1318

1419
This command will create only ios directory with swift support. See https://stackoverflow.com/questions/52244346/how-to-enable-swift-support-for-existing-project-in-flutter
1520

16-
Change your project to use 9.0
17-
# Uncomment this line to define a global platform for your project
18-
platform :ios, '9.0'
21+
<hr>
22+
23+
## Breaking Changes (from V3 to V4)
24+
1) Player Stop/Pause status is seperated
25+
26+
previously (v3 and lower): Stop/Pause -> STOPPED,
27+
<br>
28+
now (v4): Stop -> STOPPED and Pause -> PAUSED.
29+
30+
2) Refactored belowing attributes & methods
1931

32+
// attributes
33+
<br>
34+
audioCount -> audioTracksCount
35+
<br>
36+
activeAudioNum -> activeAudioTrack
37+
<br>
38+
subtitleCount -> spuTracksCount
39+
<br>
40+
activeSubtitleNum -> activeSpuTrack
41+
<br>
42+
<br>
43+
// methods
44+
<br>
45+
changeSound(int audioNumber) -> setAudioTrack(int audioTrackNumber)
46+
<br>
47+
changeSubtitle(int subtitleNumber) -> setSpuTrack(int spuTrackNumber)
48+
<br>
49+
addSubtitle(String filePath) -> addSubtitleTrack(String subtitlePath, ...)
50+
51+
52+
<hr>
2053

2154
### iOS
2255
For iOS, you need to opt into the Flutter embedded views preview.
@@ -44,8 +77,21 @@ Make sure that following line in `<project root>/ios/Podfile` uncommented:
4477
> NOTE: While the Flutter `video_player` is not functional on iOS Simulators, this package (`flutter_vlc_player`) **is**
4578
> fully functional on iOS simulators.
4679
80+
To enable vlc cast functionality for external displays (chromecast), you should also add the following:
81+
82+
```xml
83+
<key>NSLocalNetworkUsageDescription</key>
84+
<string>Used to search for chromecast devices</string>
85+
<key>NSBonjourServices</key>
86+
<array>
87+
<string>_googlecast._tcp</string>
88+
</array>
89+
```
90+
91+
<hr>
92+
4793
### Android
48-
To load media from an internet source, your app will need the `INTERNET` permission.
94+
To load media/subitle from an internet source, your app will need the `INTERNET` permission.
4995
This is done by ensuring your `<project root>/android/app/src/main/AndroidManifest.xml` file contains a `uses-permission`
5096
declaration for `android.permission.INTERNET`:
5197
```xml
@@ -54,6 +100,25 @@ declaration for `android.permission.INTERNET`:
54100

55101
As Flutter includes this permission by default, the permission is likely already declared in the file.
56102

103+
Note that if you got "Cleartext HTTP traffic to * is not permitted"
104+
you need to add the `android:usesClearTextTraffic="true"` flag in the AndroidManifest.xml file, or define a new "Network Security Configuration" file. For more information, check https://developer.android.com/training/articles/security-config
105+
106+
<br>
107+
108+
In order to load media/subtitle from internal device storage, you should put the storage permissions as follows:
109+
```xml
110+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
111+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
112+
```
113+
In some cases you also need to add the `android:requestLegacyExternalStorage="true"` flag to the Application tag in AndroidManifest.xml file.
114+
115+
After that you can access the media/subtitle file by
116+
117+
"/storage/emulated/0/{FilePath}"
118+
"/sdcard/{FilePath}"
119+
120+
<hr>
121+
57122
## Quick Start
58123
To start using the plugin, copy this code or follow the [example](https://github.com/solid-software/flutter_vlc_player/tree/master/example):
59124

@@ -116,19 +181,48 @@ Container(
116181
/// VlcPlayer widget.
117182
const VlcPlayer({
118183
Key key,
184+
119185
/// The [VlcPlayerController] that handles interaction with the platform code.
120186
@required this.controller,
187+
121188
/// The aspect ratio used to display the video.
122189
/// This MUST be provided, however it could simply be (parentWidth / parentHeight) - where parentWidth and
123190
/// parentHeight are the width and height of the parent perhaps as defined by a LayoutBuilder.
124191
@required this.aspectRatio,
192+
125193
/// This is the initial URL for the content. This also must be provided but [VlcPlayerController] implements
126194
/// [VlcPlayerController.setStreamUrl] method so this can be changed at any time.
127195
@required this.url,
196+
197+
/// Set hardware acceleration for player. Default is Automatic.
198+
this.hwAcc,
199+
200+
/// Adds options to vlc. For more [https://wiki.videolan.org/VLC_command-line_help] If nothing is provided,
201+
/// vlc will run without any options set.
202+
this.options,
203+
204+
/// Set true if the provided url is local file
205+
this.isLocalMedia,
206+
207+
/// The video should be played automatically.
208+
this.autoplay,
209+
210+
/// Set the external subtitle to load with video
211+
this.subtitle,
212+
213+
/// Set true if the provided subtitle is local file
214+
this.isLocalSubtitle,
215+
216+
/// Set true if the provided subtitle is selected by default
217+
this.isSubtitleSelected,
218+
219+
/// Loop the playback forever
220+
this.loop,
221+
128222
/// Before the platform view has initialized, this placeholder will be rendered instead of the video player.
129223
/// This can simply be a [CircularProgressIndicator] (see the example.)
130224
this.placeholder,
131-
});
225+
});
132226
```
133227

134228
```dart
@@ -137,7 +231,11 @@ VlcPlayerController({
137231
/// This is a callback that will be executed once the platform view has been initialized.
138232
/// If you want the media to play as soon as the platform view has initialized, you could just call
139233
/// [VlcPlayerController.play] in this callback. (see the example)
140-
VoidCallback onInit
234+
VoidCallback onInit,
235+
236+
/// This is a callback that will be executed every time a new cast device detected/removed
237+
/// It should be defined as "void Function(CastStatus, String, String)", where the CastStatus is an enum { DEVICE_ADDED, DEVICE_DELETED } and the next two String arguments are name and displayName of cast device, respectively.
238+
CastCallback onCastHandler
141239
}){
142240
143241
/*** PROPERTIES (Getters) ***/
@@ -155,6 +253,8 @@ VlcPlayerController({
155253
/// - PlayingState.PLAYING
156254
/// - PlayingState.BUFFERING
157255
/// - PlayingState.STOPPED
256+
/// - PlayingState.PAUSED
257+
/// - PlayingState.ERROR
158258
/// - null (When the player is uninitialized)
159259
PlayingState playingState;
160260
@@ -168,8 +268,8 @@ VlcPlayerController({
168268
int duration = Duration.zero;
169269
170270
/// This is the dimensions of the content (height and width).
171-
/// (SAFE) This value is always safe to use - it is set to Size.zero when the player is uninitialized.
172-
Size size = Size.zero;
271+
/// (SAFE) This value is always safe to use - it is set to VlcMediaSize.zero when the player is uninitialized.
272+
VlcMediaSize size = VlcMediaSize.zero;
173273
174274
/// This is the aspect ratio of the content as returned by VLC once the content has been loaded.
175275
/// (Not to be confused with the aspect ratio provided to the [VlcPlayer] widget, which is simply used for an
@@ -180,19 +280,55 @@ VlcPlayerController({
180280
/// at which VLC is playing the content has changed.)
181281
double playbackSpeed;
182282
283+
/// Returns the number of available audio tracks embedded in media except the original audio.
284+
int audioTracksCount;
285+
286+
/// Returns the active audio track index. "-1" means audio is disabled.
287+
int activeAudioTrack;
288+
289+
/// Returns the number of available subtitle tracks embedded in media.
290+
int spuTracksCount;
291+
292+
/// Returns the active subitlte track index. "-1" means subitle is disabled.
293+
int activeSpuTrack;
294+
183295
/*** METHODS ***/
184-
/// [url] - the URL of the stream to start playing.
185296
/// This stops playback and changes the URL. Once the new URL has been loaded, the playback state will revert to
186297
/// its state before the method was called. (i.e. if setStreamUrl is called whilst media is playing, once the new
187298
/// URL has been loaded, the new stream will begin playing.)
188-
Future<void> setStreamUrl(String url);
299+
/// [url] - the URL of the stream to start playing.
300+
/// [isLocalMedia] - Set true if the media url is on local storage.
301+
/// [subtitle] - Set subtitle url if you wanna add subtitle on media loading.
302+
/// [isLocalSubtitle] - Set true if subtitle is on local storage
303+
/// [isSubtitleSelected] - Set true if you wanna force the added subtitle to start display on media.
304+
Future<void> setStreamUrl(String url, {bool isLocalMedia, String subtitle, bool isLocalSubtitle, bool isSubtitleSelected});
189305
306+
/// Start playing media.
190307
Future<void> play();
308+
309+
/// Pause media player.
191310
Future<void> pause();
311+
312+
/// Stop media player.
192313
Future<void> stop();
193314
315+
/// Returns true if media is playing.
316+
Future<bool> isPlaying();
317+
194318
/// [time] - time in milliseconds to jump to.
195319
Future<void> setTime(int time);
320+
321+
/// Returns current media seek time in milliseconds.
322+
Future<int> getTime();
323+
324+
/// Returns duration/length of loaded video in milliseconds.
325+
Future<int> getDuration();
326+
327+
/// [volume] - Set vlc volume level which should be in range [0-100].
328+
Future<void> setVolume(int volume);
329+
330+
/// Returns current vlc volume level.
331+
Future<int> getVolume();
196332
197333
/// [speed] - the rate at which VLC should play media.
198334
/// For reference:
@@ -201,11 +337,103 @@ VlcPlayerController({
201337
/// 0.5 is half speed.
202338
Future<void> setPlaybackSpeed(double speed);
203339
340+
/// Returns the vlc playback speed.
341+
Future<double> getPlaybackSpeed();
342+
343+
/// Return the number of subtitle tracks (both embedded and inserted)
344+
Future<int> getSpuTracksCount();
345+
346+
/// Return all subtitle tracks as array of <Int, String>
347+
/// The key parameter is the index of subtitle which is used for changing subtitle and the value is the display name of subtitle
348+
Future<Map<dynamic, dynamic>> getSpuTracks();
349+
350+
/// [spuTrackNumber] - the subtitle index obtained from getSpuTracks()
351+
/// Change active subtitle index (set -1 to disable subtitle).
352+
Future<void> setSpuTrack(int spuTrackNumber);
353+
354+
/// Returns selected spu track index
355+
Future<int> getSpuTrack();
356+
357+
/// [delay] - the amount of time in milliseconds which vlc subtitle should be delayed. (both positive & negative value appliable)
358+
Future<void> setSpuDelay(int delay);
359+
360+
/// Returns the amount of subtitle time delay.
361+
Future<int> getSpuDelay();
362+
363+
364+
/// [subtitlePath] - URL of subtitle
365+
/// [isLocalSubtitle] - Set true if subtitle is on local storage
366+
/// [isSubtitleSelected] - Set true if you wanna force the added subtitle to start display on media.
367+
/// Add extra subtitle to media.
368+
Future<void> addSubtitleTrack(String subtitlePath,
369+
{bool isLocalSubtitle, bool isSubtitleSelected});
370+
371+
/// Returns the number of audio tracks
372+
Future<int> getAudioTracksCount();
373+
374+
/// Returns all audio tracks as array of <Int, String>
375+
/// The key parameter is the index of audio track which is used for changing audio and the value is the display name of audio
376+
Future<Map<dynamic, dynamic>> getAudioTracks();
377+
378+
/// Returns selected audio track index
379+
Future<int> getAudioTrack();
380+
381+
/// [audioTrackNumber] - the audio track index obtained from getAudioTracks()
382+
/// Change active audio track index (set -1 to mute).
383+
Future<void> setAudioTrack(int audioTrackNumber);
384+
385+
/// [delay] - the amount of time in milliseconds which vlc audio should be delayed. (both positive & negative value appliable)
386+
Future<void> setAudioDelay(int delay);
387+
388+
/// Returns the amount of audio track time delay.
389+
Future<int> getAudioDelay();
390+
391+
/// Returns the number of video tracks
392+
Future<int> getVideoTracksCount();
393+
394+
/// Returns all video tracks as array of <Int, String>
395+
/// The key parameter is the index of video track and the value is the display name of video track
396+
Future<Map<dynamic, dynamic>> getVideoTracks();
397+
398+
/// Returns an object which contains information about current video track
399+
Future<dynamic> getCurrentVideoTrack();
400+
401+
/// Returns selected video track index
402+
Future<int> getVideoTrack();
403+
404+
/// [scale] - the video scale value
405+
/// Set video scale
406+
Future<void> setVideoScale(double scale);
407+
408+
/// Returns video scale
409+
Future<double> getVideoScale();
410+
411+
/// [aspect] - the video apect ratio like "16:9"
412+
/// Set video aspect ratio
413+
Future<void> setVideoAspectRatio(String aspect);
414+
415+
/// Returns video aspect ratio
416+
Future<String> getVideoAspectRatio();
417+
204418
/// Returns binary data for a snapshot of the media at the current frame.
205419
Future<Uint8List> takeSnapshot();
206420
421+
/// Start vlc cast discovery to find external display devices (chromecast)
422+
Future<void> startCastDiscovery();
423+
424+
/// Stop vlc cast and cast discovery
425+
Future<void> stopCastDiscovery();
426+
427+
/// Returns all detected cast devices as array of <String, String>
428+
/// The key parameter is the name of cast device and the value is the display name of cast device
429+
Future<Map<dynamic, dynamic>> getCastDevices();
430+
431+
/// [castDevice] - name of cast device
432+
/// Start vlc video casting to the selected device. Set null if you wanna to stop video casting.
433+
Future<void> startCasting(String castDevice);
434+
207435
/// Disposes the platform view and unloads the VLC player.
208-
void dispose();
436+
Future<void> dispose();
209437
210438
}
211439
```

0 commit comments

Comments
 (0)