Reported by Fedora team for gcc-13 and Andrew created patch here
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / x10tv.C
1 #ifdef HAVE_X10TV
2
3 #include "channelinfo.h"
4 #include "cwindow.h"
5 #include "cwindowgui.h"
6 #include "edl.h"
7 #include "mbuttons.h"
8 #include "mwindow.h"
9 #include "mwindowgui.h"
10 #include "language.h"
11 #include "playbackengine.h"
12 #include "playtransport.h"
13 #include "record.h"
14 #include "recordgui.h"
15 #include "recordmonitor.h"
16 #include "remotecontrol.h"
17 #include "tracks.h"
18 #include "x10tv.h"
19
20 #include <dirent.h>
21 #include <linux/input.h>
22
23 X10TV::X10TV(MWindow *mwindow, int *fds, int nfds)
24 {
25         this->mwindow = mwindow;
26         this->ifds = new int[nfds];
27         this->nfds = nfds;
28         for( int i=0; i<nfds; ++i ) this->ifds[i] = fds[i];
29
30         ev = new input_event;
31         memset(ev, 0, sizeof(*ev));
32         ev->code = -1;
33         done = -1;
34         last_code = -1;
35         code = -1;
36         FD_ZERO(&rfds);
37         mfd = -1;
38 }
39
40 X10TV::~X10TV()
41 {
42         stop();
43         delete ev;
44 }
45
46 void X10TV::stop()
47 {
48         done = 1;
49         for( int i=nfds; --i>=0; ) {
50                 ioctl(ifds[i], EVIOCGRAB, 0);
51                 close(ifds[i]);
52         }
53         nfds = 0;
54         if( running() ) {
55                 cancel();
56                 join();
57         }
58 }
59
60 void X10TV::start()
61 {
62         FD_ZERO(&rfds);
63         mfd = -1;
64         for( int i=nfds; --i>=0; ) {
65                 int fd = ifds[i];
66                 ioctl(fd, EVIOCGRAB, 1);
67                 if( fd >= mfd ) mfd = fd+1;
68                 FD_SET(fd, &rfds);
69         }
70         done = 0;
71         Thread::start();
72 }
73
74 int X10TV::open_usb_inputs(int vendor, int product, int &version,
75                 int *ifds, int mxfds)
76 {
77         int ret = -1;
78         const char *dev_input = "/dev/input";
79         DIR *dir = opendir(dev_input);
80         if( !dir ) return ret;
81
82         struct dirent64 *dp;
83         struct input_id dev_id;
84         int nfds = 0;
85         while( nfds < mxfds && (dp = readdir64(dir)) != 0 ) {
86                 char *fn = dp->d_name;
87                 if( !strcmp(fn, ".") || !strcmp(fn, "..") ) continue;
88                 char path[PATH_MAX];  struct stat st;
89                 snprintf(path, PATH_MAX, "%s/%s", dev_input, fn);
90                 if( stat(path, &st) < 0 ) continue;
91                 if( !S_ISCHR(st.st_mode) ) continue;
92                 int fd = open(path, O_RDONLY);
93                 if( fd < 0 ) continue;
94                 if( !ioctl(fd, EVIOCGID, &dev_id) ) {
95                         if( dev_id.bustype == BUS_USB &&
96                             dev_id.vendor == vendor &&
97                             dev_id.product == product ) {
98                                 unsigned props = 0;
99                                 // quirk, reports pointing_stick for keys
100                                 unsigned mptrs =
101                                          (1<<INPUT_PROP_POINTING_STICK);
102                                 int ret = ioctl(fd, EVIOCGPROP(sizeof(props)), &props);
103                                 if( ret == sizeof(props) && (props & mptrs) ) {
104                                         version = dev_id.version;
105                                         ifds[nfds++] = fd;
106                                         continue;
107                                 }
108                         }
109                 }
110                 close(fd);
111         }
112         closedir(dir);
113         return nfds;
114 }
115
116
117 X10TV *X10TV::probe(MWindow *mwindow)
118 {
119         int ver = -1, ifds[16];
120         int nfds = open_usb_inputs(0x0bc7, 0x0004, ver, ifds, 16);
121         if( nfds <= 0 ) return 0;
122         printf("detected ATI X10 remote, ver=0x%04x\n", ver);
123         return new X10TV(mwindow, ifds, nfds);
124 }
125
126 void X10TV::run()
127 {
128         enable_cancel();
129         while( !done ) {
130                 fd_set rds = rfds;
131                 int ret = select(mfd, &rds, 0, 0, 0);
132                 if( ret < 0 ) break;
133                 int fd = -1, k = ret > 0 ? nfds : 0;
134                 while( --k >= 0 ) {
135                         int ifd = ifds[k];
136                         if( FD_ISSET(ifd, &rds) ) {
137                                 fd = ifd;  break;
138                         }
139                 }
140                 if( fd < 0 ) {
141                         printf("select failed\n");
142                         usleep(100000);  continue;
143                 }
144                 ret = read(fd, ev, sizeof(*ev));
145                 if( done ) break;
146                 if( ret != sizeof(*ev) ) {
147                         if( ret < 0 ) { perror("read event"); break; }
148                         fprintf(stderr, "bad read: %d\n", ret);
149                         break;
150                 }
151                 handle_event(fd);
152         }
153 }
154
155 int X10TV::check_menu_keys(int code)
156 {
157         int result = 1;
158         switch( code ) {
159         case X10_POWER:
160                 mwindow->quit();
161                 break;
162         case X10_TV: {
163                 Record *record = mwindow->gui->record;
164                 if( !record->running() )
165                         record->start();
166                 else
167                         record->record_gui->interrupt_thread->start(0);
168                 break; }
169         case X10_BOOK:
170 #ifdef HAVE_DVB
171                 mwindow->gui->channel_info->toggle_scan();
172 #endif
173                 break;
174         case X10_EDIT: {
175                 RemoteControl *remote_control = mwindow->gui->remote_control;
176                 if( !remote_control->deactivate() )
177                         remote_control->activate();
178                 break; }
179         default:
180                 result = 0;
181         }
182         return result;
183 }
184
185 void X10TV::handle_event(int fd)
186 {
187         switch(ev->type) {
188         case EV_KEY: {
189                 if( !ev->value ) break;
190                 this->last_code = this->code;
191                 this->code = ev->code;
192                 if( check_menu_keys(code) ) break;
193                 RemoteHandler *handler = mwindow->gui->remote_control->handler;
194                 if( handler )
195                         handler->process_key(ev->code);
196                 break; }
197         case EV_SYN:
198         case EV_MSC:
199                 break;
200         default: {
201                 time_t t = ev->time.tv_sec;
202                 struct tm *tp = localtime(&t);
203                 printf("x10tv event %d: %4d/%02d/%02d %02d:%02d:%02d.%03d = (%d, %d, 0x%x)\n",
204                         fd, tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday,
205                         tp->tm_hour, tp->tm_min, tp->tm_sec,
206                         (int)ev->time.tv_usec/1000, ev->type, ev->code, ev->value);
207                 break; }
208         }
209 }
210
211
212 int X10TVCWindowHandler::x10tv_process_code(int code)
213 {
214         MWindow *mwindow = x10tv->mwindow;
215         EDL *edl = mwindow->edl;
216         if( !edl ) return 0;
217         PlayTransport *transport = mwindow->gui->mbuttons->transport;
218         if( !transport->get_edl() ) return 0;
219         PlaybackEngine *engine = transport->engine;
220         double position = engine->get_tracking_position();
221         double length = edl->tracks->total_length();
222         int next_command = -1;
223
224         switch( code ) {
225         case X10_A:             break;
226         case X10_B:             break;
227         case X10_POWER:         break;
228         case X10_TV:            break;
229         case X10_DVD:           break;
230         case X10_WWW:           break;
231         case X10_BOOK:          break;
232         case X10_EDIT:          break;
233         case X10_VOLDN:         return 1;
234         case X10_VOLUP:         return 1;
235         case X10_MUTE:          break;
236         case X10_CH_DN:         break;
237         case X10_CH_UP:         break;
238 // select window tile config = BACK 1,2,3
239         case X10_1: case X10_2: case X10_3:
240                 if( mwindow->x10tv->last_code == X10_MENU ) {
241                         RemoteGUI *rgui = mwindow->gui->cwindow_remote_handler->gui;
242                         rgui->tile_windows(code - X10_1);
243                         return 1;
244                 } // fall thru
245 // select asset program config = TEXT 1,2,3,4,5,6
246         case X10_4: case X10_5: case X10_6:
247                 if( mwindow->x10tv->last_code == X10_SETUP ) {
248                         mwindow->select_asset(code - X10_1, 1);
249                         break;
250                 } // fall thru
251         case X10_7: case X10_8: case X10_9:
252         case X10_0:
253 // select position in 10 percent units
254                 position = length * (code - X10_0)/10.0;
255                 break;
256         case X10_MENU:          return 0;
257         case X10_SETUP:         return 0;
258         case X10_C:             return 1;
259         case X10_UP:  position += 60.0;  break;
260         case X10_D:             return 1;
261         case X10_PROPS:         return 1;
262         case X10_LT:  position -= 10.0;  break;
263         case X10_OK:            return 1;
264         case X10_RT:  position += 10.0;  break;
265         case X10_SCRN: {
266                 CWindowCanvas *canvas = mwindow->cwindow->gui->canvas;
267                 int on = canvas->get_fullscreen() ? 0 : 1;
268                 canvas->Canvas::set_fullscreen(on, 0);
269                 return 1; }
270         case X10_E:             return 1;
271         case X10_DN:  position -= 60.0;  break;
272         case X10_F:             return 1;
273         case X10_REW:   next_command = FAST_REWIND;     break;
274         case X10_PLAY:  next_command = NORMAL_FWD;      break;
275         case X10_FWD:   next_command = FAST_FWD;        break;
276         case X10_REC:   next_command = SLOW_REWIND;     break;
277         case X10_STOP:  next_command = STOP;            break;
278         case X10_PAUSE: next_command = SLOW_FWD;        break;
279
280         default:
281                 printf("x10tv cwindow: unknown code: %04x\n", code);
282                 return -1;
283         }
284
285         if( next_command < 0 ) {
286                 if( position < 0 ) position = 0;
287                 transport->change_position(position);
288         }
289         else
290                 transport->handle_transport(next_command);
291         return 0;
292 }
293
294 int X10TVCWindowHandler::process_key(int key)
295 {
296         return x10tv_process_code(key);
297 }
298
299 int X10TVRecordHandler::process_key(int key)
300 {
301         Record *record = x10tv->mwindow->gui->record;
302         return record->x10tv_process_code(key);
303 }
304
305
306 X10TVRecordHandler::X10TVRecordHandler(X10TV *x10tv, RemoteControl *remote_control)
307  : RemoteHandler(remote_control->gui, GREEN)
308 {
309         this->x10tv = x10tv;
310 }
311
312 X10TVCWindowHandler::X10TVCWindowHandler(X10TV *x10tv, RemoteControl *remote_control)
313  : RemoteHandler(remote_control->gui, BLUE)
314 {
315         this->x10tv = x10tv;
316 }
317
318 // HAVE_X10TV
319 #endif