Skip to content
This repository has been archived by the owner on Feb 23, 2022. It is now read-only.
/ libwinmedia Public archive

[Archived] A cross-platform simple media playback library for C/C++.

License

Notifications You must be signed in to change notification settings

harmonoid/libwinmedia

Repository files navigation

A cross-platform media playback library for C/C++ & Flutter with good number of features.

⚠️ Deprecated

The project is now archived. Reasons are documented below:

  • Inefficient Linux support: I had few (personal) reasons because of which my media URIs were not playing in GStreamer, so I decided to summon a WebKit instance using webview.h to make a basic JS interop setup for using WebAudio API (which itself is based on GStreamer in WebKitGTK). A good advantage that Flutter provides over other electron.js like alternatives is that it doesn't start a webview instance / JavaScript runtime, but using this plugin puts Flutter's those advantages to no use. This also makes us unable to add various crucial features like audio device selection/enumeration or equalizer etc. in future because of limited set of WebAudio APIs.
  • Unnecessary abstraction: As I said Linux support is not worth using, it puts Windows implementation to no use aswell. The WinRT APIs that this library exposes in a C like interface can be used directly in the project because they're already very user friendly & easy to integrate. Using this library on Windows just adds another layer of abstraction.
  • Unsafe: Using library on certain language/locales will cause crashes, since it heavily uses std::stof and std::stoi when doing JS interop. It is both inefficient and unsafe.
  • No backward compatibility: The library is only usable on later Windows 10 versions or higher. A project targetting a very small market share isn't worth maintaining.
  • No embedded Linux support: The library cannot be used on non-GTK Flutter embedders like flutter-pi etc. A lot of questions/issues have been made about this & it is not possible unless one decides to rewrite Linux implementation.

The project was started as an internal Harmonoid dependency to provide Windows/Linux support for the time-being, while I was looking for other libraries to settle on. Now that it is no longer used & current implementation isn't good enough, I don't see any point in adding features, fixing bugs etc. Thus, I have decided to discontinue this project. You are free to fork the project or use the code as allowed by the MIT license (which can be found in the LICENSE file).

Thankyou.

Example

A very simple example can be as follows.

C++

#include "libwinmedia/libwinmedia.hpp"

int32_t main(int32_t ac, const char** av) {
  using namespace std; 
  using namespace lwm;
  if (ac < 2) {
    cout << "No URI provided.\n"
         << "Example Usage:\n" << av[0]
         << " file://C:/alexmercerind/music.mp3\n" << av[0]
         << " https://alexmercerind.github.io/video.mp4\n";
    return EXIT_FAILURE;
  }
  auto player = Player(0);
  auto media = Media(av[1]);
  player.Open(vector<Media>{media});
  player.Play();
  player.events()->Position([](int32_t position) -> void {
    cout << "Current playback position is " << position << " ms.\n";
  });
  cin.get();
  return EXIT_SUCCESS;
}

Flutter

More about Flutter here or on the pub.dev.

dependencies:
  ...
  libwinmedia: ^0.0.1
import 'package:libwinmedia/libwinmedia.dart';

void main() {
  LWM.initialize();
  runApp(MyApp());
}

void demo() {
  var player = Player(id: 0);
  player.streams.medias.listen((List<Media> medias) {});
  player.streams.isPlaying.listen((bool isPlaying) {});
  player.streams.isBuffering.listen((bool isBuffering) {});
  player.streams.isCompleted.listen((bool isCompleted) {});
  player.streams.position.listen((Duration position) {});
  player.streams.duration.listen((Duration duration) {});
  player.streams.index.listen((int index) {});
  player.open([
    Media(uri: 'https://www.example.com/media/music.mp3'),
    Media(uri: 'file://C:/documents/video.mp4'),
  ]);
  player.play();
  player.seek(Duration(seconds: 20));
  player.nativeControls.update(
    album: 'Fine Line',
    albumArtist: 'Harry Styles',
    trackCount: 12,
    artist: 'Harry Styles',
    title: 'Lights Up',
    trackNumber: 1,
    thumbnail: File('album_art.png'),
  );
}

