fcast_sender_sdk 0.0.1 copy "fcast_sender_sdk: ^0.0.1" to clipboard
fcast_sender_sdk: ^0.0.1 copied to clipboard

An SDK for easily creating senders for FCast and Google cast

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:fcast_sender_sdk/fcast_sender_sdk.dart';

Future<void> main() async {
  await RustLib.init();
  initLogger(); // Intended only for debug builds
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: _Scaffold());
  }
}

class _Scaffold extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _ScaffoldState();
}

class _ScaffoldState extends State<_Scaffold> {
  final CastContext castContext = CastContext();
  CastingDevice? activeDevice;
  int currentDeviceGeneration = 0;
  final Map<String, DeviceInfo> discoveredDevices = Map.fromEntries([
    // Debugging
    // MapEntry(
    //   "FCast-test",
    //   DeviceInfo(
    //     name: "FCast-test",
    //     protocol: ProtocolType.fCast,
    //     addresses: [IpAddr.v4(o1: 127, o2: 0, o3: 0, o4: 1)],
    //     port: 46899,
    //   ),
    // ),
  ]);
  final DeviceDiscoverer discoverer = DeviceDiscoverer();
  double currentVolume = 1.0;
  double currentTime = 0.0;
  double duration = 0.0;

  Future<void> startDiscovery() async {
    await discoverer.init();
    discoverer.eventStreamController.stream.listen((event) {
      print('discovery event: $event');
      switch (event) {
        case DiscoveryEventDeviceAdded():
          setState(() {
            discoveredDevices[event.deviceInfo.name] = event.deviceInfo;
          });
          break;
        case DiscoveryEventDeviceUpdated():
          setState(() {
            discoveredDevices[event.deviceInfo.name] = event.deviceInfo;
          });
          break;
        case DiscoveryEventDeviceRemoved():
          setState(() {
            discoveredDevices.remove(event.name);
          });
          break;
        default:
          break;
      }
    });
  }

  @override
  void initState() {
    super.initState();
    startDiscovery();
  }

  @override
  Widget build(BuildContext context) => Scaffold(
    appBar: activeDevice == null
        ? AppBar(title: const Text('Connect to your receiver'))
        : null,
    body: SafeArea(
      child: activeDevice == null
          ? Center(
              child: ListView(
                children: discoveredDevices.entries
                    .map(
                      (entry) => InkWell(
                        onTap: () {
                          CastingDevice device = castContext
                              .createDeviceFromInfo(info: entry.value);
                          final thisDeviceGeneration =
                              ++currentDeviceGeneration;
                          device.connect(
                            eventHandler: DeviceEventHandler(
                              onEvent: (event) {
                                if (thisDeviceGeneration !=
                                    currentDeviceGeneration) {
                                  return;
                                }
                                print('Device event: $event');
                                switch (event) {
                                  case DeviceEvent_ConnectionStateChanged():
                                    break;
                                  case DeviceEvent_VolumeChanged():
                                    setState(() {
                                      currentVolume = event.newVolume;
                                    });
                                    break;
                                  case DeviceEvent_TimeChanged():
                                    setState(() {
                                      currentTime = event.newTime;
                                    });
                                    break;
                                  case DeviceEvent_PlaybackStateChanged():
                                    break;
                                  case DeviceEvent_DurationChanged():
                                    setState(() {
                                      duration = event.newDuration;
                                    });
                                    break;
                                  case DeviceEvent_SpeedChanged():
                                    break;
                                  case DeviceEvent_SourceChanged():
                                    break;
                                  case DeviceEvent_KeyEvent():
                                    break;
                                  case DeviceEvent_MediaEvent():
                                    break;
                                  case DeviceEvent_PlaybackError():
                                    break;
                                }
                              },
                            ),
                            reconnectIntervalMillis: 1000,
                          );
                          setState(() {
                            activeDevice = device;
                          });
                        },
                        child: SizedBox(
                          height: 50,
                          child: Center(child: Text(entry.value.name)),
                        ),
                      ),
                    )
                    .toList(),
              ),
            )
          : Center(
              child: Column(
                children: [
                  ElevatedButton(
                    onPressed: () {
                      try {
                        activeDevice?.disconnect();
                      } catch (e) {
                        print('Failed to disconnect from device: $e');
                      }
                      setState(() {
                        activeDevice = null;
                      });
                    },
                    child: Text('Disconnect'),
                  ),
                  ElevatedButton(
                    onPressed: () {
                      try {
                        activeDevice?.load(
                          request: LoadRequest_Video(
                            contentType: 'video/mp4',
                            url:
                                'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
                            resumePosition: 0.0,
                          ),
                        );
                      } catch (e) {
                        print('Failed to load video: $e');
                      }
                    },
                    child: Text('Play demo'),
                  ),
                  ElevatedButton(
                    onPressed: () {
                      try {
                        activeDevice?.pausePlayback();
                      } catch (e) {
                        print('Failed to pause playback: $e');
                      }
                    },
                    child: Text('Pause'),
                  ),
                  ElevatedButton(
                    onPressed: () {
                      try {
                        activeDevice?.resumePlayback();
                      } catch (e) {
                        print('Failed to resume playback: $e');
                      }
                    },
                    child: Text('Resume'),
                  ),
                  ElevatedButton(
                    onPressed: () {
                      try {
                        activeDevice?.stopPlayback();
                      } catch (e) {
                        print('Failed to stop playback: $e');
                      }
                    },
                    child: Text('Stop playback'),
                  ),
                  Text("Volume:"),
                  Slider(
                    value: currentVolume,
                    min: 0.0,
                    max: 1.0,
                    onChanged: (double newVolume) {
                      try {
                        activeDevice?.changeVolume(volume: newVolume);
                        setState(() {
                          currentVolume = newVolume;
                        });
                      } catch (e) {
                        print('Failed to change volume: $e');
                      }
                    },
                  ),
                  Text("Position:"),
                  Slider(
                    value: currentTime,
                    min: 0.0,
                    max: duration,
                    onChanged: (double newTime) {
                      try {
                        activeDevice?.seek(timeSeconds: newTime);
                        setState(() {
                          currentTime = newTime;
                        });
                      } catch (e) {
                        print('Failed to seek: $e');
                      }
                    },
                  ),
                ],
              ),
            ),
    ),
  );
}