1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Jean Le Feuvre
5 * Copyright (c) Telecom ParisTech 2011-2012
6 * All rights reserved
7 *
8 * This file is part of GPAC / Sampe On-Scvreen Display sub-project
9 *
10 * GPAC is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * GPAC is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; see the file COPYING. If not, write to
22 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26 #include <gpac/modules/term_ext.h>
27 #include <gpac/internal/terminal_dev.h>
28 #include <gpac/internal/compositor_dev.h>
29 #include <gpac/nodes_mpeg4.h>
30 #include <gpac/network.h>
31
32 #define XMIN 160
33 #define XMAX 480
34
35 #define YMAX 360
36 #define YMIN 120
37
38 typedef struct
39 {
40 GF_Terminal *term;
41 GF_Socket *sock;
42 Bool mouse_down;
43 u32 cnt;
44 Float last_min_x, last_max_x, last_min_y, last_max_y;
45 } GF_NetControl;
46
netctrl_process(GF_TermExt * termext,u32 action,void * param)47 static Bool netctrl_process(GF_TermExt *termext, u32 action, void *param)
48 {
49 const char *sOpt, *server_ip;
50 int port;
51 Float face_min_x, face_max_x, face_min_y, face_max_y, gaze_x, gaze_y;
52 GF_Event event;
53 GF_NetControl *netctrl = termext->udta;
54 char message[1024];
55 GF_Err e;
56 u32 bytes;
57 u32 face = 0;
58
59 switch (action) {
60 case GF_TERM_EXT_START:
61 netctrl->term = (GF_Terminal *) param;
62
63 sOpt = gf_opts_get_key("NetControler", "Enabled");
64 if (!sOpt || strcmp(sOpt, "yes")) return 0;
65 sOpt = gf_opts_get_key("NetControler", "ServerIP");
66 if (sOpt) server_ip = sOpt;
67 else server_ip = "127.0.0.1";
68 sOpt = gf_opts_get_key("NetControler", "Port");
69 if (sOpt) port = atoi(sOpt);
70 else port = 20320;
71
72 termext->caps |= GF_TERM_EXTENSION_NOT_THREADED;
73 netctrl->sock = gf_sk_new(GF_SOCK_TYPE_UDP);
74
75 if (netctrl->sock < 0) {
76 GF_LOG(GF_LOG_ERROR, GF_LOG_INTERACT, ("[NetControl] Failed to open socket for %s:%d\n", server_ip, port));
77 return 0;
78 }
79
80 e = gf_sk_bind(netctrl->sock, server_ip, port, NULL, 0, 0);
81 if (e != GF_OK) {
82 if (netctrl->sock) gf_sk_del(netctrl->sock);
83 netctrl->sock = NULL;
84 GF_LOG(GF_LOG_ERROR, GF_LOG_INTERACT, ("[NetControl] Failed to bind to socket %s:%d\n", server_ip, port));
85 return 0;
86 }
87
88 return 1;
89
90 case GF_TERM_EXT_STOP:
91 if (netctrl->sock) gf_sk_del(netctrl->sock);
92 break;
93
94 case GF_TERM_EXT_PROCESS:
95 gf_sk_receive(netctrl->sock, message, 1024, 0, &bytes);
96 if (!bytes) break;
97 message[bytes] = '\0';
98 GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[NetControl] received message %s\n", message));
99
100 if (!strncmp(message, "gpac splice ", 12) || !strncmp(message, "gpac add ", 9)
101 || !strncmp(message, "gpac select ", 12)
102 ) {
103 gf_term_scene_update(netctrl->term, NULL, message);
104 break;
105 }
106
107 if (strncmp(message, "gpac:face=", 10)) break;
108
109 sscanf(message, "gpac:face=%d,%f,%f,%f,%f", &face, &face_min_x, &face_max_x, &face_min_y, &face_max_y);
110
111
112 memset(&event, 0, sizeof(GF_Event));
113 event.mouse.button = GF_MOUSE_LEFT;
114 if (face == 0) {
115 if (netctrl->last_min_x < 0.01) {
116 netctrl->term->compositor->auto_rotate = 2;
117 } else if (netctrl->last_max_x > 0.90) {
118 netctrl->term->compositor->auto_rotate = 1;
119 } else if (netctrl->last_min_y < 0.01) {
120 netctrl->term->compositor->auto_rotate = 4;
121 } else if (netctrl->last_max_y > 0.90) {
122 netctrl->term->compositor->auto_rotate = 3;
123 } else {
124 netctrl->cnt++;
125 if ((netctrl->cnt>=50) && (netctrl->mouse_down)) {
126 netctrl->term->compositor->auto_rotate = 0;
127 netctrl->mouse_down = GF_FALSE;
128 event.type = GF_EVENT_MOUSEUP;
129 netctrl->term->compositor->video_out->on_event(netctrl->term->compositor->video_out->evt_cbk_hdl, &event);
130 }
131 }
132 break;
133 }
134
135 netctrl->last_min_x = face_min_x;
136 netctrl->last_max_x = face_max_x;
137 netctrl->last_min_y = face_min_y;
138 netctrl->last_max_y = face_max_y;
139
140 gaze_x = (face_min_x+face_max_x)/2;
141 gaze_y = (face_min_y+face_max_y)/2;
142
143 event.mouse.x = (1-gaze_x) * netctrl->term->compositor->display_width;
144 event.mouse.y = (1-gaze_y) * netctrl->term->compositor->display_height;
145
146 if (!netctrl->mouse_down) {
147 //don't grab if mouse is down
148 if (netctrl->term->compositor->navigation_state) break;
149 netctrl->mouse_down = GF_TRUE;
150 event.type = GF_EVENT_MOUSEDOWN;
151 netctrl->term->compositor->video_out->on_event(netctrl->term->compositor->video_out->evt_cbk_hdl, &event);
152 netctrl->cnt = 0;
153 }
154 event.type = GF_EVENT_MOUSEMOVE;
155 netctrl->term->compositor->video_out->on_event(netctrl->term->compositor->video_out->evt_cbk_hdl, &event);
156 break;
157 }
158 return 0;
159 }
160
161
netctrl_new()162 GF_TermExt *netctrl_new()
163 {
164 GF_TermExt *dr;
165 GF_NetControl *netctrl;
166 dr = (GF_TermExt*)gf_malloc(sizeof(GF_TermExt));
167 memset(dr, 0, sizeof(GF_TermExt));
168 GF_REGISTER_MODULE_INTERFACE(dr, GF_TERM_EXT_INTERFACE, "GPAC NetControl", "gpac distribution");
169
170 GF_SAFEALLOC(netctrl, GF_NetControl);
171 dr->process = netctrl_process;
172 dr->udta = netctrl;
173 return dr;
174 }
175
176
netctrl_delete(GF_BaseInterface * ifce)177 void netctrl_delete(GF_BaseInterface *ifce)
178 {
179 GF_TermExt *dr = (GF_TermExt *) ifce;
180 GF_NetControl *netctrl = dr->udta;
181 gf_free(netctrl);
182 gf_free(dr);
183 }
184
185 GPAC_MODULE_EXPORT
QueryInterfaces()186 const u32 *QueryInterfaces()
187 {
188 static u32 si [] = {
189 GF_TERM_EXT_INTERFACE,
190 0
191 };
192 return si;
193 }
194
195 GPAC_MODULE_EXPORT
LoadInterface(u32 InterfaceType)196 GF_BaseInterface *LoadInterface(u32 InterfaceType)
197 {
198 if (InterfaceType == GF_TERM_EXT_INTERFACE) return (GF_BaseInterface *)netctrl_new();
199 return NULL;
200 }
201
202 GPAC_MODULE_EXPORT
ShutdownInterface(GF_BaseInterface * ifce)203 void ShutdownInterface(GF_BaseInterface *ifce)
204 {
205 switch (ifce->InterfaceType) {
206 case GF_TERM_EXT_INTERFACE:
207 netctrl_delete(ifce);
208 break;
209 }
210 }
211
212 GPAC_MODULE_STATIC_DECLARATION( netctrl )
213