Skip to content

Instantly share code, notes, and snippets.

@henkman
Last active March 15, 2024 19:50
Show Gist options
  • Save henkman/87140ac06c149fcf63ef5a6f656797e9 to your computer and use it in GitHub Desktop.
Save henkman/87140ac06c149fcf63ef5a6f656797e9 to your computer and use it in GitHub Desktop.
basic video viewer using fltk & embedded mpv. just drag&drop a folder and use left and right arrow. s to shuffle
// g++ -O2 -s -o pview main.cc -lfltk -lfltk_images -lmpv
#include <stdio.h>
#include <FL/Enumerations.H>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_PNG_Image.H>
#include <FL/x.H>
#include <mpv/client.h>
#if __linux__
#include <unistd.h>
#elif _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
class MPVPlayer : public Fl_Window {
public:
MPVPlayer(int x, int y, int w, int h, const char *label = "")
: Fl_Window(x, y, w, h, label) {}
~MPVPlayer() { mpv_terminate_destroy(mpv); }
void init() {
mpv = mpv_create();
uint64_t wid = fl_xid(this);
mpv_set_property(mpv, "wid", MPV_FORMAT_INT64, &wid);
mpv_set_property_string(mpv, "loop-file", "inf");
mpv_initialize(mpv);
}
void startFile(const char *file) {
const char *mpv_cmd[] = {"loadfile", file, NULL};
mpv_command(mpv, mpv_cmd);
}
void playlistNext() {
const char *mpv_cmd[] = {"playlist-next", NULL};
mpv_command(mpv, mpv_cmd);
}
void playlistPrev() {
const char *mpv_cmd[] = {"playlist-prev", NULL};
mpv_command(mpv, mpv_cmd);
}
void playlistShuffle() {
const char *mpv_cmd[] = {"playlist-shuffle", NULL};
mpv_command(mpv, mpv_cmd);
}
void openFileManager() {
const char *path = mpv_get_property_string(mpv, "path");
#if __linux__
#define FILE_MANAGER "nemo"
{
char cmd[512] = {0};
sprintf(cmd, "/bin/bash -c '" FILE_MANAGER " \"%s\"'", path);
FILE *pf = popen(cmd, "r");
pclose(pf);
}
#elif _WIN32
{
char args[1024] = {0};
sprintf(args, "/select, \"%s\"", path);
ShellExecute(NULL, "explorer", args, NULL, NULL, 0);
}
#else
#endif
mpv_free((void *)path);
}
int handle(int event) override {
switch (event) {
case FL_KEYBOARD: {
switch (Fl::event_key()) {
case 'n': // fallthrough
case FL_Right: {
playlistNext();
} break;
case 'p': // fallthrough
case FL_Left: {
playlistPrev();
} break;
case 's': {
playlistShuffle();
} break;
case 'o': {
openFileManager();
} break;
}
} break;
case FL_PASTE: {
const char *file = Fl::event_text();
char *fixed = strdup(file);
size_t len = strlen(fixed);
fixed[len - 1] = 0;
startFile(fixed);
free(fixed);
} // fallthrough
case FL_DND_DRAG: // fallthrough
case FL_DND_ENTER: // fallthrough
case FL_DND_LEAVE: // fallthrough
case FL_DND_RELEASE: // fallthrough
case FL_FOCUS: // fallthrough
return 1;
}
return Fl_Window::handle(event);
}
private:
mpv_handle *mpv = nullptr;
};
int main(int argc, char **argv) {
auto win = Fl_Double_Window(1280, 720, "pview");
auto player = MPVPlayer(0, 0, 1280, 720);
win.icon(new Fl_PNG_Image("Awicons-Vista-Artistic-Folder-my-video.256.png"));
win.add(player);
win.resizable(player);
win.show(argc, argv);
player.init();
Fl::focus(&player);
return (Fl::run());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment