1 /*
2 * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
3 *
4 * This is free software: you can redistribute it and/or modify
5 * it under the terms of the Artistic License 2.0 as published by
6 * The Perl Foundation.
7 *
8 * This source is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * Artistic License 2.0 for more details.
12 *
13 * You should have received a copy of the Artistic License 2.0
14 * along the source as a COPYING file. If not, obtain it from
15 * http://www.perlfoundation.org/artistic_license_2_0.
16 */
17
18 #include <stdatomic.h>
19 #include <stdbool.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <signal.h>
24 #include <time.h>
25
26 #define CROSS_CLOCK_IMPLEMENTATION
27 #include <cross_clock/cross_clock.h>
28
29 #include <sandbox_slave.h>
30 #include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
31
32 typedef struct _app_t app_t;
33
34 struct _app_t {
35 sandbox_slave_t *sb;
36 LV2UI_Handle *handle;
37 const LV2UI_Idle_Interface *idle_iface;
38 const LV2UI_Show_Interface *show_iface;
39 cross_clock_t clk_mono;
40 };
41
42 static atomic_bool done = ATOMIC_VAR_INIT(false);
43
44 static inline void
_sig(int signum)45 _sig(int signum)
46 {
47 atomic_store_explicit(&done, true, memory_order_relaxed);
48 }
49
50 static inline int
_init(sandbox_slave_t * sb,void * data)51 _init(sandbox_slave_t *sb, void *data)
52 {
53 app_t *app= data;
54
55 signal(SIGINT, _sig);
56
57 void *widget = NULL;
58 if(!(app->handle = sandbox_slave_instantiate(sb, NULL, &widget)))
59 return -1;
60
61 app->idle_iface = sandbox_slave_extension_data(sb, LV2_UI__idleInterface);
62 app->show_iface = sandbox_slave_extension_data(sb, LV2_UI__showInterface);
63
64 if(app->show_iface)
65 app->show_iface->show(app->handle);
66
67 cross_clock_init(&app->clk_mono, CROSS_CLOCK_MONOTONIC);
68
69 return 0; //success
70 }
71
72 static inline void
_run(sandbox_slave_t * sb,float update_rate,void * data)73 _run(sandbox_slave_t *sb, float update_rate, void *data)
74 {
75 app_t *app = data;
76 const unsigned ns = 1000000000 / update_rate;
77 struct timespec to;
78 cross_clock_gettime(&app->clk_mono, &to);
79
80 while(!atomic_load_explicit(&done, memory_order_relaxed))
81 {
82 to.tv_nsec += ns;
83 while(to.tv_nsec >= 1000000000)
84 {
85 to.tv_nsec -= 1000000000;
86 to.tv_sec += 1;
87 }
88
89 cross_clock_nanosleep(&app->clk_mono, true, &to);
90
91 if(sandbox_slave_recv(sb))
92 atomic_store_explicit(&done, true, memory_order_relaxed);
93 if(app->idle_iface)
94 {
95 if(app->idle_iface->idle(app->handle))
96 atomic_store_explicit(&done, true, memory_order_relaxed);
97 }
98 }
99
100 if(app->show_iface)
101 app->show_iface->hide(app->handle);
102 }
103
104 static inline void
_deinit(void * data)105 _deinit(void *data)
106 {
107 app_t *app = data;
108
109 cross_clock_deinit(&app->clk_mono);
110 }
111
112 static const sandbox_slave_driver_t driver = {
113 .init_cb = _init,
114 .run_cb = _run,
115 .deinit_cb = _deinit,
116 .resize_cb = NULL
117 };
118
119 int
main(int argc,char ** argv)120 main(int argc, char **argv)
121 {
122 static app_t app;
123 int res;
124
125 app.sb = sandbox_slave_new(argc, argv, &driver, &app, &res);
126 if(app.sb)
127 {
128 sandbox_slave_run(app.sb);
129 sandbox_slave_free(app.sb);
130 return res;
131 }
132
133 return res;
134 }
135