bmdrm_mobile 0.0.17 copy "bmdrm_mobile: ^0.0.17" to clipboard
bmdrm_mobile: ^0.0.17 copied to clipboard

A Flutter plugin for DRM-protected video playback with watermark support.

example/lib/main.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:bmdrm_mobile/bmdrm_video_player.dart';
import 'package:bmdrm_mobile/bmdrm_resume_store.dart';

const String _sessionJson =
    '{"edge":"https://YOUR_EDGE_SERVER.video-crypt.com","videoId":"YOUR_VIDEO_ID","signature":"YOUR_SIGNATURE","userId":"YOUR_USER_ID","subscriptionId":"YOUR_SUBSCRIPTION_ID","sessionId":"YOUR_SESSION_ID","nonce":"YOUR_NONCE","date":0}';

class Lesson {
  const Lesson(this.id, this.title);
  final String id;
  final String title;
}

// Each lesson tracks its own resume position under its id.
const _lessons = [
  Lesson('lesson-1', 'Lesson 1 · DRM playback'),
  Lesson('lesson-2', 'Lesson 2 · Adaptive streaming'),
];

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    final scheme = ColorScheme.fromSeed(seedColor: Colors.indigo);
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'BMDRM Player',
      theme: ThemeData(useMaterial3: true, colorScheme: scheme),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  List<ResumeEntry> _inProgress = const [];

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

  Future<void> _load() async {
    final entries = await VideoPlayerController.continueWatching();
    if (mounted) setState(() => _inProgress = entries);
  }

  Future<void> _open(Lesson lesson) async {
    await Navigator.of(
      context,
    ).push(MaterialPageRoute(builder: (_) => PlayerPage(lesson: lesson)));
    _load();
  }

  String _titleFor(String id) =>
      _lessons.firstWhere((l) => l.id == id, orElse: () => Lesson(id, id)).title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('BMDRM Player')),
      body: ListView(
        children: [
          if (_inProgress.isNotEmpty) ...[
            const _SectionTitle('Continue watching'),
            for (final e in _inProgress)
              ListTile(
                leading: const Icon(Icons.play_circle_fill),
                title: Text(_titleFor(e.resumeId)),
                subtitle: LinearProgressIndicator(value: e.progress),
                trailing: Text('${(e.progress * 100).round()}%'),
                onTap: () => _open(Lesson(e.resumeId, _titleFor(e.resumeId))),
              ),
            const Divider(height: 24),
          ],
          const _SectionTitle('Lessons'),
          for (final lesson in _lessons)
            ListTile(
              leading: const Icon(Icons.ondemand_video),
              title: Text(lesson.title),
              onTap: () => _open(lesson),
            ),
        ],
      ),
    );
  }
}

class _SectionTitle extends StatelessWidget {
  const _SectionTitle(this.text);
  final String text;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
      child: Text(text, style: Theme.of(context).textTheme.titleMedium),
    );
  }
}

class PlayerPage extends StatelessWidget {
  const PlayerPage({super.key, required this.lesson});

  final Lesson lesson;

  @override
  Widget build(BuildContext context) {
    final videoHeight = MediaQuery.of(context).size.width * 9 / 16;
    return Scaffold(
      appBar: AppBar(title: Text(lesson.title)),
      body: Column(
        children: [
          BmdrmVideoPlayer.drmFromBackendSession(
            backendSession: jsonDecode(_sessionJson),
            width: double.infinity,
            height: videoHeight,
            autoPlay: true,
            resumeId: lesson.id,
            resumeFromLastPosition: true,
            fullscreenDrawerBuilder: (context, controller) =>
                _AboutDrawer(onClose: controller.closeDrawer),
            fullscreenDrawerToggle: const BmdrmDrawerToggle(
              label: 'À propos de cette leçon',
            ),
          ),
        ],
      ),
    );
  }
}

/// Example content for the player's fullscreen drawer. Any Flutter widget works
/// here — the plugin only provides the sliding panel and the toggle button.
class _AboutDrawer extends StatelessWidget {
  const _AboutDrawer({required this.onClose});

  final VoidCallback onClose;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      left: false,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Padding(
            padding: const EdgeInsets.fromLTRB(16, 12, 8, 4),
            child: Row(
              children: [
                const Expanded(
                  child: Text(
                    'About this lesson',
                    style: TextStyle(fontSize: 18, fontWeight: FontWeight.w700),
                  ),
                ),
                IconButton(icon: const Icon(Icons.close), onPressed: onClose),
              ],
            ),
          ),
          const Expanded(
            child: Padding(
              padding: EdgeInsets.all(16),
              child: Text(
                'Your custom fullscreen panel goes here — put any Flutter '
                'widgets you like beside the video.',
              ),
            ),
          ),
        ],
      ),
    );
  }
}
2
likes
0
points
874
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin for DRM-protected video playback with watermark support.

Homepage

License

unknown (license)

Dependencies

crypto, flutter, http, path, plugin_platform_interface, pointycastle, sqflite

More

Packages that depend on bmdrm_mobile

Packages that implement bmdrm_mobile