Changeset 51bb400466101d3a545817ba7e27f9d25568ab51
- Timestamp:
- 07/04/09 01:15:59 (3 years ago)
- Children:
- b05530c4ff96e00046ae4e9555794b66265081b2
- Parents:
- c6dad257c20c3ef9c3f58a6f82ce1d1077782fe6
- git-committer:
- Nedko Arnaudov <nedko@arnaudov.name> / 2009-07-04T01:15:59Z+0300
- Files:
-
- 2 modified
Legend:
- Unmodified
- Added
- Removed
-
lv2_ui.c
rb22a23b r51bb400 33 33 #include <sys/types.h> 34 34 #include <unistd.h> 35 #include <fcntl.h> 36 #include <locale.h> 35 37 #include <errno.h> 36 37 #include <lo/lo.h>38 38 39 39 #include <lv2.h> … … 41 41 #include "lv2_external_ui.h" 42 42 43 #define MAX_OSC_PATH 102444 45 43 struct control 46 44 { … … 51 49 void (* ui_closed)(LV2UI_Controller controller); 52 50 53 lo_server osc_server;54 55 51 bool running; /* true if UI launched and 'exiting' not received */ 56 52 bool visible; /* true if 'show' sent */ 57 53 58 lo_address osc_address; /* non-NULL if 'update' received */ 59 60 char osc_control_path[MAX_OSC_PATH]; 61 char osc_hide_path[MAX_OSC_PATH]; 62 char osc_quit_path[MAX_OSC_PATH]; 63 char osc_show_path[MAX_OSC_PATH]; 54 int send_pipe; /* the pipe end that is used for sending messages to UI */ 55 int recv_pipe; /* the pipe end that is used for receiving messages from UI */ 64 56 }; 65 57 66 #undef control_ptr 67 68 static 69 int 70 osc_debug_handler( 71 const char * path, 72 const char * types, 73 lo_arg ** argv, 74 int argc, 75 void * data, 76 void * user_data) 77 { 78 int i; 79 80 printf("got unhandled OSC message:\n"); 81 printf("path: <%s>\n", path); 82 fflush(stdout); 83 for (i = 0; i < argc; i++) 84 { 85 printf("arg %d '%c' ", i, types[i]); 86 lo_arg_pp(types[i], argv[i]); 87 printf("\n"); 88 } 89 fflush(stdout); 90 91 return 1; 92 } 93 94 int 95 osc_exiting_handler( 96 struct control * control_ptr, 97 lo_arg ** argv) 98 { 99 //printf("OSC: got UI exit notification\n"); 100 101 control_ptr->running = false; 102 control_ptr->visible = false; 103 104 if (control_ptr->osc_address) 105 { 106 lo_address_free(control_ptr->osc_address); 107 } 108 109 control_ptr->ui_closed(control_ptr->controller); 110 111 return 0; 112 } 113 114 int 115 osc_control_handler( 116 struct control * control_ptr, 117 lo_arg ** argv) 118 { 119 int port = argv[0]->i; 120 float value = argv[1]->f; 121 122 //printf("OSC control handler: port %d = %f\n", port, value); 123 124 control_ptr->write_function(control_ptr->controller, (uint32_t)port, sizeof(float), 0, &value); 125 126 return 0; 127 } 128 129 int 130 osc_update_handler( 131 struct control * control_ptr, 132 lo_arg ** argv) 133 { 134 const char * url = &argv[0]->s; 135 char * path; 136 char * host; 137 char * port; 138 139 //printf("OSC: got update request from <%s>\n", url); 140 141 if (control_ptr->osc_address) 142 { 143 return 0; 144 } 145 146 host = lo_url_get_hostname(url); 147 port = lo_url_get_port(url); 148 control_ptr->osc_address = lo_address_new(host, port); 149 free(host); 150 free(port); 151 152 path = lo_url_get_path(url); 153 154 sprintf(control_ptr->osc_control_path, "%scontrol", path); 155 sprintf(control_ptr->osc_hide_path, "%shide", path); 156 sprintf(control_ptr->osc_show_path, "%sshow", path); 157 sprintf(control_ptr->osc_quit_path, "%squit", path); 158 159 free(path); 160 161 control_ptr->running = true; 162 163 return 0; 164 } 165 166 #define control_ptr ((struct control *)user_data) 167 168 static 169 int 170 osc_message_handler( 171 const char * path, 172 const char * types, 173 lo_arg ** argv, 174 int argc, 175 void * data, 176 void * user_data) 177 { 178 const char *method; 179 180 method = path; 181 if (method[0] != '/' || method[1] != '/') 182 return osc_debug_handler(path, types, argv, argc, data, user_data); 183 method += 2; 184 185 if (!strcmp(method, "update") && argc == 1 && !strcmp(types, "s")) 186 { 187 return osc_update_handler(control_ptr, argv); 188 } 189 else if (!strcmp(method, "control") && argc == 2 && !strcmp(types, "if")) 190 { 191 return osc_control_handler(control_ptr, argv); 192 } 193 else if (!strcmp(method, "exiting") && argc == 0) 194 { 195 return osc_exiting_handler(control_ptr, argv); 196 } 197 198 return osc_debug_handler(path, types, argv, argc, data, user_data); 199 } 200 201 #undef control_ptr 58 static 59 char * 60 read_line( 61 struct control * control_ptr) 62 { 63 ssize_t ret; 64 char ch; 65 char buf[100]; 66 char * ptr; 67 68 ptr = buf; 69 70 loop: 71 ret = read(control_ptr->recv_pipe, &ch, 1); 72 if (ret == 1 && ch != '\n') 73 { 74 *ptr++ = ch; 75 goto loop; 76 } 77 78 if (ptr != buf) 79 { 80 *ptr = 0; 81 //printf("recv: \"%s\"\n", buf); 82 return strdup(buf); 83 } 84 85 return NULL; 86 } 202 87 203 88 #define control_ptr ((struct control *)_this_) … … 208 93 struct lv2_external_ui * _this_) 209 94 { 95 char * msg; 96 char * port_index_str; 97 char * port_value_str; 98 int port; 99 float value; 100 char * locale; 101 210 102 //printf("run() called\n"); 211 while (lo_server_recv_noblock(control_ptr->osc_server, 0) != 0) {} 103 104 msg = read_line(control_ptr); 105 if (msg == NULL) 106 { 107 return; 108 } 109 110 locale = strdup(setlocale(LC_NUMERIC, NULL)); 111 setlocale(LC_NUMERIC, "POSIX"); 112 113 if (!strcmp(msg, "port_value")) 114 { 115 port_index_str = read_line(control_ptr); 116 port_value_str = read_line(control_ptr); 117 118 port = atoi(port_index_str); 119 if (sscanf(port_value_str, "%f", &value) == 1) 120 { 121 //printf("port %d = %f\n", port, value); 122 control_ptr->write_function(control_ptr->controller, (uint32_t)port, sizeof(float), 0, &value); 123 } 124 else 125 { 126 fprintf(stderr, "failed to convert \"%s\" to float\n", port_value_str); 127 } 128 129 free(port_index_str); 130 free(port_value_str); 131 } 132 else if (!strcmp(msg, "exiting")) 133 { 134 //printf("got UI exit notification\n"); 135 control_ptr->running = false; 136 control_ptr->visible = false; 137 control_ptr->ui_closed(control_ptr->controller); 138 } 139 else 140 { 141 printf("unknown message: \"%s\"\n", msg); 142 } 143 144 setlocale(LC_NUMERIC, locale); 145 free(locale); 146 147 free(msg); 212 148 } 213 149 … … 224 160 } 225 161 226 if (control_ptr->osc_address) 227 { 228 lo_send(control_ptr->osc_address, control_ptr->osc_show_path, ""); 229 control_ptr->visible = true; 230 } 162 write(control_ptr->send_pipe, "show\n", 5); 163 control_ptr->visible = true; 231 164 } 232 165 … … 238 171 //printf("hide() called\n"); 239 172 240 if (!control_ptr->visible || !control_ptr->osc_address)173 if (!control_ptr->visible) 241 174 { 242 175 return; 243 176 } 244 177 245 lo_send(control_ptr->osc_address, control_ptr->osc_hide_path, "");178 write(control_ptr->send_pipe, "hide\n", 5); 246 179 control_ptr->visible = false; 247 180 } … … 263 196 struct lv2_external_ui_host * ui_host_ptr; 264 197 char * filename; 265 char * osc_url; 198 int pipe1[2]; /* written by host process, read by plugin UI process */ 199 int pipe2[2]; /* written by plugin UI process, read by host process */ 200 char ui_recv_pipe[100]; 201 char ui_send_pipe[100]; 202 int oldflags; 266 203 267 204 //printf("instantiate('%s', '%s') called\n", plugin_uri, bundle_path); … … 297 234 control_ptr->ui_closed = ui_host_ptr->ui_closed; 298 235 236 if (pipe(pipe1) != 0) 237 { 238 fprintf(stderr, "pipe1 creation failed."); 239 } 240 241 if (pipe(pipe2) != 0) 242 { 243 fprintf(stderr, "pipe2 creation failed."); 244 } 245 246 snprintf(ui_recv_pipe, sizeof(ui_recv_pipe), "%d", pipe1[0]); /* [0] means reading end */ 247 snprintf(ui_send_pipe, sizeof(ui_send_pipe), "%d", pipe2[1]); /* [1] means writting end */ 248 299 249 filename = malloc(strlen(bundle_path) + strlen(UI_EXECUTABLE) + 1); 300 250 if (filename == NULL) … … 308 258 control_ptr->running = false; 309 259 control_ptr->visible = false; 310 control_ptr->osc_address = NULL; 311 312 control_ptr->osc_server = lo_server_new(NULL, NULL);313 osc_url = lo_server_get_url(control_ptr->osc_server);314 //printf("host OSC URL is %s\n", osc_url);315 lo_server_add_method(control_ptr->osc_server, NULL, NULL, osc_message_handler, control_ptr);316 317 if (fork() == 0)318 { 260 261 switch (vfork()) 262 { 263 case 0: /* child process */ 264 /* fork duplicated the handles, close pipe ends that are used by parent process */ 265 /* it looks we cant do this for vfork() */ 266 //close(pipe1[1]); 267 //close(pipe2[0]); 268 319 269 execlp( 320 270 "python", 321 271 "python", 322 272 filename, 323 osc_url,324 273 plugin_uri, 325 274 bundle_path, 326 275 ui_host_ptr->plugin_human_id != NULL ? ui_host_ptr->plugin_human_id : "", 276 ui_recv_pipe, /* reading end */ 277 ui_send_pipe, /* writting end */ 327 278 NULL); 328 279 fprintf(stderr, "exec of UI failed: %s", strerror(errno)); 329 280 exit(1); 330 } 331 332 while (!control_ptr->running) 333 { 334 if (lo_server_recv_noblock(control_ptr->osc_server, 0) == 0) 335 { 336 usleep(300000); 337 } 338 } 281 case -1: 282 fprintf(stderr, "fork() failed to create new process for plugin UI"); 283 goto fail_free_control; 284 } 285 286 /* fork duplicated the handles, close pipe ends that are used by the child process */ 287 close(pipe1[0]); 288 close(pipe2[1]); 289 290 control_ptr->send_pipe = pipe1[1]; /* [1] means writting end */ 291 control_ptr->recv_pipe = pipe2[0]; /* [0] means reading end */ 292 293 oldflags = fcntl(control_ptr->recv_pipe, F_GETFL); 294 fcntl(control_ptr->recv_pipe, F_SETFL, oldflags | O_NONBLOCK); 339 295 340 296 *widget = (LV2UI_Widget)control_ptr; … … 369 325 const void * buffer) 370 326 { 327 char buf[100]; 328 int len; 329 char * locale; 330 371 331 //printf("port_event(%u, %f) called\n", (unsigned int)port_index, *(float *)buffer); 372 332 373 lo_send(control_ptr->osc_address, control_ptr->osc_control_path, "if", (int)port_index, *(float *)buffer); 333 locale = strdup(setlocale(LC_NUMERIC, NULL)); 334 setlocale(LC_NUMERIC, "POSIX"); 335 336 write(control_ptr->send_pipe, "port_value\n", 11); 337 len = sprintf(buf, "%u\n", (unsigned int)port_index); 338 write(control_ptr->send_pipe, buf, len); 339 len = sprintf(buf, "%.10f\n", *(float *)buffer); 340 write(control_ptr->send_pipe, buf, len); 341 fsync(control_ptr->send_pipe); 342 343 setlocale(LC_NUMERIC, locale); 344 free(locale); 374 345 } 375 346 -
ui
r1e11982 r51bb400 19 19 20 20 import sys 21 import os 22 import fcntl 21 23 import gtk 22 24 import gobject … … 24 26 from math import pi, sin, cos, atan2, log, sqrt, hypot, log10 25 27 from colorsys import hls_to_rgb, rgb_to_hls 26 import liblo27 28 28 29 def map_coords_linear(x,y): … … 874 875 self.invalidate_all() 875 876 876 class dssi_ui:877 class filter_ui: 877 878 def __init__(self, argv): 878 879 self.fake = len(argv) == 1 … … 885 886 886 887 #print repr(argv) 887 self.host_osc_url = argv[1] 888 self.plugin_uri = argv[2] 889 self.bundle_path = argv[3] 890 self.human_id = argv[4] 891 892 self.server = liblo.Server() 893 self.server.add_method(None, None, self.on_osc) 894 self.send_update() 895 896 def send_update(self): 897 if self.fake: 898 return 899 #print "UI -> update -> host" 900 liblo.send(self.host_osc_url, "//update", self.server.get_url()) 901 902 def send_port_value(self, port_index, value): 903 if self.fake: 904 return 905 liblo.send(self.host_osc_url, "//control", int(port_index), float(value)) 906 907 def send_exiting(self): 908 if self.fake: 909 return 910 liblo.send(self.host_osc_url, "//exiting") 911 912 def run(self): 913 if self.fake: 914 if not self.shown: 915 self.shown = True 916 self.on_show() 917 return 918 919 while self.server.recv(0): 920 pass 921 922 def on_osc(self, path, args, types): 923 if path == "/control" and types == "if": 924 self.on_port_value_changed(args[0], args[1]) 925 elif path == "/show" and types == "": 926 self.on_show() 927 elif path == "/hide" and types == "": 928 self.on_hide() 929 elif path == "/quit" and types == "": 930 self.on_quit() 931 else: 932 print "Unhandled OSC message. path='%s' types='%s', args=%s" % (path, types, repr(args)) 933 934 def on_port_value_changed(self, port_index, port_value): 935 return 936 937 def on_show(self): 938 return 939 940 def on_hide(self): 941 return 942 943 def on_quit(self): 944 return 945 946 class filter_ui(dssi_ui): 947 def __init__(self, argv): 948 dssi_ui.__init__(self, argv) 888 self.plugin_uri = argv[1] 889 self.bundle_path = argv[2] 890 self.human_id = argv[3] 891 892 self.recv_pipe_fd = int(argv[4]) 893 self.send_pipe_fd = int(argv[5]) 894 895 oldflags = fcntl.fcntl(self.recv_pipe_fd, fcntl.F_GETFL) 896 fcntl.fcntl(self.recv_pipe_fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK) 897 898 self.recv_pipe = os.fdopen(self.recv_pipe_fd, 'r') 899 self.send_pipe = os.fdopen(self.send_pipe_fd, 'w') 949 900 950 901 if self.plugin_uri == "http://nedko.aranaudov.org/soft/filter/2/mono": … … 1188 1139 self.send_port_value(port_index + self.port_base, value) 1189 1140 1141 def send(self, lines): 1142 for line in lines: 1143 #print 'send: "' + line + '"' 1144 self.send_pipe.write(line + "\n") 1145 self.send_pipe.flush() 1146 1147 def send_exiting(self): 1148 self.send(["exiting"]) 1149 1150 def send_port_value(self, port_index, value): 1151 self.send(["port_value", str(port_index), "%.10f" % value]) 1152 1153 def recv_line(self): 1154 return self.recv_pipe.readline().strip() 1155 1156 def recv_command(self): 1157 try: 1158 msg = self.recv_line() 1159 1160 if msg == "port_value": 1161 port_index = int(self.recv_line()) 1162 port_value = float(self.recv_line()) 1163 #print "port_value_change recevied: %d %f" % (port_index, port_value) 1164 self.on_port_value_changed(port_index, port_value) 1165 elif msg == "show": 1166 self.on_show() 1167 elif msg == "hide": 1168 self.on_hide() 1169 elif msg == "quit": 1170 self.on_quit() 1171 else: 1172 print 'unknown message: "' + msg + '"' 1173 1174 return True 1175 except IOError: 1176 return False 1177 1178 def on_recv(self, fd, cond): 1179 #print "on_recv" 1180 if cond == gobject.IO_HUP: 1181 gtk.main_quit() 1182 return False 1183 1184 while True: 1185 if not self.recv_command(): 1186 break 1187 1188 return True 1189 1190 1190 def run(self): 1191 1191 self.window.connect("destroy", self.on_window_closed) 1192 gobject.timeout_add(50, self.on_idle) 1192 1193 if self.fake: 1194 if not self.shown: 1195 self.shown = True 1196 self.on_show() 1197 else: 1198 gobject.io_add_watch(self.recv_pipe_fd, gobject.IO_IN | gobject.IO_HUP, self.on_recv) 1199 1193 1200 gtk.main() 1194 1195 def on_idle(self):1196 dssi_ui.run(self)1197 return True1198 1201 1199 1202 def on_port_value_changed(self, port_index, port_value):
