Awesome
<h1 align="center"><a href="https://github.com/libwinmedia/libwinmedia">libwinmedia</a></h1> <h4 align="center">A cross-platform media playback library for C/C++ & Flutter with good number of features.</h4>⚠️ 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 aWebKit
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
andstd::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.
<a href="https://www.buymeacoffee.com/alexmercerind"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=alexmercerind&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff"></a>
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 saini123hitesh@gmail.com
This library & work under this repository is MIT licensed.
Contributions welcomed.