Skip to content

Commit

Permalink
feat: Get video duration from chromecast native plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
kashifalaliwala-simformsolutions committed Apr 15, 2021
1 parent fbe8299 commit 8819c99
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.google.android.gms.cast.framework.CastButtonFactory
import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.cast.framework.Session
import com.google.android.gms.cast.framework.SessionManagerListener
import com.google.android.gms.cast.framework.media.RemoteMediaClient
import com.google.android.gms.common.api.PendingResult
import com.google.android.gms.common.api.Status
import io.flutter.plugin.common.BinaryMessenger
Expand All @@ -20,7 +21,7 @@ class ChromeCastController(
messenger: BinaryMessenger,
viewId: Int,
context: Context?
) : PlatformView, MethodChannel.MethodCallHandler, SessionManagerListener<Session>, PendingResult.StatusListener {
) : PlatformView, MethodChannel.MethodCallHandler, SessionManagerListener<Session>, PendingResult.StatusListener, RemoteMediaClient.ProgressListener {
private val channel = MethodChannel(messenger, "flutter_video_cast/chromeCast_$viewId")
private val chromeCastButton = MediaRouteButton(ContextThemeWrapper(context, R.style.Theme_AppCompat_NoActionBar))
private val sessionManager = CastContext.getSharedInstance()?.sessionManager
Expand All @@ -36,6 +37,7 @@ class ChromeCastController(
val media = MediaInfo.Builder(url).build()
val options = MediaLoadOptions.Builder().build()
val request = sessionManager?.currentCastSession?.remoteMediaClient?.load(media, options)
sessionManager?.currentCastSession?.remoteMediaClient?.addProgressListener(this, 1000)
request?.addStatusListener(this)
}
}
Expand Down Expand Up @@ -122,6 +124,7 @@ class ChromeCastController(
result.success(null)
}
"chromeCast#stopCasting" -> {
sessionManager?.currentCastSession?.remoteMediaClient?.removeProgressListener(this)
sessionManager?.endCurrentSession(true)
result.success(null)
}
Expand Down Expand Up @@ -173,4 +176,11 @@ class ChromeCastController(
channel.invokeMethod("chromeCast#requestDidComplete", null)
}
}

override fun onProgressUpdated(progress: Long, duration: Long) {
val data = HashMap<String, String>()
data[DURATION] = duration.toString()
data[PROGRESS] = progress.toString()
channel.invokeMethod("chromeCast#getVideoProgress", data)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package it.aesys.flutter_video_cast

const val DURATION = "duration"
const val PROGRESS = "progress"
2 changes: 1 addition & 1 deletion example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c

COCOAPODS: 1.9.2
COCOAPODS: 1.9.1
3 changes: 0 additions & 3 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ class _CastSampleState extends State<CastSample> {
}

Future<void> _onRequestCompleted() async {
print('_onRequestCompleted');
final playing = await _controller.isPlaying();
setState(() {
_state = AppState.mediaLoaded;
Expand All @@ -135,8 +134,6 @@ class _CastSampleState extends State<CastSample> {
}

Future<void> _onRequestFailed(String error) async {
print('_onRequestFailed');

setState(() => _state = AppState.error);
print(error);
}
Expand Down
17 changes: 16 additions & 1 deletion ios/Classes/ChromeCastController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Flutter
import GoogleCast

class ChromeCastController: NSObject, FlutterPlatformView {
class ChromeCastController: NSObject, FlutterPlatformView, GCKRemoteMediaClientListener {

// MARK: - Internal properties

Expand Down Expand Up @@ -104,6 +104,10 @@ class ChromeCastController: NSObject, FlutterPlatformView {
case "chromeCast#removeSessionListener":
removeSessionListener()
result(nil)
case "chromeCast#stopCasting":
sessionManager.currentCastSession?.remoteMediaClient?.remove(self)
sessionManager.endSession()
result(nil)
default:
result(nil)
break
Expand All @@ -122,8 +126,19 @@ class ChromeCastController: NSObject, FlutterPlatformView {
if let request = sessionManager.currentCastSession?.remoteMediaClient?.loadMedia(mediaInformation) {
request.delegate = self
}
sessionManager.currentCastSession?.remoteMediaClient?.add(self)
}

public func remoteMediaClient(_ client: GCKRemoteMediaClient, didUpdate mediaStatus: GCKMediaStatus?) {
if let mediaStatusPosition = mediaStatus?.streamPosition, let duration = mediaStatus?.mediaInformation?.streamDuration {
channel.invokeMethod("chromeCast#getVideoProgress", arguments: [
"position": String(mediaStatusPosition * 1000),
"duration": String(duration * 1000)
])
}

}

private func play() {
if let request = sessionManager.currentCastSession?.remoteMediaClient?.play() {
request.delegate = self
Expand Down
1 change: 1 addition & 0 deletions lib/flutter_video_cast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/material.dart';

import 'package:flutter_video_cast/src/chrome_cast/chrome_cast_platform.dart';
import 'package:flutter_video_cast/src/air_play/air_play_platform.dart';
import 'package:flutter_video_cast/src/chrome_cast/video_progress_model.dart';

part 'src/chrome_cast/chrome_cast_controller.dart';
part 'src/chrome_cast/chrome_cast_button.dart';
Expand Down
4 changes: 4 additions & 0 deletions lib/src/chrome_cast/chrome_cast_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ class ChromeCastController {
return _chromeCastPlatform.stopCasting(id: id);
}

Stream<VideoProgress> getVideoProgress() {
return _chromeCastPlatform.progressStreamEvents;
}

/// Returns `true` when a cast session is connected, `false` otherwise.
Future<bool> isConnected() {
return _chromeCastPlatform.isConnected(id: id);
Expand Down
3 changes: 3 additions & 0 deletions lib/src/chrome_cast/chrome_cast_platform.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_video_cast/src/chrome_cast/chrome_cast_event.dart';
import 'package:flutter_video_cast/src/chrome_cast/method_channel_chrome_cast.dart';
import 'package:flutter_video_cast/src/chrome_cast/video_progress_model.dart';

/// The interface that platform-specific implementations of `flutter_video_cast` must extend.
abstract class ChromeCastPlatform {
Expand All @@ -12,6 +13,8 @@ abstract class ChromeCastPlatform {
/// Defaults to [MethodChannelChromeCast].
static get instance => _instance;

Stream<VideoProgress> get progressStreamEvents;

/// Initializes the platform interface with [id].
///
/// This method is called when the plugin is first initialized.
Expand Down
12 changes: 12 additions & 0 deletions lib/src/chrome_cast/method_channel_chrome_cast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_video_cast/src/chrome_cast/chrome_cast_event.dart';
import 'package:flutter_video_cast/src/chrome_cast/chrome_cast_platform.dart';
import 'package:flutter_video_cast/src/chrome_cast/video_progress_model.dart';
import 'package:stream_transform/stream_transform.dart';

/// An implementation of [ChromeCastPlatform] that uses [MethodChannel] to communicate with the native code.
Expand All @@ -25,10 +26,17 @@ class MethodChannelChromeCast extends ChromeCastPlatform {
// different stream views of this Controller.
final _eventStreamController = StreamController<ChromeCastEvent>.broadcast();

final _progressStreamController = StreamController<VideoProgress>.broadcast();

// Returns a filtered view of the events in the _controller, by id.
Stream<ChromeCastEvent> _events(int id) =>
_eventStreamController.stream.where((event) => event.id == id);

@override
Stream<VideoProgress> get progressStreamEvents =>
_progressStreamController.stream;


@override
Future<void> init(int id) {
MethodChannel channel;
Expand Down Expand Up @@ -130,6 +138,10 @@ class MethodChannelChromeCast extends ChromeCastPlatform {
_eventStreamController
.add(RequestDidFailEvent(id, call.arguments['error']));
break;
case 'chromeCast#getVideoProgress':
var progress = VideoProgress.fromJson(call.arguments.cast<String,String>());
_progressStreamController.sink.add(VideoProgress.fromJson(call.arguments.cast<String,String>()));
break;
default:
throw MissingPluginException();
}
Expand Down
13 changes: 13 additions & 0 deletions lib/src/chrome_cast/video_progress_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class VideoProgress {
Duration currentProgress;
Duration videoDuration;

VideoProgress({this.currentProgress, this.videoDuration});

VideoProgress.fromJson(Map<String, String> map) {
currentProgress =
Duration(milliseconds: double.parse(map['progress']).toInt());
videoDuration =
Duration(milliseconds: double.parse(map['duration']).toInt());
}
}

0 comments on commit 8819c99

Please sign in to comment.