forked from avilleret/gem-mpv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgem_mpv.hpp
199 lines (179 loc) · 5.08 KB
/
gem_mpv.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#pragma once
#include "gemframebuffer.h"
#include <mpv/client.h>
#include <mpv/render_gl.h>
#include <atomic>
#include <string.h>
// some helper functions
// from qthelper.hpp (see qt_opengl in mpv-examples)
struct node_builder {
node_builder(int argc, t_atom* argv, std::string types = {}) {
m_types=types;
char type{};
if(!m_types.empty())
type = m_types.at(0);
set(&node_, argc, argv, type);
}
~node_builder() {
free_node(&node_);
}
mpv_node *node() { return &node_; }
private:
// disable copy by making copy constructor
// and copy assignment operators private
node_builder(const node_builder&);
node_builder& operator=(const node_builder&);
mpv_node node_;
std::string m_types;
unsigned int m_index;
mpv_node_list *create_list(mpv_node *dst, bool is_map, int num) {
dst->format = is_map ? MPV_FORMAT_NODE_MAP : MPV_FORMAT_NODE_ARRAY;
mpv_node_list *list = new mpv_node_list();
dst->u.list = list;
if (!list)
goto err;
list->values = new mpv_node[num]();
if (!list->values)
goto err;
if (is_map) {
list->keys = new char*[num]();
if (!list->keys)
goto err;
}
return list;
err:
free_node(dst);
return NULL;
}
/*
char *dup_qstring(const QString &s) {
QByteArray b = s.toUtf8();
char *r = new char[b.size() + 1];
if (r)
std::memcpy(r, b.data(), b.size() + 1);
return r;
}
bool test_type(const QVariant &v, QMetaType::Type t) {
// The Qt docs say: "Although this function is declared as returning
// "QVariant::Type(obsolete), the return value should be interpreted
// as QMetaType::Type."
// So a cast really seems to be needed to avoid warnings (urgh).
return static_cast<int>(v.type()) == static_cast<int>(t);
}
*/
void set(mpv_node *dst, int argc, t_atom* argv, char type = 0) {
if(argc == 1)
{
if (argv->a_type == A_SYMBOL) {
t_symbol* s = argv->a_w.w_symbol;
if(!s)
return;
dst->format = MPV_FORMAT_STRING;
dst->u.string = strdup(s->s_name);
if (!dst->u.string)
goto fail;
} else if (argv->a_type == A_FLOAT) {
float f = argv->a_w.w_float;
switch(type)
{
case 'b':
dst->format = MPV_FORMAT_FLAG;
dst->u.flag = f > 0;
break;
case 'i':
dst->format = MPV_FORMAT_INT64;
dst->u.int64 = f;
break;
case 'd':
default:
dst->format = MPV_FORMAT_DOUBLE;
dst->u.double_ = f;
}
}
}
else
{
mpv_node_list *list = create_list(dst, false, argc);
if (!list)
goto fail;
list->num = argc;
for (int n = 0; n < argc; n++)
{
char tag{};
if(m_types != std::string{})
{
if(n > m_types.size())
{
error("types size < argc");
}
else
tag = m_types.at(n);
}
set(&list->values[n], 1, argv+n, tag);
}
}
return;
fail:
error("can't process command");
dst->format = MPV_FORMAT_NONE;
}
void free_node(mpv_node *dst) {
switch (dst->format) {
case MPV_FORMAT_STRING:
delete[] dst->u.string;
break;
case MPV_FORMAT_NODE_ARRAY:
case MPV_FORMAT_NODE_MAP: {
mpv_node_list *list = dst->u.list;
if (list) {
for (int n = 0; n < list->num; n++) {
if (list->keys)
delete[] list->keys[n];
if (list->values)
free_node(&list->values[n]);
}
delete[] list->keys;
delete[] list->values;
}
delete list;
break;
}
default: ;
}
dst->format = MPV_FORMAT_NONE;
}
};
struct node_autofree {
mpv_node *ptr;
node_autofree(mpv_node *a_ptr) : ptr(a_ptr) {}
~node_autofree() { mpv_free_node_contents(ptr); }
};
class GEM_EXTERN mpv : public gemframebuffer
{
CPPEXTERN_HEADER(mpv, GemBase);
public:
mpv(int argc, t_atom*argv);
~mpv();
void startRendering(void);
void stopRendering(void);
void render(GemState *state);
void postrender(GemState *state);
void command_mess(t_symbol* s, int argc, t_atom* argv);
void dimen_mess(int width, int height);
void log_mess(std::string);
void inline rise_event_flag(){ m_event_flag = true; };
private:
void handle_prop_event(mpv_event_property* prop);
mpv_handle* m_mpv{};
mpv_render_context* m_mpv_gl{};
bool m_pause{};
std::atomic_bool m_event_flag; // flag rised when new event arrived
bool m_auto_resize{};
bool m_started{};
bool m_reload{};
bool m_new_frame{};
int64_t m_media_width{512};
int64_t m_media_height{512};
t_outlet* m_prop_outlet{};
std::vector<t_atom> m_loadfile_cmd;
};