summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergio Padrino <sergio.padrino@gmail.com>2017-07-15 12:30:40 +0200
committerwm4 <wm4@nowhere>2017-08-03 16:39:41 +0200
commitf5cb6e5de4fe01355eb6b73d88197e1085506677 (patch)
treefa8a240d0452a9acf1105ea432725acd44fc9a58
parentad72c56b4c054fe9537b8d9cc1d8f0908fe25252 (diff)
downloadmpv-examples-f5cb6e5de4fe01355eb6b73d88197e1085506677.tar.bz2
mpv-examples-f5cb6e5de4fe01355eb6b73d88197e1085506677.tar.xz
Add iOS example using libmpv
-rw-r--r--libmpv/ios/ViewController.h7
-rw-r--r--libmpv/ios/ViewController.m209
2 files changed, 216 insertions, 0 deletions
diff --git a/libmpv/ios/ViewController.h b/libmpv/ios/ViewController.h
new file mode 100644
index 0000000..a79652b
--- /dev/null
+++ b/libmpv/ios/ViewController.h
@@ -0,0 +1,7 @@
+#import <UIKit/UIKit.h>
+
+@interface ViewController : UIViewController
+
+
+@end
+
diff --git a/libmpv/ios/ViewController.m b/libmpv/ios/ViewController.m
new file mode 100644
index 0000000..ddd71e7
--- /dev/null
+++ b/libmpv/ios/ViewController.m
@@ -0,0 +1,209 @@
+@import GLKit;
+@import OpenGLES;
+
+#import "ViewController.h"
+
+
+#import <mpv/client.h>
+#import <mpv/opengl_cb.h>
+
+#import <stdio.h>
+#import <stdlib.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.opengles")), symbolName);
+ CFRelease(symbolName);
+ return addr;
+}
+
+static void glupdate(void *ctx);
+
+@interface MpvClientOGLView : GLKView
+ @property mpv_opengl_cb_context *mpvGL;
+@end
+
+@implementation MpvClientOGLView {
+ GLint defaultFBO;
+}
+
+- (void)awakeFromNib
+{
+ [super awakeFromNib];
+ self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
+ [EAGLContext setCurrentContext:self.context];
+
+ // Configure renderbuffers created by the view
+ self.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
+ self.drawableDepthFormat = GLKViewDrawableDepthFormatNone;
+ self.drawableStencilFormat = GLKViewDrawableStencilFormatNone;
+
+ defaultFBO = -1;
+}
+
+- (void)fillBlack
+{
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+- (void)drawRect
+{
+ if (defaultFBO == -1)
+ {
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
+ }
+
+ if (self.mpvGL)
+ {
+ mpv_opengl_cb_draw(self.mpvGL,
+ defaultFBO,
+ self.bounds.size.width * self.contentScaleFactor,
+ -self.bounds.size.height * self.contentScaleFactor);
+ }
+}
+
+- (void)drawRect:(CGRect)rect
+{
+ [self drawRect];
+}
+
+@end
+
+
+
+static void wakeup(void *);
+
+
+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 display];
+ });
+}
+
+
+@interface ViewController ()
+
+@property (nonatomic) IBOutlet MpvClientOGLView *glView;
+- (void) readEvents;
+
+@end
+
+static void wakeup(void *context)
+{
+ ViewController *a = (__bridge ViewController *) context;
+ [a readEvents];
+}
+
+
+
+@implementation ViewController {
+ mpv_handle *mpv;
+ dispatch_queue_t queue;
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // Do any additional setup after loading the view, typically from a nib.
+
+ mpv = mpv_create();
+ if (!mpv) {
+ printf("failed creating context\n");
+ exit(1);
+ }
+
+ // request important errors
+ NSString *logFile = [NSTemporaryDirectory() stringByAppendingPathComponent:@"mpv-log.txt"];
+ NSLog(@"%@", logFile);
+ check_error(mpv_set_option_string(mpv, "log-file", logFile.UTF8String));
+ 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);
+ }
+
+ [self.glView display];
+
+ // pass the mpvGL context to our view
+ self.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 *)self.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", "http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_640x360.m4v", NULL};
+ check_error(mpv_command(mpv, cmd));
+ check_error(mpv_set_option_string(mpv, "loop", "inf"));
+ });
+}
+
+- (void)didReceiveMemoryWarning
+{
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+- (void)handleEvent:(mpv_event *)event
+{
+ switch (event->event_id) {
+ case MPV_EVENT_SHUTDOWN: {
+ mpv_detach_destroy(mpv);
+ mpv_opengl_cb_uninit_gl(self.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)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];
+ }
+ });
+}
+
+@end