summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAman Gupta <aman@tmm1.net>2016-08-07 19:41:07 +0200
committerwm4 <wm4@nowhere>2016-08-07 19:41:34 +0200
commitce0491a176bcc29b8655a832061708dde7a38b64 (patch)
tree82d293fa13e668cfad9c2b00bb28d632934463d3
parentca6be6fc155a98d02ef9fcd8085cff750c4efebd (diff)
downloadmpv-examples-ce0491a176bcc29b8655a832061708dde7a38b64.tar.bz2
mpv-examples-ce0491a176bcc29b8655a832061708dde7a38b64.tar.xz
Add stream_cb example
Signed-off-by: wm4 <wm4@nowhere>
-rw-r--r--libmpv/README.md5
-rw-r--r--libmpv/streamcb/simple-streamcb.c99
2 files changed, 104 insertions, 0 deletions
diff --git a/libmpv/README.md b/libmpv/README.md
index f1b7828..cc9e5dd 100644
--- a/libmpv/README.md
+++ b/libmpv/README.md
@@ -118,3 +118,8 @@ video is not a normal QML element. Uses the opengl-cb API for video.
Show how to embed the mpv OpenGL renderer in SDL. Uses the opengl-cb API for
video.
+
+### streamcb
+
+Demonstrates use of the custom stream API.
+
diff --git a/libmpv/streamcb/simple-streamcb.c b/libmpv/streamcb/simple-streamcb.c
new file mode 100644
index 0000000..cec7725
--- /dev/null
+++ b/libmpv/streamcb/simple-streamcb.c
@@ -0,0 +1,99 @@
+// Build with: gcc -o simple-streamcb simple-streamcb.c `pkg-config --libs --cflags mpv`
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mpv/client.h>
+#include <mpv/stream_cb.h>
+
+static int64_t read_fn(void *cookie, char *buf, uint64_t nbytes)
+{
+ FILE *fp = cookie;
+ size_t ret = fread(buf, 1, nbytes, fp);
+ if (ret == 0) {
+ return feof(fp) ? 0 : -1;
+ }
+ return ret;
+}
+
+static int64_t seek_fn(void *cookie, int64_t offset)
+{
+ FILE *fp = cookie;
+ // not 64-bit safe
+ int r = fseek(fp, offset, SEEK_SET);
+ return r < 0 ? MPV_ERROR_GENERIC : r;
+}
+
+static void close_fn(void *cookie)
+{
+ FILE *fp = cookie;
+ fclose(fp);
+}
+
+static int open_fn(void *user_data, char *uri, mpv_stream_cb_info *info)
+{
+ FILE *fp = fopen((char *)user_data, "r");
+ info->cookie = fp;
+ info->read_fn = read_fn;
+ info->seek_fn = seek_fn;
+ info->close_fn = close_fn;
+ return fp ? 0 : MPV_ERROR_LOADING_FAILED;
+}
+
+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));
+
+ check_error(mpv_request_log_messages(ctx, "v"));
+
+ check_error(mpv_stream_cb_add_ro(ctx, "myprotocol", argv[1], open_fn));
+
+ // Play this file.
+ const char *cmd[] = {"loadfile", "myprotocol://fake", 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);
+ if (event->event_id == 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);
+ continue;
+ }
+ printf("event: %s\n", mpv_event_name(event->event_id));
+ if (event->event_id == MPV_EVENT_SHUTDOWN)
+ break;
+ }
+
+ mpv_terminate_destroy(ctx);
+ return 0;
+}