Bindings

  • just_audio: Cross platform audio playback library for Flutter, working on Android, iOS, macOS, Windows, Linux & Web.
  • libwinmedia-py: libwinmedia bindings for Python.
  • libwinmedia.dart: libwinmedia bindings for Flutter.

Support

Consider supporting the project by starring the repository or buying me a coffee.

Thanks a lot for your support.

Documentation

Setup

For using the library on Windows, you can download the pre-compiled shared library from the releases page & headers can be found here.

Usage

Create a new player.

Player player = Player(0);

Create a media to open inside player.

Media media = Media("file://C:/alexmercerind/music.mp3");
int32_t duration = media.duration();

Play the medias.

player.Open(std::vector<lwm::Media>{media});

Control playback.

player.Play();

player.Pause();

player.SetVolume(0.69);

player.SetRate(1.2);

player.Seek(10000);

player.SetIsLooping(false);

player.SetAudioBalance(1.0);

Listen to playback events.

player.events()->Position(
  [=](int position) -> void {}
);

player.events()->Duration(
  [=](int duration) -> void {}
);

player.events()->Rate(
  [=](float rate) -> void {}
);

player.events()->Volume(
  [=](float volume) -> void {}
);

player.events()->IsPlaying(
  [=](bool isPlaying) -> void {}
);

// Other events.

Create native system media controls.

Pass function as argument to receive event callbacks.

auto controls = lwm::NativeControls(
  [](auto button) -> void {
    if (button == NativeControlsButton::Play) std::cout << "Play clicked.\n";
    if (button == NativeControlsButton::Pause) std::cout << "Pause clicked.\n";
  }
);

Update the native system media controls.

controls.Update(
  std::make_shared<lwm::MusicNativeControlState>(
    "album_artist",
    "album",
    "track_count",
    "artist",
    "title",
    "track_number"
  ),
  "file://C:/Users/Hitesh/Pictures/AlbumArt.PNG"
);

Clear the native system media controls.

controls.Dispose();

Extract metadata tags.

auto tags = lwm::Tags::FromMusic(std::wstring(music_file));
std::wcout << "album        : " << tags.album() << ".\n"
           << "album_artist : " << tags.album_artist() << ".\n"
           << "bitrate      : " << tags.bitrate() << ".\n";
           
// Other metadata tags.

Extract album art.

lwm::Tags::ExtractThumbnail(
  music_file,
  TO_WIDESTRING(std::filesystem::current_path().string()),
  "ExtractedAlbumArt.PNG",
  lwm::ThumbnailMode::Music,
  400
);

Show video in a window.

For showing video, you must instantiate player as follows.

Player player = Player(0, true);

Control video output.

player.ShowWindow();

player.CloseWindow();

Notes

Windows

For showing video

You need to embed a manifest with maxversiontested property to the generated executable. The library creates a separate win32 window on another thread & uses XAML islands to render the MediaPlayerElement in it (for showing video). Learn more here & here.

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
        <application>
            <maxversiontested Id="10.0.18362.0"/>
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
        </application>
    </compatibility>
</assembly>

Aim

The main goals of creating libwinmedia are:

  • Having high-level, user friendly library for media playback in C++.
  • Having small footprint, by using already existing OS APIs.
  • Having necessary things like network playback, event callbacks etc.
  • Being able to build similar high-level bindings to other programming languages, by just looking up for methods inside a single shared library.
  • Supporting multiple playback instances.
  • Supporting media tag-parsing & other things like lockscreen/system notifications.
  • Being permissively licensed.
  • Being cross-platform **.

** Currently only working on Windows & Linux.

License

Copyright (c) 2021 Hitesh Kumar Saini [email protected]

This library & work under this repository is MIT licensed.

Contributions welcomed.