sariska_media_flutter_sdk 0.1.0 copy "sariska_media_flutter_sdk: ^0.1.0" to clipboard
sariska_media_flutter_sdk: ^0.1.0 copied to clipboard

Sariska Media Flutter SDK provides powerful Dart API's for developing real-time applications for audio and video calling.

example/lib/main.dart

import 'dart:io';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_audio_output/flutter_audio_output.dart';
import 'package:get/get.dart';
import 'package:flutter_iconly/flutter_iconly.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:sariska_media_flutter_sdk/Conference.dart';
import 'package:sariska_media_flutter_sdk/Connection.dart';
import 'package:sariska_media_flutter_sdk/JitsiLocalTrack.dart';
import 'package:sariska_media_flutter_sdk/JitsiRemoteTrack.dart';
import 'package:sariska_media_flutter_sdk/SariskaMediaTransport.dart';
import 'package:sariska_media_flutter_sdk/WebRTCView.dart';
import 'package:sariska_media_flutter_sdk_example/GenerateToken.dart';

typedef LocalTrackCallback = void Function(List<JitsiLocalTrack> tracks);
const Color themeColor = Color(0xff4050B5);

void main() {
  runApp(const GetMaterialApp(
    home: RoomNamePage(),
    debugShowCheckedModeBanner: true,
  ));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key, required this.roomName}) : super(key: key);

  final String roomName;

  @override
  State<MyApp> createState() => _MyAppState();
  static late LocalTrackCallback localTrackCallback;
}

class _MyAppState extends State<MyApp> {
  final _sariskaMediaTransport = SariskaMediaTransport();
  String token = 'unknown';
  String streamURL = '';
  List<JitsiRemoteTrack> remoteTracks = [];
  List<JitsiLocalTrack> localtracks = [];
  JitsiLocalTrack? localTrack;
  JitsiRemoteTrack? remoteTrack;
  bool isAudioOn = true;
  bool isVideoOn = true;

  late Conference _conference;
  late Connection _connection;

  @override
  void initState() {
    super.initState();
    initPlatformState();
    init();
  }

  late AudioInput _currentInput = const AudioInput("unknown", 0);
  bool isSpeakerOn = false;
  bool isCameraSwitch = false;

  Future<void> init() async {
    FlutterAudioOutput.setListener(() async {
      await _getInput();
      setState(() {});
    });

    await _getInput();
    if (!mounted) return;
    setState(() {});
  }

