Skip to content

Commit aa10224

Browse files
Added isSeekable method (#175)
* fixed dart deprecation warning added the missing async await to some platform methods * updated example code * fixed dart deprecation warning added the missing async await to some platform methods * updated example code * added isSeekable method fix example player widget crash if the media position becomes greater than the media duration * fixed dart deprecation warning added the missing async await to some platform methods * updated example code * revert back seekto method * updated pubspec and changelog * 5.0.4 release / readme and changelog * Update flutter_vlc_player/ios/Classes/SwiftFlutterVlcPlayerPlugin.swift Co-authored-by: Yuri Prykhodko <[email protected]> * Update flutter_vlc_player/android/src/main/java/software/solid/fluttervlcplayer/FlutterVlcPlayer.java Co-authored-by: Yuri Prykhodko <[email protected]> * update example code Co-authored-by: Yuri Prykhodko <[email protected]>
1 parent 3abeab6 commit aa10224

File tree

18 files changed

+482
-319
lines changed

18 files changed

+482
-319
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ class _MyHomePageState extends State<MyHomePage> {
127127
@override
128128
void dispose() async {
129129
super.dispose();
130-
_videoPlayerController.removeListener(() {});
131130
await _videoPlayerController.stopRendererScanning();
132131
await _videoViewController.dispose();
133132
}

flutter_vlc_player/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 5.0.4
2+
Added isSeekable method
3+
Credits to Alireza Setayesh (https://github.com/alr2413), Mitch Ross (https://github.com/mitchross).
4+
15
## 5.0.3
26
Fix memory leak.
37
Credits to Alireza Setayesh (https://github.com/alr2413), Mitch Ross (https://github.com/mitchross).

flutter_vlc_player/android/src/main/java/software/solid/fluttervlcplayer/FlutterVlcPlayer.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,10 @@ boolean isPlaying() {
320320
return mediaPlayer.isPlaying();
321321
}
322322

323+
boolean isSeekable() {
324+
return mediaPlayer.isSeekable();
325+
}
326+
323327
void setStreamUrl(String url, boolean isAssetUrl, boolean autoPlay, long hwAcc) {
324328
try {
325329
mediaPlayer.stop();
@@ -595,9 +599,9 @@ HashMap<String, String> getRendererDevices() {
595599
}
596600

597601
void castToRenderer(String rendererDevice) {
598-
if(isDisposed)
602+
if (isDisposed) {
599603
return;
600-
//
604+
}
601605
boolean isPlaying = mediaPlayer.isPlaying();
602606
if (isPlaying)
603607
mediaPlayer.pause();

flutter_vlc_player/android/src/main/java/software/solid/fluttervlcplayer/FlutterVlcPlayerBuilder.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@ public Messages.BooleanMessage isPlaying(Messages.TextureMessage arg) {
133133
return message;
134134
}
135135

136+
@Override
137+
public Messages.BooleanMessage isSeekable(Messages.TextureMessage arg) {
138+
FlutterVlcPlayer player = vlcPlayers.get(arg.getTextureId());
139+
Messages.BooleanMessage message = new Messages.BooleanMessage();
140+
message.setResult(player.isSeekable());
141+
return message;
142+
}
143+
136144
@Override
137145
public void setLooping(Messages.LoopingMessage arg) {
138146
FlutterVlcPlayer player = vlcPlayers.get(arg.getTextureId());

flutter_vlc_player/android/src/main/java/software/solid/fluttervlcplayer/Messages.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,7 @@ public interface VlcPlayerApi {
783783
void pause(TextureMessage arg);
784784
void stop(TextureMessage arg);
785785
BooleanMessage isPlaying(TextureMessage arg);
786+
BooleanMessage isSeekable(TextureMessage arg);
786787
void setLooping(LoopingMessage arg);
787788
void seekTo(PositionMessage arg);
788789
PositionMessage position(TextureMessage arg);
@@ -988,6 +989,27 @@ static void setup(BinaryMessenger binaryMessenger, VlcPlayerApi api) {
988989
channel.setMessageHandler(null);
989990
}
990991
}
992+
{
993+
BasicMessageChannel<Object> channel =
994+
new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.VlcPlayerApi.isSeekable", new StandardMessageCodec());
995+
if (api != null) {
996+
channel.setMessageHandler((message, reply) -> {
997+
HashMap<String, HashMap> wrapped = new HashMap<>();
998+
try {
999+
@SuppressWarnings("ConstantConditions")
1000+
TextureMessage input = TextureMessage.fromMap((HashMap)message);
1001+
BooleanMessage output = api.isSeekable(input);
1002+
wrapped.put("result", output.toMap());
1003+
}
1004+
catch (Exception exception) {
1005+
wrapped.put("error", wrapError(exception));
1006+
}
1007+
reply.reply(wrapped);
1008+
});
1009+
} else {
1010+
channel.setMessageHandler(null);
1011+
}
1012+
}
9911013
{
9921014
BasicMessageChannel<Object> channel =
9931015
new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.VlcPlayerApi.setLooping", new StandardMessageCodec());

flutter_vlc_player/example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
1414
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
1515
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
16+
A5B9EA2DCD75D90287B6E40D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37E38E0408878246AA07407B /* Pods_Runner.framework */; };
1617
/* End PBXBuildFile section */
1718

1819
/* Begin PBXCopyFilesBuildPhase section */
@@ -31,9 +32,11 @@
3132
/* Begin PBXFileReference section */
3233
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
3334
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
35+
37E38E0408878246AA07407B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3436
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3537
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
3638
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
39+
7A62D53992769F2B7EDD4676 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
3740
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
3841
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
3942
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
@@ -42,19 +45,41 @@
4245
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
4346
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
4447
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
48+
9E08256A9794662F399FE19C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
49+
AD9A3FE064CAF8F90832C4FF /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
4550
/* End PBXFileReference section */
4651

4752
/* Begin PBXFrameworksBuildPhase section */
4853
97C146EB1CF9000F007C117D /* Frameworks */ = {
4954
isa = PBXFrameworksBuildPhase;
5055
buildActionMask = 2147483647;
5156
files = (
57+
A5B9EA2DCD75D90287B6E40D /* Pods_Runner.framework in Frameworks */,
5258
);
5359
runOnlyForDeploymentPostprocessing = 0;
5460
};
5561
/* End PBXFrameworksBuildPhase section */
5662

5763
/* Begin PBXGroup section */
64+
164104D44CC3C356A215989E /* Pods */ = {
65+
isa = PBXGroup;
66+
children = (
67+
9E08256A9794662F399FE19C /* Pods-Runner.debug.xcconfig */,
68+
AD9A3FE064CAF8F90832C4FF /* Pods-Runner.release.xcconfig */,
69+
7A62D53992769F2B7EDD4676 /* Pods-Runner.profile.xcconfig */,
70+
);
71+
name = Pods;
72+
path = Pods;
73+
sourceTree = "<group>";
74+
};
75+
763DB387735FA98410DE7640 /* Frameworks */ = {
76+
isa = PBXGroup;
77+
children = (
78+
37E38E0408878246AA07407B /* Pods_Runner.framework */,
79+
);
80+
name = Frameworks;
81+
sourceTree = "<group>";
82+
};
5883
9740EEB11CF90186004384FC /* Flutter */ = {
5984
isa = PBXGroup;
6085
children = (
@@ -72,6 +97,8 @@
7297
9740EEB11CF90186004384FC /* Flutter */,
7398
97C146F01CF9000F007C117D /* Runner */,
7499
97C146EF1CF9000F007C117D /* Products */,
100+
164104D44CC3C356A215989E /* Pods */,
101+
763DB387735FA98410DE7640 /* Frameworks */,
75102
);
76103
sourceTree = "<group>";
77104
};
@@ -105,12 +132,14 @@
105132
isa = PBXNativeTarget;
106133
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
107134
buildPhases = (
135+
9DEDE8E0A12A45F8A4FB88C8 /* [CP] Check Pods Manifest.lock */,
108136
9740EEB61CF901F6004384FC /* Run Script */,
109137
97C146EA1CF9000F007C117D /* Sources */,
110138
97C146EB1CF9000F007C117D /* Frameworks */,
111139
97C146EC1CF9000F007C117D /* Resources */,
112140
9705A1C41CF9048500538489 /* Embed Frameworks */,
113141
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
142+
27171385958D77650BE5F644 /* [CP] Embed Pods Frameworks */,
114143
);
115144
buildRules = (
116145
);
@@ -169,6 +198,23 @@
169198
/* End PBXResourcesBuildPhase section */
170199

171200
/* Begin PBXShellScriptBuildPhase section */
201+
27171385958D77650BE5F644 /* [CP] Embed Pods Frameworks */ = {
202+
isa = PBXShellScriptBuildPhase;
203+
buildActionMask = 2147483647;
204+
files = (
205+
);
206+
inputFileListPaths = (
207+
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
208+
);
209+
name = "[CP] Embed Pods Frameworks";
210+
outputFileListPaths = (
211+
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
212+
);
213+
runOnlyForDeploymentPostprocessing = 0;
214+
shellPath = /bin/sh;
215+
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
216+
showEnvVarsInLog = 0;
217+
};
172218
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
173219
isa = PBXShellScriptBuildPhase;
174220
buildActionMask = 2147483647;
@@ -197,6 +243,28 @@
197243
shellPath = /bin/sh;
198244
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
199245
};
246+
9DEDE8E0A12A45F8A4FB88C8 /* [CP] Check Pods Manifest.lock */ = {
247+
isa = PBXShellScriptBuildPhase;
248+
buildActionMask = 2147483647;
249+
files = (
250+
);
251+
inputFileListPaths = (
252+
);
253+
inputPaths = (
254+
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
255+
"${PODS_ROOT}/Manifest.lock",
256+
);
257+
name = "[CP] Check Pods Manifest.lock";
258+
outputFileListPaths = (
259+
);
260+
outputPaths = (
261+
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
262+
);
263+
runOnlyForDeploymentPostprocessing = 0;
264+
shellPath = /bin/sh;
265+
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
266+
showEnvVarsInLog = 0;
267+
};
200268
/* End PBXShellScriptBuildPhase section */
201269

202270
/* Begin PBXSourcesBuildPhase section */

flutter_vlc_player/example/lib/vlc_player_with_controls.dart

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class VlcPlayerWithControlsState extends State<VlcPlayerWithControls>
3737
String duration = '';
3838
int numberOfCaptions = 0;
3939
int numberOfAudioTracks = 0;
40+
bool validPosition = false;
4041

4142
//
4243
List<double> playbackSpeeds = [0.5, 1.0, 2.0];
@@ -76,7 +77,8 @@ class VlcPlayerWithControlsState extends State<VlcPlayerWithControls>
7677
position = oPosition.toString().split('.')[0];
7778
duration = oDuration.toString().split('.')[0];
7879
}
79-
sliderValue = _controller.value.position.inSeconds.toDouble();
80+
validPosition = oDuration.compareTo(oPosition) >= 0;
81+
sliderValue = validPosition ? oPosition.inSeconds.toDouble() : 0;
8082
}
8183
numberOfCaptions = _controller.value.spuTracksCount;
8284
numberOfAudioTracks = _controller.value.audioTracksCount;
@@ -313,16 +315,12 @@ class VlcPlayerWithControlsState extends State<VlcPlayerWithControls>
313315
inactiveColor: Colors.white70,
314316
value: sliderValue,
315317
min: 0.0,
316-
max: _controller.value.duration == null
318+
max: (!validPosition &&
319+
_controller.value.duration == null)
317320
? 1.0
318321
: _controller.value.duration.inSeconds.toDouble(),
319-
onChanged: (progress) {
320-
setState(() {
321-
sliderValue = progress.floor().toDouble();
322-
});
323-
//convert to Milliseconds since VLC requires MS to set time
324-
_controller.setTime(sliderValue.toInt() * 1000);
325-
},
322+
onChanged:
323+
!validPosition ? null : _onSliderPositionChanged,
326324
),
327325
),
328326
Text(
@@ -379,6 +377,14 @@ class VlcPlayerWithControlsState extends State<VlcPlayerWithControls>
379377
);
380378
}
381379

380+
void _onSliderPositionChanged(double progress) {
381+
setState(() {
382+
sliderValue = progress.floor().toDouble();
383+
});
384+
//convert to Milliseconds since VLC requires MS to set time
385+
_controller.setTime(sliderValue.toInt() * 1000);
386+
}
387+
382388
void _getSubtitleTracks() async {
383389
if (!_controller.value.isPlaying) return;
384390

flutter_vlc_player/ios/Classes/SwiftFlutterVlcPlayerPlugin.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ public class VLCViewBuilder: NSObject, VlcPlayerApi{
140140
public func play(_ input: TextureMessage, error: AutoreleasingUnsafeMutablePointer<FlutterError?>) {
141141

142142
let player = getPlayer(textureId: input.textureId)
143+
143144
player?.play()
144145
}
145146

@@ -153,20 +154,28 @@ public class VLCViewBuilder: NSObject, VlcPlayerApi{
153154
public func stop(_ input: TextureMessage, error: AutoreleasingUnsafeMutablePointer<FlutterError?>) {
154155

155156
let player = getPlayer(textureId: input.textureId)
156-
157157

158158
player?.stop()
159159
}
160160

161161
public func isPlaying(_ input: TextureMessage, error: AutoreleasingUnsafeMutablePointer<FlutterError?>) -> BooleanMessage? {
162162

163163
let player = getPlayer(textureId: input.textureId)
164-
164+
165165
let message: BooleanMessage = BooleanMessage()
166166
message.result = player?.isPlaying()
167167
return message
168168
}
169169

170+
public func isSeekable(_ input: TextureMessage, error: AutoreleasingUnsafeMutablePointer<FlutterError?>) -> BooleanMessage? {
171+
172+
let player = getPlayer(textureId: input.textureId)
173+
174+
let message: BooleanMessage = BooleanMessage()
175+
message.result = player?.isSeekable()
176+
return message
177+
}
178+
170179
public func setLooping(_ input: LoopingMessage, error: AutoreleasingUnsafeMutablePointer<FlutterError?>) {
171180

172181
let player = getPlayer(textureId: input.textureId)
@@ -177,7 +186,7 @@ public class VLCViewBuilder: NSObject, VlcPlayerApi{
177186
public func seek(to input: PositionMessage, error: AutoreleasingUnsafeMutablePointer<FlutterError?>) {
178187

179188
let player = getPlayer(textureId: input.textureId)
180-
189+
181190
player?.seek(position: input.position)
182191
}
183192

@@ -520,6 +529,11 @@ public class VLCViewController: NSObject, FlutterPlatformView {
520529
return self.vlcMediaPlayer.isPlaying as NSNumber
521530
}
522531

532+
public func isSeekable() -> NSNumber? {
533+
534+
return self.vlcMediaPlayer.isSeekable as NSNumber
535+
}
536+
523537
public func setLooping(isLooping: NSNumber?) {
524538

525539
let enableLooping = isLooping?.boolValue ?? false;
@@ -1131,4 +1145,3 @@ extension VLCMediaPlayer {
11311145
}
11321146

11331147

1134-

flutter_vlc_player/ios/Classes/messages.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ NS_ASSUME_NONNULL_BEGIN
185185
-(void)pause:(TextureMessage*)input error:(FlutterError *_Nullable *_Nonnull)error;
186186
-(void)stop:(TextureMessage*)input error:(FlutterError *_Nullable *_Nonnull)error;
187187
-(nullable BooleanMessage *)isPlaying:(TextureMessage*)input error:(FlutterError *_Nullable *_Nonnull)error;
188+
-(nullable BooleanMessage *)isSeekable:(TextureMessage*)input error:(FlutterError *_Nullable *_Nonnull)error;
188189
-(void)setLooping:(LoopingMessage*)input error:(FlutterError *_Nullable *_Nonnull)error;
189190
-(void)seekTo:(PositionMessage*)input error:(FlutterError *_Nullable *_Nonnull)error;
190191
-(nullable PositionMessage *)position:(TextureMessage*)input error:(FlutterError *_Nullable *_Nonnull)error;

flutter_vlc_player/ios/Classes/messages.m

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,23 @@ void VlcPlayerApiSetup(id<FlutterBinaryMessenger> binaryMessenger, id<VlcPlayerA
779779
[channel setMessageHandler:nil];
780780
}
781781
}
782+
{
783+
FlutterBasicMessageChannel *channel =
784+
[FlutterBasicMessageChannel
785+
messageChannelWithName:@"dev.flutter.pigeon.VlcPlayerApi.isSeekable"
786+
binaryMessenger:binaryMessenger];
787+
if (api) {
788+
[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
789+
FlutterError *error;
790+
TextureMessage *input = [TextureMessage fromMap:message];
791+
BooleanMessage *output = [api isSeekable:input error:&error];
792+
callback(wrapResult([output toMap], error));
793+
}];
794+
}
795+
else {
796+
[channel setMessageHandler:nil];
797+
}
798+
}
782799
{
783800
FlutterBasicMessageChannel *channel =
784801
[FlutterBasicMessageChannel

0 commit comments

Comments
 (0)