diff options
Diffstat (limited to 'DOCS/client_api_examples')
25 files changed, 0 insertions, 1936 deletions
diff --git a/DOCS/client_api_examples/Copyright b/DOCS/client_api_examples/Copyright deleted file mode 100644 index 38d1891eb7..0000000000 --- a/DOCS/client_api_examples/Copyright +++ /dev/null @@ -1,14 +0,0 @@ -All examples in this directory and its sub-directories are licensed -under one of the following licenses: - - WTFPL, ISC, Ms-PL, AGPLv3, BSD (any) - -Pick any license of your liking, and disregard the others. - -(The full text of each license is available on this website: - http://opensource.org/licenses/alphabetical ) - -Additionally, you may consider the example code to be public domain. -You are free to use any of the example code without further -requirements or need for attribution. - diff --git a/DOCS/client_api_examples/README.md b/DOCS/client_api_examples/README.md deleted file mode 100644 index c21deb5579..0000000000 --- a/DOCS/client_api_examples/README.md +++ /dev/null @@ -1,114 +0,0 @@ -# Client API examples - -All these examples use the mpv client API through libmpv. - -## Where are the docs? - -The libmpv C API is documented directly in the header files (on normal Unix -systems, this is in `/usr/include/mpv/client.h`. - -libmpv merely gives you access to mpv's command interface, which is documented -here: -* Options (`mpv_set_option()` and friends): http://mpv.io/manual/master/#options -* Commands (`mpv_command()` and friends): http://mpv.io/manual/master/#list-of-input-commands -* Properties (`mpv_set_property()` and friends): http://mpv.io/manual/master/#properties - -Essentially everything is done with them, including loading a file, retrieving -playback progress, and so on. - -## Methods of embedding the video window - -All of these examples concentrate on how to integrate mpv's video renderers -with your own GUI. This is generally the hardest part. libmpv enforces a -somewhat efficient video output method, rather than e.g. returning a RGBA -surface in memory for each frame. The latter would be prohibitively inefficient, -because it would require conversion on the CPU. The goal is also not requiring -the API users to reinvent their own video rendering/scaling/presentation -mechanisms. - -There are currently 2 methods of embedding video. - -### Native window embedding - -This uses the platform's native method of nesting multiple windows. For example, -Linux/X11 can nest a window from a completely different process. The nested -window can redraw contents on its own, and receive user input if the user -interacts with this window. - -libmpv lets you specify a parent window for its own video window via the `wid` -option. Then libmpv will create its window with your window as parent, and -render its video inside of it. - -This method is highly OS-dependent. Some behavior is OS-specific. There are -problems with focusing on X11 (the ancient X11 focus policy mismatches with -that of modern UI toolkits - it's normally worked around, but this is not -easily possible with raw window embedding). It seems to have stability problems -on OSX when using the Qt toolkit. - -### OpenGL embedding - -This method lets you use libmpv's OpenGL renderer directly. You create an -OpenGL context, and then use `mpv_opengl_cb_draw()` to render the video on -each frame. - -This is more complicated, because libmpv will work directly on your own OpenGL -state. It's also not possible to have mpv automatically receive user input. -You will have to simulate this with the `mouse`/`keypress`/`keydown`/`keyup` -commands. - -You also get much more flexibility. For example, you can actually render your -own OSD on top of the video, something that is not possible with raw window -embedding. - -### Which one to use? - -Due to the various platform-specific behavior and problems (in particular on -OSX), OpenGL embedding is recommended. If you're not comfortable with requiring -OpenGL, or want to support "direct" video output such as vdpau (which might -win when it comes to performance and energy-saving), you should probably -support both methods if possible. - -## List of examples - -### simple - -Very primitive terminal-only example. Shows some most basic API usage. - -### cocoa - -Shows how to embed the mpv video window in Objective-C/Cocoa. - -### cocoa-openglcb - -Similar to the cocoa sample, but shows how to integrate mpv's OpenGL renderer -using libmpv's opengl-cb API. Since it does not require complicated interaction -with Cocoa elements from different libraries, it's more robust. - -### qt - -Shows how to embed the mpv video window in Qt (using normal desktop widgets). - -### qt_opengl - -Shows how to use mpv's OpenGL video renderer in Qt. This uses the opengl-cb API -for video. Since it does not rely on embedding "foreign" native Windows, it's -usually more robust, potentially faster, and it's easier to control how your -GUI interacts with the video. You can do your own OpenGL rendering on top of -the video as well. - -### qml - -Shows how to use mpv's OpenGL video renderer in QtQuick2 with QML. Uses the -opengl-cb API for video. Since the video is a normal QML element, it's trivial -to create OSD overlays with QML-native graphical elements as well. - -### qml_direct - -Alternative example, which typically avoids a FBO indirection. Might be -slightly faster, but is less flexible and harder to use. In particular, the -video is not a normal QML element. Uses the opengl-cb API for video. - -### sdl - -Show how to embed the mpv OpenGL renderer in SDL. Uses the opengl-cb API for -video. diff --git a/DOCS/client_api_examples/cocoa-openglcb/cocoa-openglcb.m b/DOCS/client_api_examples/cocoa-openglcb/cocoa-openglcb.m deleted file mode 100644 index 4a4e8aa533..0000000000 --- a/DOCS/client_api_examples/cocoa-openglcb/cocoa-openglcb.m +++ /dev/null @@ -1,304 +0,0 @@ -// Plays a video from the command line in an opengl view in its own window. - -// Build with: clang -o cocoa-openglcb cocoa-openglcb.m `pkg-config --libs --cflags mpv` -framework Cocoa -framework OpenGL - -#import <mpv/client.h> -#import <mpv/opengl_cb.h> - -#import <stdio.h> -#import <stdlib.h> -#import <OpenGL/gl.h> - -#import <Cocoa/Cocoa.h> - - -static inline void check_error(int status) -{ - if (status < 0) { - printf("mpv API error: %s\n", mpv_error_string(status)); - exit(1); - } -} - -static void *get_proc_address(void *ctx, const char *name) -{ - CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); - void *addr = CFBundleGetFunctionPointerForName(CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")), symbolName); - CFRelease(symbolName); - return addr; -} - -static void glupdate(void *ctx); - -@interface MpvClientOGLView : NSOpenGLView -@property mpv_opengl_cb_context *mpvGL; -- (instancetype)initWithFrame:(NSRect)frame; -- (void)drawRect; -- (void)fillBlack; -@end - -@implementation MpvClientOGLView -- (instancetype)initWithFrame:(NSRect)frame -{ - // make sure the pixel format is double buffered so we can use - // [[self openGLContext] flushBuffer]. - NSOpenGLPixelFormatAttribute attributes[] = { - NSOpenGLPFADoubleBuffer, - 0 - }; - self = [super initWithFrame:frame - pixelFormat:[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]]; - - if (self) { - [self setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; - // swap on vsyncs - GLint swapInt = 1; - [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; - [[self openGLContext] makeCurrentContext]; - self.mpvGL = nil; - } - return self; -} - -- (void)fillBlack -{ - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); -} - -- (void)drawRect -{ - if (self.mpvGL) - mpv_opengl_cb_draw(self.mpvGL, 0, self.bounds.size.width, -self.bounds.size.height); - else - [self fillBlack]; - [[self openGLContext] flushBuffer]; -} - -- (void)drawRect:(NSRect)dirtyRect -{ - [self drawRect]; -} -@end - -@interface CocoaWindow : NSWindow -@property(retain, readonly) MpvClientOGLView *glView; -@property(retain, readonly) NSButton *pauseButton; -@end - -@implementation CocoaWindow -- (BOOL)canBecomeMainWindow { return YES; } -- (BOOL)canBecomeKeyWindow { return YES; } -- (void)initOGLView { - NSRect bounds = [[self contentView] bounds]; - // window coordinate origin is bottom left - NSRect glFrame = NSMakeRect(bounds.origin.x, bounds.origin.y + 30, bounds.size.width, bounds.size.height - 30); - _glView = [[MpvClientOGLView alloc] initWithFrame:glFrame]; - [self.contentView addSubview:_glView]; - - NSRect buttonFrame = NSMakeRect(bounds.origin.x, bounds.origin.y, 60, 30); - _pauseButton = [[NSButton alloc] initWithFrame:buttonFrame]; - _pauseButton.buttonType = NSToggleButton; - // button target has to be the delegate (it holds the mpv context - // pointer), so that's set later. - _pauseButton.action = @selector(togglePause:); - _pauseButton.title = @"Pause"; - _pauseButton.alternateTitle = @"Play"; - [self.contentView addSubview:_pauseButton]; -} -@end - -@interface AppDelegate : NSObject <NSApplicationDelegate> -{ - mpv_handle *mpv; - dispatch_queue_t queue; - CocoaWindow *window; -} -@end - -static void wakeup(void *); - -@implementation AppDelegate - -- (void)createWindow { - - int mask = NSTitledWindowMask|NSClosableWindowMask| - NSMiniaturizableWindowMask|NSResizableWindowMask; - - window = [[CocoaWindow alloc] - initWithContentRect:NSMakeRect(0, 0, 1280, 720) - styleMask:mask - backing:NSBackingStoreBuffered - defer:NO]; - - // force a minimum size to stop opengl from exploding. - [window setMinSize:NSMakeSize(200, 200)]; - [window initOGLView]; - [window setTitle:@"cocoa-openglcb example"]; - [window makeMainWindow]; - [window makeKeyAndOrderFront:nil]; - - NSMenu *m = [[NSMenu alloc] initWithTitle:@"AMainMenu"]; - NSMenuItem *item = [m addItemWithTitle:@"Apple" action:nil keyEquivalent:@""]; - NSMenu *sm = [[NSMenu alloc] initWithTitle:@"Apple"]; - [m setSubmenu:sm forItem:item]; - [sm addItemWithTitle: @"quit" action:@selector(terminate:) keyEquivalent:@"q"]; - [NSApp setMenu:m]; - [NSApp activateIgnoringOtherApps:YES]; -} - -- (void) applicationDidFinishLaunching:(NSNotification *)notification { - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - atexit_b(^{ - // Because activation policy has just been set to behave like a real - // application, that policy must be reset on exit to prevent, among - // other things, the menubar created here from remaining on screen. - [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited]; - }); - - // Read filename - NSArray *args = [NSProcessInfo processInfo].arguments; - if (args.count < 2) { - NSLog(@"Expected filename on command line"); - exit(1); - } - NSString *filename = args[1]; - - [self createWindow]; - window.pauseButton.target = self; - - mpv = mpv_create(); - if (!mpv) { - printf("failed creating context\n"); - exit(1); - } - - check_error(mpv_set_option_string(mpv, "input-media-keys", "yes")); - // request important errors - check_error(mpv_request_log_messages(mpv, "warn")); - - check_error(mpv_initialize(mpv)); - check_error(mpv_set_option_string(mpv, "vo", "opengl-cb")); - mpv_opengl_cb_context *mpvGL = mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB); - if (!mpvGL) { - puts("libmpv does not have the opengl-cb sub-API."); - exit(1); - } - // pass the mpvGL context to our view - window.glView.mpvGL = mpvGL; - int r = mpv_opengl_cb_init_gl(mpvGL, NULL, get_proc_address, NULL); - if (r < 0) { - puts("gl init has failed."); - exit(1); - } - mpv_opengl_cb_set_update_callback(mpvGL, glupdate, (__bridge void *)window.glView); - - // Deal with MPV in the background. - queue = dispatch_queue_create("mpv", DISPATCH_QUEUE_SERIAL); - dispatch_async(queue, ^{ - // Register to be woken up whenever mpv generates new events. - mpv_set_wakeup_callback(mpv, wakeup, (__bridge void *)self); - // Load the indicated file - const char *cmd[] = {"loadfile", filename.UTF8String, NULL}; - check_error(mpv_command(mpv, cmd)); - }); -} - -static void glupdate(void *ctx) -{ - MpvClientOGLView *glView = (__bridge MpvClientOGLView *)ctx; - // I'm still not sure what the best way to handle this is, but this - // works. - dispatch_async(dispatch_get_main_queue(), ^{ - [glView drawRect]; - }); -} - -- (void) handleEvent:(mpv_event *)event -{ - switch (event->event_id) { - case MPV_EVENT_SHUTDOWN: { - mpv_detach_destroy(mpv); - mpv_opengl_cb_uninit_gl(window.glView.mpvGL); - mpv = NULL; - printf("event: shutdown\n"); - break; - } - - case MPV_EVENT_LOG_MESSAGE: { - struct mpv_event_log_message *msg = (struct mpv_event_log_message *)event->data; - printf("[%s] %s: %s", msg->prefix, msg->level, msg->text); - } - - default: - printf("event: %s\n", mpv_event_name(event->event_id)); - } -} - -- (void)togglePause:(NSButton *)button -{ - if (mpv) { - switch (button.state) { - case NSOffState: - { - int pause = 0; - mpv_set_property(mpv, "pause", MPV_FORMAT_FLAG, &pause); - } - break; - case NSOnState: - { - int pause = 1; - mpv_set_property(mpv, "pause", MPV_FORMAT_FLAG, &pause); - } - break; - default: - NSLog(@"This should never happen."); - } - } -} - -- (void) readEvents -{ - dispatch_async(queue, ^{ - while (mpv) { - mpv_event *event = mpv_wait_event(mpv, 0); - if (event->event_id == MPV_EVENT_NONE) - break; - [self handleEvent:event]; - } - }); -} - -static void wakeup(void *context) -{ - AppDelegate *a = (__bridge AppDelegate *) context; - [a readEvents]; -} - -// quit when the window is closed. -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app -{ - return YES; -} - -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender -{ - NSLog(@"Terminating."); - const char *args[] = {"quit", NULL}; - mpv_command(mpv, args); - [window.glView clearGLContext]; - return NSTerminateNow; -} - -@end - -// Delete this if you already have a main.m. -int main(int argc, const char * argv[]) { - @autoreleasepool { - NSApplication *app = [NSApplication sharedApplication]; - AppDelegate *delegate = [AppDelegate new]; - app.delegate = delegate; - [app run]; - } - return 0; -} diff --git a/DOCS/client_api_examples/cocoa/cocoabasic.m b/DOCS/client_api_examples/cocoa/cocoabasic.m deleted file mode 100644 index 5a78250c3a..0000000000 --- a/DOCS/client_api_examples/cocoa/cocoabasic.m +++ /dev/null @@ -1,209 +0,0 @@ -// Plays a video from the command line in a view provided by the client -// application. - -// Build with: clang -o cocoabasic cocoabasic.m `pkg-config --libs --cflags mpv` -framework cocoa - -#include <mpv/client.h> - -#include <stdio.h> -#include <stdlib.h> - -static inline void check_error(int status) -{ - if (status < 0) { - printf("mpv API error: %s\n", mpv_error_string(status)); - exit(1); - } -} - -#import <Cocoa/Cocoa.h> - -@interface CocoaWindow : NSWindow -@end - -@implementation CocoaWindow -- (BOOL)canBecomeMainWindow { return YES; } -- (BOOL)canBecomeKeyWindow { return YES; } -@end - -@interface AppDelegate : NSObject <NSApplicationDelegate> -{ - mpv_handle *mpv; - dispatch_queue_t queue; - NSWindow *w; - NSView *wrapper; -} -@end - -static void wakeup(void *); - -@implementation AppDelegate - -- (void)createWindow { - - int mask = NSTitledWindowMask|NSClosableWindowMask| - NSMiniaturizableWindowMask|NSResizableWindowMask; - - self->w = [[CocoaWindow alloc] - initWithContentRect:NSMakeRect(0,0, 1280, 720) - styleMask:mask - backing:NSBackingStoreBuffered - defer:NO]; - - [self->w setTitle:@"cocoabasic example"]; - [self->w makeMainWindow]; - [self->w makeKeyAndOrderFront:nil]; - - NSRect frame = [[self->w contentView] bounds]; - self->wrapper = [[NSView alloc] initWithFrame:frame]; - [self->wrapper setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; - [[self->w contentView] addSubview:self->wrapper]; - [self->wrapper release]; - - NSMenu *m = [[NSMenu alloc] initWithTitle:@"AMainMenu"]; - NSMenuItem *item = [m addItemWithTitle:@"Apple" action:nil keyEquivalent:@""]; - NSMenu *sm = [[NSMenu alloc] initWithTitle:@"Apple"]; - [m setSubmenu:sm forItem:item]; - [sm addItemWithTitle: @"mpv_command('stop')" action:@selector(mpv_stop) keyEquivalent:@""]; - [sm addItemWithTitle: @"mpv_command('quit')" action:@selector(mpv_quit) keyEquivalent:@""]; - [sm addItemWithTitle: @"quit" action:@selector(terminate:) keyEquivalent:@"q"]; - [NSApp setMenu:m]; - [NSApp activateIgnoringOtherApps:YES]; -} - -- (void) applicationDidFinishLaunching:(NSNotification *)notification { - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - atexit_b(^{ - // Because activation policy has just been set to behave like a real - // application, that policy must be reset on exit to prevent, among - // other things, the menubar created here from remaining on screen. - [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited]; - }); - - // Read filename - NSArray *args = [NSProcessInfo processInfo].arguments; - if (args.count < 2) { - NSLog(@"Expected filename on command line"); - exit(1); - } - NSString *filename = args[1]; - - [self createWindow]; - - // Deal with MPV in the background. - queue = dispatch_queue_create("mpv", DISPATCH_QUEUE_SERIAL); - dispatch_async(queue, ^{ - - mpv = mpv_create(); - if (!mpv) { - printf("failed creating context\n"); - exit(1); - } - - int64_t wid = (intptr_t) self->wrapper; - check_error(mpv_set_option(mpv, "wid", MPV_FORMAT_INT64, &wid)); - - // Maybe set some options here, like default key bindings. - // NOTE: Interaction with the window seems to be broken for now. - check_error(mpv_set_option_string(mpv, "input-default-bindings", "yes")); - - // for testing! - check_error(mpv_set_option_string(mpv, "input-media-keys", "yes")); - check_error(mpv_set_option_string(mpv, "input-cursor", "no")); - check_error(mpv_set_option_string(mpv, "input-vo-keyboard", "yes")); - - // request important errors - check_error(mpv_request_log_messages(mpv, "warn")); - - check_error(mpv_initialize(mpv)); - - // Register to be woken up whenever mpv generates new events. - mpv_set_wakeup_callback(mpv, wakeup, (__bridge void *) self); - - // Load the indicated file - const char *cmd[] = {"loadfile", filename.UTF8String, NULL}; - check_error(mpv_command(mpv, cmd)); - }); -} - -- (void) handleEvent:(mpv_event *)event -{ - switch (event->event_id) { - case MPV_EVENT_SHUTDOWN: { - mpv_detach_destroy(mpv); - mpv = NULL; - printf("event: shutdown\n"); - break; - } - - case MPV_EVENT_LOG_MESSAGE: { - struct mpv_event_log_message *msg = (struct mpv_event_log_message *)event->data; - printf("[%s] %s: %s", msg->prefix, msg->level, msg->text); - } - - case MPV_EVENT_VIDEO_RECONFIG: { - dispatch_async(dispatch_get_main_queue(), ^{ - NSArray *subviews = [self->wrapper subviews]; - if ([subviews count] > 0) { - // mpv's events view - NSView *eview = [self->wrapper subviews][0]; - [self->w makeFirstResponder:eview]; - } - }); - } - - default: - printf("event: %s\n", mpv_event_name(event->event_id)); - } -} - -- (void) readEvents -{ - dispatch_async(queue, ^{ - while (mpv) { - mpv_event *event = mpv_wait_event(mpv, 0); - if (event->event_id == MPV_EVENT_NONE) - break; - [self handleEvent:event]; - } - }); -} - -static void wakeup(void *context) { - AppDelegate *a = (__bridge AppDelegate *) context; - [a readEvents]; -} - -// Ostensibly, mpv's window would be hooked up to this. -- (BOOL) windowShouldClose:(id)sender -{ - return NO; -} - -- (void) mpv_stop -{ - if (mpv) { - const char *args[] = {"stop", NULL}; - mpv_command(mpv, args); - } -} - -- (void) mpv_quit -{ - if (mpv) { - const char *args[] = {"quit", NULL}; - mpv_command(mpv, args); - } -} -@end - -// Delete this if you already have a main.m. -int main(int argc, const char * argv[]) { - @autoreleasepool { - NSApplication *app = [NSApplication sharedApplication]; - AppDelegate *delegate = [AppDelegate new]; - app.delegate = delegate; - [app run]; - } - return 0; -} diff --git a/DOCS/client_api_examples/qml/main.cpp b/DOCS/client_api_examples/qml/main.cpp deleted file mode 100644 index 2122cd8c5c..0000000000 --- a/DOCS/client_api_examples/qml/main.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "main.h" - -#include <stdexcept> -#include <clocale> - -#include <QObject> -#include <QtGlobal> -#include <QOpenGLContext> -#include <QGuiApplication> - -#include <QtGui/QOpenGLFramebufferObject> - -#include <QtQuick/QQuickWindow> -#include <QtQuick/QQuickView> - -class MpvRenderer : public QQuickFramebufferObject::Renderer -{ - static void *get_proc_address(void *ctx, const char *name) { - (void)ctx; - QOpenGLContext *glctx = QOpenGLContext::currentContext(); - if (!glctx) - return NULL; - return (void *)glctx->getProcAddress(QByteArray(name)); - } - - mpv::qt::Handle mpv; - QQuickWindow *window; - mpv_opengl_cb_context *mpv_gl; -public: - MpvRenderer(const MpvObject *obj) - : mpv(obj->mpv), window(obj->window()), mpv_gl(obj->mpv_gl) - { - int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL); - if (r < 0) - throw std::runtime_error("could not initialize OpenGL"); - } - - virtual ~MpvRenderer() - { - // Until this call is done, we need to make sure the player remains - // alive. This is done implicitly with the mpv::qt::Handle instance - // in this class. - mpv_opengl_cb_uninit_gl(mpv_gl); - } - - void render() - { - QOpenGLFramebufferObject *fbo = framebufferObject(); - window->resetOpenGLState(); - mpv_opengl_cb_draw(mpv_gl, fbo->handle(), fbo->width(), fbo->height()); - window->resetOpenGLState(); - } -}; - -MpvObject::MpvObject(QQuickItem * parent) - : QQuickFramebufferObject(parent), mpv_gl(0) -{ - mpv = mpv::qt::Handle::FromRawHandle(mpv_create()); - if (!mpv) - throw std::runtime_error("could not create mpv context"); - - mpv_set_option_string(mpv, "terminal", "yes"); - mpv_set_option_string(mpv, "msg-level", "all=v"); - - if (mpv_initialize(mpv) < 0) - throw std::runtime_error("could not initialize mpv context"); - - // Make use of the MPV_SUB_API_OPENGL_CB API. - mpv::qt::set_option_variant(mpv, "vo", "opengl-cb"); - - // Request hw decoding, just for testing. - mpv::qt::set_option_variant(mpv, "hwdec", "auto"); - - // Setup the callback that will make QtQuick update and redraw if there - // is a new video frame. Use a queued connection: this makes sure the - // doUpdate() function is run on the GUI thread. - mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB); - if (!mpv_gl) - throw std::runtime_error("OpenGL not compiled in"); - mpv_opengl_cb_set_update_callback(mpv_gl, MpvObject::on_update, (void *)this); - connect(this, &MpvObject::onUpdate, this, &MpvObject::doUpdate, - Qt::QueuedConnection); -} - -MpvObject::~MpvObject() -{ - if (mpv_gl) - mpv_opengl_cb_set_update_callback(mpv_gl, NULL, NULL); -} - -void MpvObject::on_update(void *ctx) -{ - MpvObject *self = (MpvObject *)ctx; - emit self->onUpdate(); -} - -// connected to onUpdate(); signal makes sure it runs on the GUI thread -void MpvObject::doUpdate() -{ - update(); -} - -void MpvObject::command(const QVariant& params) -{ - mpv::qt::command_variant(mpv, params); -} - -void MpvObject::setProperty(const QString& name, const QVariant& value) -{ - mpv::qt::set_property_variant(mpv, name, value); -} - -QQuickFramebufferObject::Renderer *MpvObject::createRenderer() const -{ - window()->setPersistentOpenGLContext(true); - window()->setPersistentSceneGraph(true); - return new MpvRenderer(this); -} - -int main(int argc, char **argv) -{ - QGuiApplication app(argc, argv); - - // Qt sets the locale in the QGuiApplication constructor, but libmpv - // requires the LC_NUMERIC category to be set to "C", so change it back. - std::setlocale(LC_NUMERIC, "C"); - - qmlRegisterType<MpvObject>("mpvtest", 1, 0, "MpvObject"); - - QQuickView view; - view.setResizeMode(QQuickView::SizeRootObjectToView); - view.setSource(QUrl("qrc:///mpvtest/main.qml")); - view.show(); - - return app.exec(); -} diff --git a/DOCS/client_api_examples/qml/main.h b/DOCS/client_api_examples/qml/main.h deleted file mode 100644 index 9a65ae5350..0000000000 --- a/DOCS/client_api_examples/qml/main.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef MPVRENDERER_H_ -#define MPVRENDERER_H_ - -#include <QtQuick/QQuickFramebufferObject> - -#include <mpv/client.h> -#include <mpv/opengl_cb.h> -#include <mpv/qthelper.hpp> - -class MpvRenderer; - -class MpvObject : public QQuickFramebufferObject -{ - Q_OBJECT - - mpv::qt::Handle mpv; - mpv_opengl_cb_context *mpv_gl; - - friend class MpvRenderer; - -public: - MpvObject(QQuickItem * parent = 0); - virtual ~MpvObject(); - virtual Renderer *createRenderer() const; -public slots: - void command(const QVariant& params); - void setProperty(const QString& name, const QVariant& value); -signals: - void onUpdate(); -private slots: - void doUpdate(); -private: - static void on_update(void *ctx); -}; - -#endif diff --git a/DOCS/client_api_examples/qml/main.qml b/DOCS/client_api_examples/qml/main.qml deleted file mode 100644 index ec06790e86..0000000000 --- a/DOCS/client_api_examples/qml/main.qml +++ /dev/null @@ -1,71 +0,0 @@ -import QtQuick 2.0 -import QtQuick.Controls 1.0 - -import mpvtest 1.0 - -Item { - width: 1280 - height: 720 - - MpvObject { - id: renderer - anchors.fill: parent - - MouseArea { - anchors.fill: parent - onClicked: renderer.command(["loadfile", "../../../test.mkv"]) - } - } - - Rectangle { - id: labelFrame - anchors.margins: -50 - radius: 5 - color: "white" - border.color: "black" - opacity: 0.8 - anchors.fill: box - } - - Row { - id: box - anchors.bottom: renderer.bottom - anchors.left: renderer.left - anchors.right: renderer.right - anchors.margins: 100 - - Text { - anchors.margins: 10 - wrapMode: Text.WordWrap - text: "QtQuick and mpv are both rendering stuff.\n - Click to load ../../../test.mkv" - } - - // Don't take these controls too seriously. They're for testing. - Column { - CheckBox { - id: checkbox - anchors.margins: 10 - // Heavily filtered means good, right? - text: "Make video look like on a Smart TV" - onClicked: { - if (checkbox.checked) { - renderer.command(["vo_cmdline", "sharpen=5.0"]) - } else { - renderer.command(["vo_cmdline", ""]) - } - } - } - Slider { - id: slider - anchors.margins: 10 - anchors.left: checkbox.left - anchors.right: checkbox.right - minimumValue: -100 - maximumValue: 100 - value: 0 - onValueChanged: renderer.setProperty("gamma", slider.value | 0) - } - } - } -} diff --git a/DOCS/client_api_examples/qml/mpvtest.pro b/DOCS/client_api_examples/qml/mpvtest.pro deleted file mode 100644 index 0b2e96fe99..0000000000 --- a/DOCS/client_api_examples/qml/mpvtest.pro +++ /dev/null @@ -1,12 +0,0 @@ -QT += qml quick - -HEADERS += main.h -SOURCES += main.cpp - -QT_CONFIG -= no-pkg-config -CONFIG += link_pkgconfig debug -PKGCONFIG += mpv - -RESOURCES += mpvtest.qrc - -OTHER_FILES += main.qml diff --git a/DOCS/client_api_examples/qml/mpvtest.qrc b/DOCS/client_api_examples/qml/mpvtest.qrc deleted file mode 100644 index bb672657e5..0000000000 --- a/DOCS/client_api_examples/qml/mpvtest.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<RCC> - <qresource prefix="/mpvtest"> - <file>main.qml</file> - </qresource> -</RCC> diff --git a/DOCS/client_api_examples/qml_direct/main.cpp b/DOCS/client_api_examples/qml_direct/main.cpp deleted file mode 100644 index 37c6119707..0000000000 --- a/DOCS/client_api_examples/qml_direct/main.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "main.h" - -#include <stdexcept> -#include <clocale> - -#include <QObject> -#include <QtGlobal> -#include <QOpenGLContext> - -#include <QGuiApplication> -#include <QtQuick/QQuickWindow> -#include <QtQuick/QQuickView> - -static void *get_proc_address(void *ctx, const char *name) { - (void)ctx; - QOpenGLContext *glctx = QOpenGLContext::currentContext(); - if (!glctx) - return NULL; - return (void *)glctx->getProcAddress(QByteArray(name)); -} - -MpvRenderer::MpvRenderer(mpv::qt::Handle a_mpv, mpv_opengl_cb_context *a_mpv_gl) - : mpv(a_mpv), mpv_gl(a_mpv_gl), window(0), size() -{ - int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL); - if (r < 0) - throw std::runtime_error("could not initialize OpenGL"); -} - -MpvRenderer::~MpvRenderer() -{ - // Until this call is done, we need to make sure the player remains - // alive. This is done implicitly with the mpv::qt::Handle instance - // in this class. - mpv_opengl_cb_uninit_gl(mpv_gl); -} - -void MpvRenderer::paint() -{ - window->resetOpenGLState(); - - // This uses 0 as framebuffer, which indicates that mpv will render directly - // to the frontbuffer. Note that mpv will always switch framebuffers - // explicitly. Some QWindow setups (such as using QQuickWidget) actually - // want you to render into a FBO in the beforeRendering() signal, and this - // code won't work there. - // The negation is used for rendering with OpenGL's flipped coordinates. - mpv_opengl_cb_draw(mpv_gl, 0, size.width(), -size.height()); - - window->resetOpenGLState(); -} - -MpvObject::MpvObject(QQuickItem * parent) - : QQuickItem(parent), mpv_gl(0), renderer(0) -{ - mpv = mpv::qt::Handle::FromRawHandle(mpv_create()); - if (!mpv) - throw std::runtime_error("could not create mpv context"); - - mpv_set_option_string(mpv, "terminal", "yes"); - mpv_set_option_string(mpv, "msg-level", "all=v"); - - if (mpv_initialize(mpv) < 0) - throw std::runtime_error("could not initialize mpv context"); - - // Make use of the MPV_SUB_API_OPENGL_CB API. - mpv::qt::set_option_variant(mpv, "vo", "opengl-cb"); - - // Setup the callback that will make QtQuick update and redraw if there - // is a new video frame. Use a queued connection: this makes sure the - // doUpdate() function is run on the GUI thread. - mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB); - if (!mpv_gl) - throw std::runtime_error("OpenGL not compiled in"); - mpv_opengl_cb_set_update_callback(mpv_gl, MpvObject::on_update, (void *)this); - connect(this, &MpvObject::onUpdate, this, &MpvObject::doUpdate, - Qt::QueuedConnection); - - connect(this, &QQuickItem::windowChanged, - this, &MpvObject::handleWindowChanged); -} - -MpvObject::~MpvObject() -{ - if (mpv_gl) - mpv_opengl_cb_set_update_callback(mpv_gl, NULL, NULL); -} - -void MpvObject::handleWindowChanged(QQuickWindow *win) -{ - if (!win) - return; - connect(win, &QQuickWindow::beforeSynchronizing, - this, &MpvObject::sync, Qt::DirectConnection); - connect(win, &QQuickWindow::sceneGraphInvalidated, - this, &MpvObject::cleanup, Qt::DirectConnection); - connect(win, &QQuickWindow::frameSwapped, - this, &MpvObject::swapped, Qt::DirectConnection); - win->setClearBeforeRendering(false); -} - -void MpvObject::sync() -{ - if (!renderer) { - renderer = new MpvRenderer(mpv, mpv_gl); - connect(window(), &QQuickWindow::beforeRendering, - renderer, &MpvRenderer::paint, Qt::DirectConnection); - } - renderer->window = window(); - renderer->size = window()->size() * window()->devicePixelRatio(); -} - -void MpvObject::swapped() -{ - mpv_opengl_cb_report_flip(mpv_gl, 0); -} - -void MpvObject::cleanup() -{ - if (renderer) { - delete renderer; - renderer = 0; - } -} - -void MpvObject::on_update(void *ctx) -{ - MpvObject *self = (MpvObject *)ctx; - emit self->onUpdate(); -} - -// connected to onUpdate(); signal makes sure it runs on the GUI thread -void MpvObject::doUpdate() -{ - window()->update(); -} - -void MpvObject::command(const QVariant& params) -{ - mpv::qt::command_variant(mpv, params); -} - -int main(int argc, char **argv) -{ - QGuiApplication app(argc, argv); - - // Qt sets the locale in the QGuiApplication constructor, but libmpv - // requires the LC_NUMERIC category to be set to "C", so change it back. - std::setlocale(LC_NUMERIC, "C"); - - qmlRegisterType<MpvObject>("mpvtest", 1, 0, "MpvObject"); - - QQuickView view; - view.setResizeMode(QQuickView::SizeRootObjectToView); - view.setSource(QUrl("qrc:///mpvtest/main.qml")); - view.show(); - - return app.exec(); -} diff --git a/DOCS/client_api_examples/qml_direct/main.h b/DOCS/client_api_examples/qml_direct/main.h deleted file mode 100644 index b0310ff0be..0000000000 --- a/DOCS/client_api_examples/qml_direct/main.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef MPVRENDERER_H_ -#define MPVRENDERER_H_ - -#include <QtQuick/QQuickItem> - -#include <mpv/client.h> -#include <mpv/opengl_cb.h> -#include <mpv/qthelper.hpp> - -class MpvRenderer : public QObject -{ - Q_OBJECT - mpv::qt::Handle mpv; - mpv_opengl_cb_context *mpv_gl; - QQuickWindow *window; - QSize size; - - friend class MpvObject; -public: - MpvRenderer(mpv::qt::Handle a_mpv, mpv_opengl_cb_context *a_mpv_gl); - virtual ~MpvRenderer(); -public slots: - void paint(); -}; - -class MpvObject : public QQuickItem -{ - Q_OBJECT - - mpv::qt::Handle mpv; - mpv_opengl_cb_context *mpv_gl; - MpvRenderer *renderer; - -public: - MpvObject(QQuickItem * parent = 0); - virtual ~MpvObject(); -public slots: - void command(const QVariant& params); - void sync(); - void swapped(); - void cleanup(); -signals: - void onUpdate(); -private slots: - void doUpdate(); - void handleWindowChanged(QQuickWindow *win); -private: - static void on_update(void *ctx); -}; - -#endif diff --git a/DOCS/client_api_examples/qml_direct/main.qml b/DOCS/client_api_examples/qml_direct/main.qml deleted file mode 100644 index 92be9bc405..0000000000 --- a/DOCS/client_api_examples/qml_direct/main.qml +++ /dev/null @@ -1,49 +0,0 @@ -import QtQuick 2.0 -import QtQuick.Controls 1.0 - -import mpvtest 1.0 - -Item { - width: 1280 - height: 720 - - MpvObject { - id: renderer - - // This object isn't real and not visible; it just renders into the - // background of the containing Window. - width: 0 - height: 0 - } - - MouseArea { - anchors.fill: parent - onClicked: renderer.command(["loadfile", "../../../test.mkv"]) - } - - Rectangle { - id: labelFrame - anchors.margins: -50 - radius: 5 - color: "white" - border.color: "black" - opacity: 0.8 - anchors.fill: box - } - - Row { - id: box - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.margins: 100 - - Text { - anchors.margins: 10 - wrapMode: Text.WordWrap - text: "QtQuick and mpv are both rendering stuff.\n - In this example, mpv is always in the background.\n - Click to load ../../../test.mkv" - } - } -} diff --git a/DOCS/client_api_examples/qml_direct/mpvtest.pro b/DOCS/client_api_examples/qml_direct/mpvtest.pro deleted file mode 100644 index 0b2e96fe99..0000000000 --- a/DOCS/client_api_examples/qml_direct/mpvtest.pro +++ /dev/null @@ -1,12 +0,0 @@ -QT += qml quick - -HEADERS += main.h -SOURCES += main.cpp - -QT_CONFIG -= no-pkg-config -CONFIG += link_pkgconfig debug -PKGCONFIG += mpv - -RESOURCES += mpvtest.qrc - -OTHER_FILES += main.qml diff --git a/DOCS/client_api_examples/qml_direct/mpvtest.qrc b/DOCS/client_api_examples/qml_direct/mpvtest.qrc deleted file mode 100644 index bb672657e5..0000000000 --- a/DOCS/client_api_examples/qml_direct/mpvtest.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<RCC> - <qresource prefix="/mpvtest"> - <file>main.qml</file> - </qresource> -</RCC> diff --git a/DOCS/client_api_examples/qt/qtexample.cpp b/DOCS/client_api_examples/qt/qtexample.cpp deleted file mode 100644 index 5f4e86e891..0000000000 --- a/DOCS/client_api_examples/qt/qtexample.cpp +++ /dev/null @@ -1,225 +0,0 @@ -// This example can be built with: qmake && make - -#include <clocale> -#include <sstream> -#include <stdexcept> - -#include <QtGlobal> -#include <QFileDialog> -#include <QStatusBar> -#include <QMenuBar> -#include <QMenu> -#include <QGridLayout> -#include <QApplication> -#include <QTextEdit> - -#if QT_VERSION >= 0x050000 -#include <QJsonDocument> -#endif - -#include <mpv/qthelper.hpp> - -#include "qtexample.h" - -static void wakeup(void *ctx) -{ - // This callback is invoked from any mpv thread (but possibly also - // recursively from a thread that is calling the mpv API). Just notify - // the Qt GUI thread to wake up (so that it can process events with - // mpv_wait_event()), and return as quickly as possible. - MainWindow *mainwindow = (MainWindow *)ctx; - emit mainwindow->mpv_events(); -} - -MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent) -{ - setWindowTitle("Qt embedding demo"); - setMinimumSize(640, 480); - - QMenu *menu = menuBar()->addMenu(tr("&File")); - QAction *on_open = new QAction(tr("&Open"), this); - on_open->setShortcuts(QKeySequence::Open); - on_open->setStatusTip(tr("Open a file")); - connect(on_open, &QAction::triggered, this, &MainWindow::on_file_open); - menu->addAction(on_open); - - QAction *on_new = new QAction(tr("&New window"), this); - connect(on_new, &QAction::triggered, this, &MainWindow::on_new_window); - menu->addAction(on_new); - - statusBar(); - - QMainWindow *log_window = new QMainWindow(this); - log = new QTextEdit(log_window); - log->setReadOnly(true); - log_window->setCentralWidget(log); - log_window->setWindowTitle("mpv log window"); - log_window->setMinimumSize(500, 50); - log_window->show(); - - mpv = mpv_create(); - if (!mpv) - throw std::runtime_error("can't create mpv instance"); - - // Create a video child window. Force Qt to create a native window, and - // pass the window ID to the mpv wid option. Works on: X11, win32, Cocoa - mpv_container = new QWidget(this); - setCentralWidget(mpv_container); - mpv_container->setAttribute(Qt::WA_DontCreateNativeAncestors); - mpv_container->setAttribute(Qt::WA_NativeWindow); - // If you have a HWND, use: int64_t wid = (intptr_t)hwnd; - int64_t wid = mpv_container->winId(); - mpv_set_option(mpv, "wid", MPV_FORMAT_INT64, &wid); - - // Enable default bindings, because we're lazy. Normally, a player using - // mpv as backend would implement its own key bindings. - mpv_set_option_string(mpv, "input-default-bindings", "yes"); - - // Enable keyboard input on the X11 window. For the messy details, see - // --input-vo-keyboard on the manpage. - mpv_set_option_string(mpv, "input-vo-keyboard", "yes"); - - // Let us receive property change events with MPV_EVENT_PROPERTY_CHANGE if - // this property changes. - mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE); - - mpv_observe_property(mpv, 0, "track-list", MPV_FORMAT_NODE); - mpv_observe_property(mpv, 0, "chapter-list", MPV_FORMAT_NODE); - - // Request log messages with level "info" or higher. - // They are received as MPV_EVENT_LOG_MESSAGE. - mpv_request_log_messages(mpv, "info"); - - // From this point on, the wakeup function will be called. The callback - // can come from any thread, so we use the QueuedConnection mechanism to - // relay the wakeup in a thread-safe way. - connect(this, &MainWindow::mpv_events, this, &MainWindow::on_mpv_events, - Qt::QueuedConnection); - mpv_set_wakeup_callback(mpv, wakeup, this); - - if (mpv_initialize(mpv) < 0) - throw std::runtime_error("mpv failed to initialize"); -} - -void MainWindow::handle_mpv_event(mpv_event *event) -{ - switch (event->event_id) { - case MPV_EVENT_PROPERTY_CHANGE: { - mpv_event_property *prop = (mpv_event_property *)event->data; - if (strcmp(prop->name, "time-pos") == 0) { - if (prop->format == MPV_FORMAT_DOUBLE) { - double time = *(double *)prop->data; - std::stringstream ss; - ss << "At: " << time; - statusBar()->showMessage(QString::fromStdString(ss.str())); - } else if (prop->format == MPV_FORMAT_NONE) { - // The property is unavailable, which probably means playback - // was stopped. - statusBar()->showMessage(""); - } - } else if (strcmp(prop->name, "chapter-list") == 0 || - strcmp(prop->name, "track-list") == 0) - { - // Dump the properties as JSON for demo purposes. -#if QT_VERSION >= 0x050000 - if (prop->format == MPV_FORMAT_NODE) { - QVariant v = mpv::qt::node_to_variant((mpv_node *)prop->data); - // Abuse JSON support for easily printing the mpv_node contents. - QJsonDocument d = QJsonDocument::fromVariant(v); - append_log("Change property " + QString(prop->name) + ":\n"); - append_log(d.toJson().data()); - } -#endif - } - break; - } - case MPV_EVENT_VIDEO_RECONFIG: { - // Retrieve the new video size. - int64_t w, h; - if (mpv_get_property(mpv, "dwidth", MPV_FORMAT_INT64, &w) >= 0 && - mpv_get_property(mpv, "dheight", MPV_FORMAT_INT64, &h) >= 0 && - w > 0 && h > 0) - { - // Note that the MPV_EVENT_VIDEO_RECONFIG event doesn't necessarily - // imply a resize, and you should check yourself if the video - // dimensions really changed. - // mpv itself will scale/letter box the video to the container size - // if the video doesn't fit. - std::stringstream ss; - ss << "Reconfig: " << w << " " << h; - statusBar()->showMessage(QString::fromStdString(ss.str())); - } - break; - } - case MPV_EVENT_LOG_MESSAGE: { - struct mpv_event_log_message *msg = (struct mpv_event_log_message *)event->data; - std::stringstream ss; - ss << "[" << msg->prefix << "] " << msg->level << ": " << msg->text; - append_log(QString::fromStdString(ss.str())); - break; - } - case MPV_EVENT_SHUTDOWN: { - mpv_terminate_destroy(mpv); - mpv = NULL; - break; - } - default: ; - // Ignore uninteresting or unknown events. - } -} - -// This slot is invoked by wakeup() (through the mpv_events signal). -void MainWindow::on_mpv_events() -{ - // Process all events, until the event queue is empty. - while (mpv) { - mpv_event *event = mpv_wait_event(mpv, 0); - if (event->event_id == MPV_EVENT_NONE) - break; - handle_mpv_event(event); - } -} - -void MainWindow::on_file_open() -{ - QString filename = QFileDialog::getOpenFileName(this, "Open file"); - if (mpv) { - const QByteArray c_filename = filename.toUtf8(); - const char *args[] = {"loadfile", c_filename.data(), NULL}; - mpv_command_async(mpv, 0, args); - } -} - -void MainWindow::on_new_window() -{ - (new MainWindow())->show(); -} - -void MainWindow::append_log(const QString &text) -{ - QTextCursor cursor = log->textCursor(); - cursor.movePosition(QTextCursor::End); - cursor.insertText(text); - log->setTextCursor(cursor); -} - -MainWindow::~MainWindow() -{ - if (mpv) - mpv_terminate_destroy(mpv); -} - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - - // Qt sets the locale in the QApplication constructor, but libmpv requires - // the LC_NUMERIC category to be set to "C", so change it back. - std::setlocale(LC_NUMERIC, "C"); - - MainWindow w; - w.show(); - - return a.exec(); -} diff --git a/DOCS/client_api_examples/qt/qtexample.h b/DOCS/client_api_examples/qt/qtexample.h deleted file mode 100644 index c3891cf4a7..0000000000 --- a/DOCS/client_api_examples/qt/qtexample.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef QTEXAMPLE_H -#define QTEXAMPLE_H - -#include <QMainWindow> - -#include <mpv/client.h> - -class QTextEdit; - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - explicit MainWindow(QWidget *parent = 0); - ~MainWindow(); - -private slots: - void on_file_open(); - void on_new_window(); - void on_mpv_events(); - -signals: - void mpv_events(); - -private: - QWidget *mpv_container; - mpv_handle *mpv; - QTextEdit *log; - - void append_log(const QString &text); - - void create_player(); - void handle_mpv_event(mpv_event *event); -}; - -#endif // QTEXAMPLE_H diff --git a/DOCS/client_api_examples/qt/qtexample.pro b/DOCS/client_api_examples/qt/qtexample.pro deleted file mode 100644 index 7c0a6ade02..0000000000 --- a/DOCS/client_api_examples/qt/qtexample.pro +++ /dev/null @@ -1,13 +0,0 @@ -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -TARGET = qtexample -TEMPLATE = app - -QT_CONFIG -= no-pkg-config -CONFIG += link_pkgconfig debug -PKGCONFIG += mpv - -SOURCES += qtexample.cpp -HEADERS += qtexample.h diff --git a/DOCS/client_api_examples/qt_opengl/main.cpp b/DOCS/client_api_examples/qt_opengl/main.cpp deleted file mode 100644 index 086a4b4617..0000000000 --- a/DOCS/client_api_examples/qt_opengl/main.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include <QApplication> -#include "mainwindow.h" - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - // Qt sets the locale in the QApplication constructor, but libmpv requires - // the LC_NUMERIC category to be set to "C", so change it back. - setlocale(LC_NUMERIC, "C"); - MainWindow w; - w.show(); - return a.exec(); -} diff --git a/DOCS/client_api_examples/qt_opengl/mainwindow.cpp b/DOCS/client_api_examples/qt_opengl/mainwindow.cpp deleted file mode 100644 index 3ecd0a196d..0000000000 --- a/DOCS/client_api_examples/qt_opengl/mainwindow.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "mainwindow.h" -#include "mpvwidget.h" -#include <QPushButton> -#include <QSlider> -#include <QLayout> -#include <QFileDialog> - -MainWindow::MainWindow(QWidget *parent) : QWidget(parent) -{ - m_mpv = new MpvWidget(this); - m_slider = new QSlider(); - m_slider->setOrientation(Qt::Horizontal); - m_openBtn = new QPushButton("Open"); - m_playBtn = new QPushButton("Pause"); - QHBoxLayout *hb = new QHBoxLayout(); - hb->addWidget(m_openBtn); - hb->addWidget(m_playBtn); - QVBoxLayout *vl = new QVBoxLayout(); - vl->addWidget(m_mpv); - vl->addWidget(m_slider); - vl->addLayout(hb); - setLayout(vl); - connect(m_slider, SIGNAL(sliderMoved(int)), SLOT(seek(int))); - connect(m_openBtn, SIGNAL(clicked()), SLOT(openMedia())); - connect(m_playBtn, SIGNAL(clicked()), SLOT(pauseResume())); - connect(m_mpv, SIGNAL(positionChanged(int)), m_slider, SLOT(setValue(int))); - connect(m_mpv, SIGNAL(durationChanged(int)), this, SLOT(setSliderRange(int))); -} - -void MainWindow::openMedia() -{ - QString file = QFileDialog::getOpenFileName(0, "Open a video"); - if (file.isEmpty()) - return; - m_mpv->command(QStringList() << "loadfile" << file); -} - -void MainWindow::seek(int pos) -{ - m_mpv->command(QVariantList() << "seek" << pos << "absolute"); -} - -void MainWindow::pauseResume() -{ - const bool paused = m_mpv->getProperty("pause").toBool(); - m_mpv->setProperty("pause", !paused); -} - -void MainWindow::setSliderRange(int duration) -{ - m_slider->setRange(0, duration); -} diff --git a/DOCS/client_api_examples/qt_opengl/mainwindow.h b/DOCS/client_api_examples/qt_opengl/mainwindow.h deleted file mode 100644 index 523b385bb4..0000000000 --- a/DOCS/client_api_examples/qt_opengl/mainwindow.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef MainWindow_H -#define MainWindow_H - -#include <QtWidgets/QWidget> - -class MpvWidget; -class QSlider; -class QPushButton; -class MainWindow : public QWidget -{ - Q_OBJECT -public: - explicit MainWindow(QWidget *parent = 0); -public Q_SLOTS: - void openMedia(); - void seek(int pos); - void pauseResume(); -private Q_SLOTS: - void setSliderRange(int duration); -private: - MpvWidget *m_mpv; - QSlider *m_slider; - QPushButton *m_openBtn; - QPushButton *m_playBtn; -}; - -#endif // MainWindow_H diff --git a/DOCS/client_api_examples/qt_opengl/mpvwidget.cpp b/DOCS/client_api_examples/qt_opengl/mpvwidget.cpp deleted file mode 100644 index 4d2cad6241..0000000000 --- a/DOCS/client_api_examples/qt_opengl/mpvwidget.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#include "mpvwidget.h" -#include <stdexcept> -#include <QtGui/QOpenGLContext> -#include <QtCore/QMetaObject> - -static void wakeup(void *ctx) -{ - QMetaObject::invokeMethod((MpvWidget*)ctx, "on_mpv_events", Qt::QueuedConnection); -} - -static void *get_proc_address(void *ctx, const char *name) { - Q_UNUSED(ctx); - QOpenGLContext *glctx = QOpenGLContext::currentContext(); - if (!glctx) - return NULL; - return (void *)glctx->getProcAddress(QByteArray(name)); -} - -MpvWidget::MpvWidget(QWidget *parent, Qt::WindowFlags f) - : QOpenGLWidget(parent, f) -{ - mpv = mpv::qt::Handle::FromRawHandle(mpv_create()); - if (!mpv) - throw std::runtime_error("could not create mpv context"); - - mpv_set_option_string(mpv, "terminal", "yes"); - mpv_set_option_string(mpv, "msg-level", "all=v"); - if (mpv_initialize(mpv) < 0) - throw std::runtime_error("could not initialize mpv context"); - - // Make use of the MPV_SUB_API_OPENGL_CB API. - mpv::qt::set_option_variant(mpv, "vo", "opengl-cb"); - - // Request hw decoding, just for testing. - mpv::qt::set_option_variant(mpv, "hwdec", "auto"); - - mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB); - if (!mpv_gl) - throw std::runtime_error("OpenGL not compiled in"); - mpv_opengl_cb_set_update_callback(mpv_gl, MpvWidget::on_update, (void *)this); - connect(this, SIGNAL(frameSwapped()), SLOT(swapped())); - - mpv_observe_property(mpv, 0, "duration", MPV_FORMAT_DOUBLE); - mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE); - mpv_set_wakeup_callback(mpv, wakeup, this); -} - -MpvWidget::~MpvWidget() -{ - makeCurrent(); - if (mpv_gl) - mpv_opengl_cb_set_update_callback(mpv_gl, NULL, NULL); - // Until this call is done, we need to make sure the player remains - // alive. This is done implicitly with the mpv::qt::Handle instance - // in this class. - mpv_opengl_cb_uninit_gl(mpv_gl); -} - -void MpvWidget::command(const QVariant& params) -{ - mpv::qt::command_variant(mpv, params); -} - -void MpvWidget::setProperty(const QString& name, const QVariant& value) -{ - mpv::qt::set_property_variant(mpv, name, value); -} - -QVariant MpvWidget::getProperty(const QString &name) const -{ - return mpv::qt::get_property_variant(mpv, name); -} - -void MpvWidget::initializeGL() -{ - int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL); - if (r < 0) - throw std::runtime_error("could not initialize OpenGL"); -} - -void MpvWidget::paintGL() -{ - mpv_opengl_cb_draw(mpv_gl, defaultFramebufferObject(), width(), -height()); -} - -void MpvWidget::swapped() -{ - mpv_opengl_cb_report_flip(mpv_gl, 0); -} - -void MpvWidget::on_mpv_events() -{ - // Process all events, until the event queue is empty. - while (mpv) { - mpv_event *event = mpv_wait_event(mpv, 0); - if (event->event_id == MPV_EVENT_NONE) { - break; - } - handle_mpv_event(event); - } -} - -void MpvWidget::handle_mpv_event(mpv_event *event) -{ - switch (event->event_id) { - case MPV_EVENT_PROPERTY_CHANGE: { - mpv_event_property *prop = (mpv_event_property *)event->data; - if (strcmp(prop->name, "time-pos") == 0) { - if (prop->format == MPV_FORMAT_DOUBLE) { - double time = *(double *)prop->data; - Q_EMIT positionChanged(time); - } - } else if (strcmp(prop->name, "duration") == 0) { - if (prop->format == MPV_FORMAT_DOUBLE) { - double time = *(double *)prop->data; - Q_EMIT durationChanged(time); - } - } - break; - } - default: ; - // Ignore uninteresting or unknown events. - } -} - -void MpvWidget::on_update(void *ctx) -{ - QMetaObject::invokeMethod((MpvWidget*)ctx, "update"); -} diff --git a/DOCS/client_api_examples/qt_opengl/mpvwidget.h b/DOCS/client_api_examples/qt_opengl/mpvwidget.h deleted file mode 100644 index a219681393..0000000000 --- a/DOCS/client_api_examples/qt_opengl/mpvwidget.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef PLAYERWINDOW_H -#define PLAYERWINDOW_H - -#include <QtWidgets/QOpenGLWidget> -#include <mpv/client.h> -#include <mpv/opengl_cb.h> -#include <mpv/qthelper.hpp> - -class MpvWidget Q_DECL_FINAL: public QOpenGLWidget -{ - Q_OBJECT -public: - MpvWidget(QWidget *parent = 0, Qt::WindowFlags f = 0); - ~MpvWidget(); - void command(const QVariant& params); - void setProperty(const QString& name, const QVariant& value); - QVariant getProperty(const QString& name) const; - QSize sizeHint() const { return QSize(480, 270);} -Q_SIGNALS: - void durationChanged(int value); - void positionChanged(int value); -protected: - void initializeGL() Q_DECL_OVERRIDE; - void paintGL() Q_DECL_OVERRIDE; -private Q_SLOTS: - void swapped(); - void on_mpv_events(); -private: - void handle_mpv_event(mpv_event *event); - static void on_update(void *ctx); - - mpv::qt::Handle mpv; - mpv_opengl_cb_context *mpv_gl; -}; - - - -#endif // PLAYERWINDOW_H diff --git a/DOCS/client_api_examples/qt_opengl/qt_opengl.pro b/DOCS/client_api_examples/qt_opengl/qt_opengl.pro deleted file mode 100644 index 8a2bcc665d..0000000000 --- a/DOCS/client_api_examples/qt_opengl/qt_opengl.pro +++ /dev/null @@ -1,13 +0,0 @@ -CONFIG -= app_bundle -QT += widgets - -QT_CONFIG -= no-pkg-config -CONFIG += link_pkgconfig debug -PKGCONFIG += mpv - -HEADERS = \ - mpvwidget.h \ - mainwindow.h -SOURCES = main.cpp \ - mpvwidget.cpp \ - mainwindow.cpp diff --git a/DOCS/client_api_examples/sdl/main.c b/DOCS/client_api_examples/sdl/main.c deleted file mode 100644 index b3b5952668..0000000000 --- a/DOCS/client_api_examples/sdl/main.c +++ /dev/null @@ -1,158 +0,0 @@ -// Build with: gcc -o main main.c `pkg-config --libs --cflags mpv sdl2` - -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -#include <SDL.h> - -#include <mpv/client.h> -#include <mpv/opengl_cb.h> - -static Uint32 wakeup_on_mpv_redraw, wakeup_on_mpv_events; - -static void die(const char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -static void *get_proc_address_mpv(void *fn_ctx, const char *name) -{ - return SDL_GL_GetProcAddress(name); -} - -static void on_mpv_events(void *ctx) -{ - SDL_Event event = {.type = wakeup_on_mpv_events}; - SDL_PushEvent(&event); -} - -static void on_mpv_redraw(void *ctx) -{ - SDL_Event event = {.type = wakeup_on_mpv_redraw}; - SDL_PushEvent(&event); -} - -int main(int argc, char *argv[]) -{ - if (argc != 2) - die("pass a single media file as argument"); - - mpv_handle *mpv = mpv_create(); - if (!mpv) - die("context init failed"); - - // Some minor options can only be set before mpv_initialize(). - if (mpv_initialize(mpv) < 0) - die("mpv init failed"); - - if (SDL_Init(SDL_INIT_VIDEO) < 0) - die("SDL init failed"); - - SDL_Window *window = - SDL_CreateWindow("hi", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - 1000, 500, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | - SDL_WINDOW_RESIZABLE); - if (!window) - die("failed to create SDL window"); - - // The OpenGL API is somewhat separate from the normal mpv API. This only - // returns NULL if no OpenGL support is compiled. - mpv_opengl_cb_context *mpv_gl = mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB); - if (!mpv_gl) - die("failed to create mpv GL API handle"); - - SDL_GLContext glcontext = SDL_GL_CreateContext(window); - if (!glcontext) - die("failed to create SDL GL context"); - - // This makes mpv use the currently set GL context. It will use the callback - // to resolve GL builtin functions, as well as extensions. - if (mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address_mpv, NULL) < 0) - die("failed to initialize mpv GL context"); - - // Actually using the opengl_cb state has to be explicitly requested. - // Otherwise, mpv will create a separate platform window. - if (mpv_set_option_string(mpv, "vo", "opengl-cb") < 0) - die("failed to set VO"); - - // We use events for thread-safe notification of the SDL main loop. - // Generally, the wakeup callbacks (set further below) should do as least - // work as possible, and merely wake up another thread to do actual work. - // On SDL, waking up the mainloop is the ideal course of action. SDL's - // SDL_PushEvent() is thread-safe, so we use that. - wakeup_on_mpv_redraw = SDL_RegisterEvents(1); - wakeup_on_mpv_events = SDL_RegisterEvents(1); - if (wakeup_on_mpv_redraw == (Uint32)-1 || wakeup_on_mpv_events == (Uint32)-1) - die("could not register events"); - - // When normal mpv events are available. - mpv_set_wakeup_callback(mpv, on_mpv_events, NULL); - - // When a new frame should be drawn with mpv_opengl_cb_draw(). - // (Separate from the normal event handling mechanism for the sake of - // users which run OpenGL on a different thread.) - mpv_opengl_cb_set_update_callback(mpv_gl, on_mpv_redraw, NULL); - - // Play this file. Note that this starts playback asynchronously. - const char *cmd[] = {"loadfile", argv[1], NULL}; - mpv_command(mpv, cmd); - - while (1) { - SDL_Event event; - if (SDL_WaitEvent(&event) != 1) - die("event loop error"); - int redraw = 0; - switch (event.type) { - case SDL_QUIT: - goto done; - case SDL_WINDOWEVENT: - if (event.window.event == SDL_WINDOWEVENT_EXPOSED) - redraw = 1; - break; - case SDL_KEYDOWN: - if (event.key.keysym.sym == SDLK_SPACE) - mpv_command_string(mpv, "cycle pause"); - break; - default: - // Happens when a new video frame should be rendered, or if the - // current frame has to be redrawn e.g. due to OSD changes. - if (event.type == wakeup_on_mpv_redraw) - redraw = 1; - // Happens when at least 1 new event is in the mpv event queue. - if (event.type == wakeup_on_mpv_events) { - // Handle all remaining mpv events. - while (1) { - mpv_event *mp_event = mpv_wait_event(mpv, 0); - if (mp_event->event_id == MPV_EVENT_NONE) - break; - printf("event: %s\n", mpv_event_name(mp_event->event_id)); - } - } - } - if (redraw) { - int w, h; - SDL_GetWindowSize(window, &w, &h); - // Note: - // - The 0 is the FBO to use; 0 is the default framebuffer (i.e. - // render to the window directly. - // - The negative height tells mpv to flip the coordinate system. - // - If you do not want the video to cover the whole screen, or want - // to apply any form of fancy transformation, you will have to - // render to a FBO. - // - See opengl_cb.h on what OpenGL environment mpv expects, and - // other API details. - mpv_opengl_cb_draw(mpv_gl, 0, w, -h); - SDL_GL_SwapWindow(window); - } - } -done: - - // Destroy the GL renderer and all of the GL objects it allocated. If video - // is still running, the video track will be deselected. - mpv_opengl_cb_uninit_gl(mpv_gl); - - mpv_terminate_destroy(mpv); - return 0; -} diff --git a/DOCS/client_api_examples/simple/simple.c b/DOCS/client_api_examples/simple/simple.c deleted file mode 100644 index 3ba1c35686..0000000000 --- a/DOCS/client_api_examples/simple/simple.c +++ /dev/null @@ -1,54 +0,0 @@ -// Build with: gcc -o simple simple.c `pkg-config --libs --cflags mpv` - -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -#include <mpv/client.h> - -static inline void check_error(int status) -{ - if (status < 0) { - printf("mpv API error: %s\n", mpv_error_string(status)); - exit(1); - } -} - -int main(int argc, char *argv[]) -{ - if (argc != 2) { - printf("pass a single media file as argument\n"); - return 1; - } - - mpv_handle *ctx = mpv_create(); - if (!ctx) { - printf("failed creating context\n"); - return 1; - } - - // Enable default key bindings, so the user can actually interact with - // the player (and e.g. close the window). - check_error(mpv_set_option_string(ctx, "input-default-bindings", "yes")); - mpv_set_option_string(ctx, "input-vo-keyboard", "yes"); - int val = 1; - check_error(mpv_set_option(ctx, "osc", MPV_FORMAT_FLAG, &val)); - - // Done setting up options. - check_error(mpv_initialize(ctx)); - - // Play this file. - const char *cmd[] = {"loadfile", argv[1], NULL}; - check_error(mpv_command(ctx, cmd)); - - // Let it play, and wait until the user quits. - while (1) { - mpv_event *event = mpv_wait_event(ctx, 10000); - printf("event: %s\n", mpv_event_name(event->event_id)); - if (event->event_id == MPV_EVENT_SHUTDOWN) - break; - } - - mpv_terminate_destroy(ctx); - return 0; -} |