  _getInput() async {
    _currentInput = await FlutterAudioOutput.getCurrentOutput();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Stack(
          children: [
            if (localTrack != null && isVideoOn)
              Positioned(
                top: 0,
                left: 0,
                right: 0,
                bottom: 0,
                child: WebRTCView(
                  localTrack: localTrack!,
                  mirror: true,
                  objectFit: 'cover',
                ),
              ),
            if (localTrack != null && !isVideoOn)
              const Positioned(
                top: 0,
                left: 0,
                right: 0,
                bottom: 0,
                child: Center(
                  child: Icon(
                    IconlyLight.profile,
                    size: 100,
                    color: Colors.white, // Customize color as needed
                  ),
                ),
              ),
            if(remoteTrack != null)
              Positioned(
                bottom: 140,
                left: 0,
                right: 0,
                child: SizedBox(
                  height: 100,
                  child: ListView.builder(
                    scrollDirection: Axis.horizontal,
                    itemCount: 1,
                    itemBuilder: (BuildContext context, int index) {
                      return Padding(
                        padding: const EdgeInsets.only(left: 2.0, right: 2.0),
                        child: Container(
                          width: 120,
                          height: 100,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(30),
                          ),
                          child: WebRTCView(
                            localTrack: remoteTrack!,
                            mirror: true,
                            objectFit: 'cover',
                          ),
                        ),
                      );
                    },
                  ),
                ),
              ),
            Positioned(
              bottom: 0,
              left: 0,
              right: 0,
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Container(
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(30),
                  ),
                  child: Material(
                    borderRadius: BorderRadius.circular(30),
                    clipBehavior: Clip.antiAlias,
                    color: Colors.transparent,
                    child: BackdropFilter(
                      filter: ImageFilter.blur(
                        sigmaY: 20,
                        sigmaX: 20,
                      ),
                      child: InkWell(
                        highlightColor: Colors.transparent,
                        splashColor: Colors.transparent,
                        child: Container(
                          decoration: BoxDecoration(
                            color: Colors.white.withAlpha(30),
                          ),
                          padding: const EdgeInsets.symmetric(
                            horizontal: 14,
                            vertical: 20,
                          ),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: [
                              buildCustomButton(
                                onPressed: () {
                                  setState(() {
                                    for (JitsiLocalTrack track in localtracks) {
                                      if (track.getType() == "audio") {
                                        if (isAudioOn) {
                                          track.mute();
                                          isAudioOn = !isAudioOn;
                                        } else {
                                          track.unmute();
                                          isAudioOn = !isAudioOn;
                                        }
                                        break;
                                      }
                                    }
                                  });
                                },
                                icon: isAudioOn
                                    ? IconlyLight.voice
                                    : Icons.mic_off_outlined,
                                color: Colors.transparent,
                              ),
                              buildCustomButton(
                                onPressed: () {
                                  setState(() {
                                    for (JitsiLocalTrack track in localtracks) {
                                      if (track.getType() == "video") {
                                        track.switchCamera();
                                        isCameraSwitch = !isCameraSwitch;
                                      }
                                    }
                                  });
                                  setState(() {});
                                },
                                icon: isCameraSwitch
                                    ? IconlyLight.camera
                                    : Icons.switch_camera_outlined,
                                color: Colors.transparent,
                              ),
                              buildEndCallButton(
                                onPressed: () {
                                  print("Ending call");
                                  localTrack?.dispose();
                                  localtracks.clear();
                                  remoteTrack = null;
                                  remoteTracks.clear();
                                  _conference.leave();
                                  _connection.disconnect();
                                  Get.off(() => RoomNamePage());
                                },
                              ),
                              buildCustomButton(
                                onPressed: () {
                                  setState(() {
                                    for (JitsiLocalTrack track in localtracks) {
                                      if (track.getType() == "video") {
                                        if (isVideoOn) {
                                          track.mute();
                                          isVideoOn = !isVideoOn;
                                        } else {
                                          track.unmute();
                                          isVideoOn = !isVideoOn;
                                        }
                                        break;
                                      }
                                    }
                                  });
                                },
                                icon: isVideoOn
                                    ? IconlyLight.video
                                    : Icons.videocam_off_outlined,
                                color: Colors.transparent,
                              ),
                              buildCustomButton(
                                onPressed: () async {
                                  if (isSpeakerOn) {
                                    toggleSpeaker(false);
                                  } else {
                                    toggleSpeaker(true);
                                  }
                                },
                                icon: isSpeakerOn
                                    ? IconlyLight.volumeUp
                                    : IconlyBold.volumeOff,
                                color: Colors.transparent,
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
        backgroundColor: Colors.black,
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
  }

  Future<void> initPlatformState() async {
    try {
      token = await generateToken();

      _sariskaMediaTransport.initializeSdk();
      
      setupLocalStream();

      _connection = Connection(token, widget.roomName, false);
      
      _connection.addEventListener("CONNECTION_ESTABLISHED", () {
        _conference = _connection.initJitsiConference();
      
        _conference.addEventListener("CONFERENCE_JOINED", () {
          print("Conference joined from Swift and Android");
          for (JitsiLocalTrack track in localtracks) {
            _conference.addTrack(track);
          }
        });
      
        _conference.addEventListener("TRACK_ADDED", (track) {
          JitsiRemoteTrack remoteTrack = track;
          for (JitsiLocalTrack track in localtracks) {
            if (track.getStreamURL() == remoteTrack.getStreamURL()) {
              return;
            }
          }
          if (remoteTrack.getType() == "audio") {
            return;
          }
          streamURL = remoteTrack.getStreamURL();
          replaceChild(remoteTrack);
        });

        _conference.addEventListener("TRACK_REMOVED", (track) {
          setState(() {
            remoteTrack = null;
          });
        });
      
        _conference.join();
      });
      
      _connection.addEventListener("CONNECTION_FAILED", () {
        print("Connection Failed");
      });
      
      _connection.addEventListener("CONNECTION_DISCONNECTED", () {
        print("Connection Disconnected");
      });
      
      _connection.connect();

      setState(() {});
    } on PlatformException {
      print("Failed to get platform version.");
    }
  }

  void setupLocalStream() {
    Map<String, dynamic> options = {};
    options["audio"] = true;
    options["video"] = true;

    _sariskaMediaTransport.createLocalTracks(options, (tracks) {
      localtracks = tracks;
      for (JitsiLocalTrack track in localtracks) {
        if (track.getType() == "video") {
          setState(() {
            localTrack = track;
          });
        }
      }
    });
  }

  void replaceChild(JitsiRemoteTrack remoteTrack) {
    if (mounted) {
      setState(() {
        this.remoteTrack = remoteTrack;
      });
    }
  }

  void toggleSpeaker(bool isSpeaker) async {
    for (JitsiLocalTrack track in localtracks) {
      if (track.getType() == "audio") {
        track.toggleSpeaker(isSpeaker);
        isSpeakerOn = isSpeaker;
        setState(() {});
      }
    }
  }

  Widget buildCustomButton({
    required VoidCallback onPressed,
    required IconData icon,
    required Color color,
  }) {
    return Container(
      decoration: const BoxDecoration(
        shape: BoxShape.circle,
        color: Colors.transparent,
      ),
      child: InkWell(
        onTap: onPressed,
        customBorder: const CircleBorder(),
        child: Container(
          padding: const EdgeInsets.all(10),
          decoration: BoxDecoration(
            shape: BoxShape.circle,
            color: color,
          ),
          child: Icon(
            icon,
            color: Colors.black,
            size: 30,
          ),
        ),
      ),
    );
  }

  Widget buildEndCallButton({required VoidCallback onPressed}) {
    return Container(
      decoration: const BoxDecoration(
        shape: BoxShape.circle,
        color: Colors.red,
      ),
      child: InkWell(
        onTap: onPressed,
        customBorder: const CircleBorder(),
        child: Container(
          padding: const EdgeInsets.all(15),
          child: const Icon(
            Icons.call_end,
            color: Colors.white,
            size: 40,
          ),
        ),
      ),
    );
  }
}

class RoomNamePage extends StatefulWidget {
  const RoomNamePage({Key? key}) : super(key: key);

  @override
  _RoomNamePageState createState() => _RoomNamePageState();
}

class _RoomNamePageState extends State<RoomNamePage> {
  final TextEditingController _roomNameController = TextEditingController();

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

  Future webViewMethod() async {
    print('In Microphone permission method');
    WidgetsFlutterBinding.ensureInitialized();
    await Permission.microphone.request();
    WebViewMethodForCamera();
  }

  Future WebViewMethodForCamera() async {
    print('In Camera permission method');
    WidgetsFlutterBinding.ensureInitialized();
    await Permission.camera.request();
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      type: MaterialType.transparency, // or any other theme configuration
      child: Scaffold(
        appBar: AppBar(
          title: const Text(
            'Sariska.io',
            style: TextStyle(
              color: themeColor,
              fontSize: 30,
              fontWeight: FontWeight.w500,
            ),
          ),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: [
              const SizedBox(height: 20),
              TextField(
                controller: _roomNameController,
                decoration: const InputDecoration(
                  prefixIcon: Icon(IconlyLight.video),
                  contentPadding: EdgeInsets.symmetric(horizontal: 15),
                  focusedBorder: OutlineInputBorder(
                    borderSide: BorderSide(color: themeColor, width: 2),
                  ),
                  labelText: "Room Name",
                  labelStyle: TextStyle(
                    color: Colors.grey,
                    fontSize: 14,
                  ),
                  border: OutlineInputBorder(),
                ),
              ),
              const SizedBox(height: 20),
              ElevatedButton(
                style: ElevatedButton.styleFrom(
                  backgroundColor: themeColor,
                  textStyle: const TextStyle(color: Colors.white),
                ),
                onPressed: () {
                  final roomName = _roomNameController.text.trim();
                  if (roomName.isNotEmpty) {
                    Navigator.pushReplacement(
                      context,
                      MaterialPageRoute(
                        builder: (context) => MyApp(roomName: roomName),
                      ),
                    );
                  } else {
                    Fluttertoast.showToast(
                        msg: "Please Enter a room name",
                        toastLength: Toast.LENGTH_SHORT,
                        gravity: ToastGravity.BOTTOM,
                        timeInSecForIosWeb: 1,
                        backgroundColor: Colors.yellow,
                        textColor: Colors.white,
                        fontSize: 16.0);
                  }
                },
                child: const Text(
                  'Enter Room',
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 20,
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
7
likes
0
points
5
downloads

Publisher

unverified uploader

Weekly Downloads

Sariska Media Flutter SDK provides powerful Dart API's for developing real-time applications for audio and video calling.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on sariska_media_flutter_sdk

Packages that implement sariska_media_flutter_sdk