404: Something's gone wrong :-(
+ +You've tried to visit a page that doesn't exist. Luckily this site + has other pages.
+If you were looking for something specific, try searching: +
+ + +diff --git a/Makefile b/Makefile index efa159d..68c7570 100644 --- a/Makefile +++ b/Makefile @@ -19,4 +19,7 @@ open-ios: open example/ios/Runner.xcworkspace run-all: - cd example && flutter run -d all \ No newline at end of file + cd example && flutter run -d all + +docs: + flutter pub run dartdoc --output docs/api \ No newline at end of file diff --git a/README.md b/README.md index 6129e9a..c522c2a 100644 --- a/README.md +++ b/README.md @@ -148,4 +148,3 @@ I used this project to test the capabilities of the following technologies: * Handle progress seek * Handle queue * Handle mini-player -* Produce HTML docs diff --git a/docs/api/__404error.html b/docs/api/__404error.html new file mode 100644 index 0000000..b839f22 --- /dev/null +++ b/docs/api/__404error.html @@ -0,0 +1,104 @@ + + +
+ + + + + +You've tried to visit a page that doesn't exist. Luckily this site + has other pages.
+If you were looking for something specific, try searching: +
+ + +typedef AdBreakClipProgressListener = void Function(
+ String adBreakId,
+ String adBreakClipId,
+ int progressMs,
+ int durationMs,
+ int whenSkippableMs,
+);
+String? adBreakClipId;
+
+
+String? adBreakId;
+
+
+static AdBreakStatus decode(Object message) {
+ final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+ return AdBreakStatus()
+ ..adBreakId = pigeonMap['adBreakId'] as String?
+ ..adBreakClipId = pigeonMap['adBreakClipId'] as String?
+ ..whenSkippableMs = pigeonMap['whenSkippableMs'] as int?;
+}
+Object encode() {
+ final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+ pigeonMap['adBreakId'] = adBreakId;
+ pigeonMap['adBreakClipId'] = adBreakClipId;
+ pigeonMap['whenSkippableMs'] = whenSkippableMs;
+ return pigeonMap;
+}
+int? whenSkippableMs;
+
+
+Class wrapping the global context fot the Cast SDK
+CastContext(this._hostApi);
+Internal method that shouldn't be visible
+@internal
+void onCastStateChanged(int castState) {
+ _stateNotifier.value = CastState.values[castState];
+}
+Returns the SessionManager.
+SessionManager get sessionManager {
+ var result = _sessionManager;
+ if (result == null) {
+ _sessionManager = result = SessionManager(_hostApi);
+ }
+ return result;
+}
+Display the native dialog to select the cast device to connect
+void showCastChooserDialog() {
+ _hostApi.showCastDialog();
+}
+Listenable connection state of the cast device
+ValueListenable<CastState> get state => _stateNotifier;
+static CastDevice decode(Object message) {
+ final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+ return CastDevice()
+ ..deviceId = pigeonMap['deviceId'] as String?
+ ..friendlyName = pigeonMap['friendlyName'] as String?
+ ..modelName = pigeonMap['modelName'] as String?;
+}
+String? deviceId;
+
+
+Object encode() {
+ final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+ pigeonMap['deviceId'] = deviceId;
+ pigeonMap['friendlyName'] = friendlyName;
+ pigeonMap['modelName'] = modelName;
+ return pigeonMap;
+}
+String? friendlyName;
+
+
+String? modelName;
+
+
+static CastMessage decode(Object message) {
+ final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+ return CastMessage()
+ ..namespace = pigeonMap['namespace'] as String?
+ ..message = pigeonMap['message'] as String?;
+}
+Object encode() {
+ final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+ pigeonMap['namespace'] = namespace;
+ pigeonMap['message'] = message;
+ return pigeonMap;
+}
+String? message;
+
+
+String? namespace;
+
+
+The possible casting states.
+A Cast session is established.
+ + +const CastState(4)
+ A Cast session is being established.
+ + +const CastState(3)
+ Cast connection has never been initialized.
+ + +const CastState(0)
+ No Cast devices are available.
+ + +const CastState(1)
+ Cast devices are available, but a Cast session is not established.
+ + +const CastState(2)
+ A constant List of the values in this enum, in order of their declaration.
+ + +const List<CastState>
+ A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse function (like int.parse).
+These classes will provide the textual representation as
+their string represetion.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
Entrypoint for the Flutter Cast Framework
+Create the Flutter Cast Framework. +namespaces is the list of namespaces to listen for custom messages.
+FlutterCastFramework.create(List<String> namespaces) {
+ debugPrint("FlutterCastFramework created!");
+ final castContext = CastContext(_hostApi);
+ this._castFlutterApiImplementor = new _CastFlutterApiImplementor(
+ castContext: castContext,
+ namespaces: namespaces,
+ );
+
+ CastFlutterApi.setup(this._castFlutterApiImplementor);
+}
+Get the entrypoint for the Cast SDK. This is immutable and it is expected to never change.
+CastContext get castContext => _castFlutterApiImplementor.castContext;
+String? contentId;
+
+
+String? contentType;
+
+
+String? customDataAsJson;
+
+
+static MediaInfo decode(Object message) {
+ final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+ return MediaInfo()
+ ..contentId = pigeonMap['contentId'] as String?
+ ..streamType = pigeonMap['streamType'] != null
+ ? StreamType.values[pigeonMap['streamType']! as int]
+ : null
+ ..contentType = pigeonMap['contentType'] as String?
+ ..mediaMetadata = pigeonMap['mediaMetadata'] != null
+ ? MediaMetadata.decode(pigeonMap['mediaMetadata']!)
+ : null
+ ..mediaTracks = (pigeonMap['mediaTracks'] as List<Object?>?)?.cast<MediaTrack?>()
+ ..streamDuration = pigeonMap['streamDuration'] as int?
+ ..customDataAsJson = pigeonMap['customDataAsJson'] as String?;
+}
+Object encode() {
+ final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+ pigeonMap['contentId'] = contentId;
+ pigeonMap['streamType'] = streamType == null ? null : streamType!.index;
+ pigeonMap['contentType'] = contentType;
+ pigeonMap['mediaMetadata'] = mediaMetadata == null ? null : mediaMetadata!.encode();
+ pigeonMap['mediaTracks'] = mediaTracks;
+ pigeonMap['streamDuration'] = streamDuration;
+ pigeonMap['customDataAsJson'] = customDataAsJson;
+ return pigeonMap;
+}
+MediaMetadata? mediaMetadata;
+
+
+List<MediaTrack?>? mediaTracks;
+
+
+int? streamDuration;
+
+
+StreamType? streamType;
+
+
+int? currentTime;
+
+
+static MediaLoadRequestData decode(Object message) {
+ final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+ return MediaLoadRequestData()
+ ..shouldAutoplay = pigeonMap['shouldAutoplay'] as bool?
+ ..currentTime = pigeonMap['currentTime'] as int?
+ ..mediaInfo = pigeonMap['mediaInfo'] != null
+ ? MediaInfo.decode(pigeonMap['mediaInfo']!)
+ : null;
+}
+Object encode() {
+ final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+ pigeonMap['shouldAutoplay'] = shouldAutoplay;
+ pigeonMap['currentTime'] = currentTime;
+ pigeonMap['mediaInfo'] = mediaInfo == null ? null : mediaInfo!.encode();
+ return pigeonMap;
+}
+MediaInfo? mediaInfo;
+
+
+bool? shouldAutoplay;
+
+
+static MediaMetadata decode(Object message) {
+ final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+ return MediaMetadata()
+ ..mediaType = pigeonMap['mediaType'] != null
+ ? MediaType.values[pigeonMap['mediaType']! as int]
+ : null
+ ..webImages = (pigeonMap['webImages'] as List<Object?>?)?.cast<WebImage?>();
+}
+Object encode() {
+ final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+ pigeonMap['mediaType'] = mediaType == null ? null : mediaType!.index;
+ pigeonMap['webImages'] = webImages;
+ return pigeonMap;
+}
+MediaType? mediaType;
+
+
+List<WebImage?>? webImages;
+
+
+AdBreakStatus? adBreakStatus;
+
+
+static MediaStatus decode(Object message) {
+ final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+ return MediaStatus()
+ ..playerState = pigeonMap['playerState'] != null
+ ? PlayerState.values[pigeonMap['playerState']! as int]
+ : null
+ ..isPlayingAd = pigeonMap['isPlayingAd'] as bool?
+ ..mediaInfo = pigeonMap['mediaInfo'] != null
+ ? MediaInfo.decode(pigeonMap['mediaInfo']!)
+ : null
+ ..adBreakStatus = pigeonMap['adBreakStatus'] != null
+ ? AdBreakStatus.decode(pigeonMap['adBreakStatus']!)
+ : null;
+}
+Object encode() {
+ final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+ pigeonMap['playerState'] = playerState == null ? null : playerState!.index;
+ pigeonMap['isPlayingAd'] = isPlayingAd;
+ pigeonMap['mediaInfo'] = mediaInfo == null ? null : mediaInfo!.encode();
+ pigeonMap['adBreakStatus'] = adBreakStatus == null ? null : adBreakStatus!.encode();
+ return pigeonMap;
+}
+bool? isPlayingAd;
+
+
+MediaInfo? mediaInfo;
+
+
+PlayerState? playerState;
+
+
+String? contentId;
+
+
+static MediaTrack decode(Object message) {
+ final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+ return MediaTrack()
+ ..id = pigeonMap['id'] as int?
+ ..trackType = pigeonMap['trackType'] != null
+ ? TrackType.values[pigeonMap['trackType']! as int]
+ : null
+ ..name = pigeonMap['name'] as String?
+ ..trackSubtype = pigeonMap['trackSubtype'] != null
+ ? TrackSubtype.values[pigeonMap['trackSubtype']! as int]
+ : null
+ ..contentId = pigeonMap['contentId'] as String?
+ ..language = pigeonMap['language'] as String?;
+}
+Object encode() {
+ final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+ pigeonMap['id'] = id;
+ pigeonMap['trackType'] = trackType == null ? null : trackType!.index;
+ pigeonMap['name'] = name;
+ pigeonMap['trackSubtype'] = trackSubtype == null ? null : trackSubtype!.index;
+ pigeonMap['contentId'] = contentId;
+ pigeonMap['language'] = language;
+ return pigeonMap;
+}
+int? id;
+
+
+String? language;
+
+
+String? name;
+
+
+TrackSubtype? trackSubtype;
+
+
+TrackType? trackType;
+
+
+const MediaType(5)
+ const MediaType(0)
+ const MediaType(1)
+ const MediaType(3)
+ const MediaType(4)
+ const MediaType(2)
+ const MediaType(6)
+ A constant List of the values in this enum, in order of their declaration.
+ + +const List<MediaType>
+ A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse function (like int.parse).
+These classes will provide the textual representation as
+their string represetion.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
typedef MessageReceivedCallback = void Function(
+ String namespace, String message);
+const PlayerState(4)
+ const PlayerState(1)
+ const PlayerState(5)
+ const PlayerState(3)
+ const PlayerState(2)
+ const PlayerState(0)
+ A constant List of the values in this enum, in order of their declaration.
+ + +const List<PlayerState>
+ A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse function (like int.parse).
+These classes will provide the textual representation as
+their string represetion.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
typedef ProgressListener = void Function(int progressMs, int durationMs);
+Class for controlling a media player application running on a receiver.
+RemoteMediaClient(this._hostApi);
+Internal method that shouldn't be visible
+@internal
+void dispatchPlayerStateUpdate(PlayerState playerState) {
+ this._playerStateNotifier.value = playerState;
+}
+Returns the current media information
+Future<MediaInfo> getMediaInfo() async {
+ // FIXME: can remove future? we could avoid to call host and rely on listener callbacks (maybe onMetadataUpdated)
+ return await _hostApi.getMediaInfo();
+}
+Loads a new media item with specified options.
+void load(MediaLoadRequestData request) {
+ _hostApi.loadMediaLoadRequestData(request);
+}
+Callback to get updates on the progess of the currently playing ad break clip
+AdBreakClipProgressListener? onAdBreakClipProgressUpdated;
+
+
+Called when updated ad break status information is received.
+VoidCallback? onAdBreakStatusUpdated;
+
+
+Called when receiving media error message.
+VoidCallback? onMediaError;
+
+
+Called when updated media metadata is received.
+VoidCallback? onMetadataUpdated;
+
+
+Called when updated player queue preload status information is received, +for example, the next item to play has been preloaded.
+VoidCallback? onPreloadStatusUpdated;
+
+
+Callback to get updates on the progress of the currently playing media.
+ProgressListener? onProgressUpdated;
+
+
+Called when updated player queue status information is received.
+VoidCallback? onQueueStatusUpdated;
+
+
+Called when there is an outgoing request to the receiver.
+VoidCallback? onSendingRemoteMediaRequest;
+
+
+Pauses playback of the current media item.
+void pause() {
+ _hostApi.pause();
+}
+Begins (or resumes) playback of the current media item.
+void play() {
+ _hostApi.play();
+}
+Listenable state of the remote media player
+ValueListenable<PlayerState> get playerState => _playerStateNotifier;
+A Dialog to show the available tracks (Text and Audio) for user to select.
+void showTracksChooserDialog() {
+ _hostApi.showTracksChooserDialog();
+}
+Skips the playing ad.
+void skipAd() {
+ _hostApi.skipAd();
+}
+Stops playback of the current media item.
+void stop() {
+ _hostApi.stop();
+}
+A class that manages Session instances. The application can attach a +listeners to be notified of session events.
+SessionManager(this._hostApi);
+Returns the currently connected cast device
+Future<CastDevice> getCastDevice() async {
+ return await _hostApi.getCastDevice();
+}
+Callback called when the Cast Receiver sent a message
+MessageReceivedCallback? onMessageReceived;
+
+
+Internal method that shouldn't be visible
+@internal
+void onSessionStateChanged(SessionState sessionState) {
+ switch (sessionState) {
+ case SessionState.starting:
+ case SessionState.started:
+ case SessionState.start_failed:
+ case SessionState.ending:
+ case SessionState.ended:
+ case SessionState.resuming:
+ case SessionState.resumed:
+ case SessionState.resume_failed:
+ case SessionState.suspended:
+ _stateNotifier.value = sessionState;
+ break;
+ case SessionState.idle:
+ // Not raised
+ break;
+ }
+}
+Internal method that shouldn't be visible
+@internal
+void platformOnMessageReceived(CastMessage castMessage) {
+ var thisOnMessageReceived = onMessageReceived;
+
+ if (thisOnMessageReceived == null) return;
+ final namespace = castMessage.namespace ?? "";
+ final message = castMessage.message ?? "";
+
+ thisOnMessageReceived(namespace, message);
+}
+Returns the RemoteMediaClient for remote media control.
+RemoteMediaClient get remoteMediaClient {
+ var result = _remoteMediaClient;
+ if (result == null) {
+ _remoteMediaClient = result = RemoteMediaClient(_hostApi);
+ }
+ return result;
+}
+Send a string message to the Cast Receiver using the input namespace
+void sendMessage(String namespace, String message) {
+ final castMessage = CastMessage();
+ castMessage.namespace = namespace;
+ castMessage.message = message;
+ _hostApi.sendMessage(castMessage);
+}
+Toggles the stream muting.
+void setMute(bool muted) {
+ _hostApi.setMute(muted);
+}
+Listenable session state of the cast device
+ValueListenable<SessionState> get state => _stateNotifier;
+State of the session
+const SessionState(5)
+ const SessionState(4)
+ const SessionState(0)
+ const SessionState(8)
+ const SessionState(7)
+ const SessionState(6)
+ const SessionState(3)
+ const SessionState(2)
+ const SessionState(1)
+ const SessionState(9)
+ A constant List of the values in this enum, in order of their declaration.
+ + +const List<SessionState>
+ A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse function (like int.parse).
+These classes will provide the textual representation as
+their string represetion.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
const StreamType(2)
+ const StreamType(0)
+ const StreamType(3)
+ const StreamType(1)
+ A constant List of the values in this enum, in order of their declaration.
+ + +const List<StreamType>
+ A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse function (like int.parse).
+These classes will provide the textual representation as
+their string represetion.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
const TrackSubtype(3)
+ const TrackSubtype(5)
+ const TrackSubtype(4)
+ const TrackSubtype(6)
+ const TrackSubtype(1)
+ const TrackSubtype(2)
+ const TrackSubtype(0)
+ A constant List of the values in this enum, in order of their declaration.
+ + +const List<TrackSubtype>
+ A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse function (like int.parse).
+These classes will provide the textual representation as
+their string represetion.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
const TrackType(2)
+ const TrackType(1)
+ const TrackType(0)
+ A constant List of the values in this enum, in order of their declaration.
+ + +const List<TrackType>
+ const TrackType(3)
+ A string representation of this object.
+Some classes have a default textual representation,
+often paired with a static parse function (like int.parse).
+These classes will provide the textual representation as
+their string represetion.
Other classes have no meaningful textual representation
+that a program will care about.
+Such classes will typically override toString to provide
+useful information when inspecting the object,
+mainly for debugging or logging.
static WebImage decode(Object message) {
+ final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+ return WebImage()
+ ..url = pigeonMap['url'] as String?;
+}
+Object encode() {
+ final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+ pigeonMap['url'] = url;
+ return pigeonMap;
+}
+String? url;
+
+
+Flutter Cast Framework is a POC of a flutter plugin that lets you use Chromecast API in a flutter app.
+Currently only the following APIs are integrated (both Android and iOS):
+Clone this repo and add the following piece of code to your app's pubspec
+dependencies:
+ flutter_cast_framework:
+ path: ../flutter_cast_framework/ # the path depends on where you cloned this repo
+
+CastOptionsProviderAdd the following class to your Android project:
+import android.content.Context
+import com.google.android.gms.cast.framework.CastOptions
+import com.google.android.gms.cast.framework.OptionsProvider
+import com.google.android.gms.cast.framework.SessionProvider
+
+class CastOptionsProvider : OptionsProvider {
+ override fun getCastOptions(context: Context): CastOptions {
+ return CastOptions.Builder()
+ .setReceiverApplicationId("4F8B3483") // Your receiver Application ID
+ .build()
+ }
+
+ override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? {
+ return null
+ }
+}
+
+CastOptionsProviderAdd the following entry in the AndroidManifest.xml file under the <application> tag to reference the CastOptionsProvider class:
<application>
+ <meta-data
+ android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
+ android:value="com.gianlucaparadise.flutter_cast_framework_example.CastOptionsProvider" />
+</application>
+
+Make sure that your application and your activity are using an AppCompat theme (as stated here).
Make sure you minimum iOS version is 10.0. +Select Runner from left pane > General tab > Deployment Info > Target: set 10.0 or higher
+When Xcode is closed, open a terminal at the root folder of your project and run:
+cd ios && pod install
+
+To open your flutter project with Xcode, from root folder run open ios/Runner.xcworkspace
Add the following lines to your AppDelegate.swift:
import UIKit
+ import Flutter
++import GoogleCast
+
+ @UIApplicationMain
+-@objc class AppDelegate: FlutterAppDelegate {
++@objc class AppDelegate: FlutterAppDelegate, GCKLoggerDelegate {
++ let kReceiverAppID = "4F8B3483" // Your receiver Application ID
++ let kDebugLoggingEnabled = true
++
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
+ ) -> Bool {
++ let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID)
++ let options = GCKCastOptions(discoveryCriteria: criteria)
++ GCKCastContext.setSharedInstanceWith(options)
++
++ // Enable logger.
++ GCKLogger.sharedInstance().delegate = self
++
+ GeneratedPluginRegistrant.register(with: self)
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
++
++ // MARK: - GCKLoggerDelegate
++
++ func logMessage(_ message: String,
++ at level: GCKLoggerLevel,
++ fromFunction function: String,
++ location: String) {
++ if (kDebugLoggingEnabled) {
++ print(function + " - " + message)
++ }
++ }
+ }
+
+I used this project to test the capabilities of the following technologies:
+