Third set of 50 GPL attribution for CV-Contributors added +
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / androidcontrol.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2016-2020 William Morrow
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published
7  * by the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  */
20
21 #include "keys.h"
22 #include "mwindow.h"
23 #include "mwindowgui.h"
24 #include "androidcontrol.h"
25 #include "preferences.h"
26
27
28 int AndroidControl::open(unsigned short port)
29 {
30         sockfd = socket(PF_INET,SOCK_DGRAM,0);
31         if( sockfd < 0 ) { perror("socket:"); return -1; }
32
33         struct linger lgr;
34         lgr.l_onoff = 0;
35         lgr.l_linger = 0;
36
37         if( setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &lgr, sizeof(lgr)) < 0 ) {
38                 perror("setlinger:");
39                 return -1;
40         }
41
42         struct sockaddr_in sadr;
43         memset(&sadr,0,sizeof(sadr));
44         sadr.sin_family = AF_INET;
45         sadr.sin_port = htons(port);
46         sadr.sin_addr.s_addr = 0;
47
48         if( bind(sockfd,(struct sockaddr *)&sadr,sizeof(sadr)) < 0 ) {
49                 perror("bind:");
50                 return -1;
51         }
52
53         return 0;
54 }
55
56 void AndroidControl::close()
57 {
58         if( sockfd >= 0 ) {
59                 ::close(sockfd);
60                 sockfd = -1;
61         }
62 }
63
64 AndroidControl::AndroidControl(MWindowGUI *mwindow_gui)
65  : Thread(1, 0, 0)
66 {
67         this->mwindow_gui = mwindow_gui;
68         Thread::start();
69         done = -1;
70         sockfd = -1;
71         msg = 0;
72 }
73
74 bool AndroidControl::is_msg(const char *cp)
75 {
76         if( msg_len != (int)strlen(cp) ) return false;
77         if( strncmp(cp, msg, msg_len) ) return false;
78         return true;
79 }
80
81 void AndroidControl::press(int key)
82 {
83 // printf("press 0x%04x\n",key);
84         if( key == KPMENU && mwindow_gui->keyev_grab_remote() )
85                 printf("android grab remote\n");
86         if( mwindow_gui->key_listener(key) ) return;
87         mwindow_gui->remote_control->remote_key(key);
88 }
89
90 void AndroidControl::run()
91 {
92         unsigned short port = mwindow_gui->mwindow->preferences->android_port;
93         done = open(port) >= 0 ? 0 : 1;
94
95         while( !done ) {
96                 struct sockaddr sadr;
97                 socklen_t sadr_len;
98                 enable_cancel();
99                 int ret = recvfrom(sockfd, buf, sizeof(buf), 0, &sadr, &sadr_len);
100                 if( ret < 0 ) {
101                         perror("AndroidControl::run: recvfrom");
102                         sleep(1);
103                 }
104                 disable_cancel();
105                 // validate message
106                 msg = buf;  msg_len = ret;
107                 // cinelerra android remote magic number
108                 if( msg[0] != 'C' || msg[1] != 'A' || msg[2] != 'R' ) continue;
109                 // version number
110                 if( msg[3] != 1 ) continue;
111                 msg += 4;  msg_len -= 4;
112                 // pin
113                 const char *pin = mwindow_gui->mwindow->preferences->android_pin;
114                 int len = sizeof(mwindow_gui->mwindow->preferences->android_pin);
115                 while( len > 0 && msg_len > 0 && *pin != 0 && *msg != 0 ) {
116                         if( *pin != *msg ) break;
117                         ++pin;  --len;
118                         ++msg;  --msg_len;
119                 }
120                 if( !len || !msg_len || *pin != *msg ) continue;
121                 ++msg; --msg_len;
122                 if( msg_len <= 0 ) continue;
123                 if( is_msg("menu") ) press(KPMENU);
124                 else if( is_msg("key 0") ) press('0');
125                 else if( is_msg("key 1") ) press('1');
126                 else if( is_msg("key 2") ) press('2');
127                 else if( is_msg("key 3") ) press('3');
128                 else if( is_msg("key 4") ) press('4');
129                 else if( is_msg("key 5") ) press('5');
130                 else if( is_msg("key 6") ) press('6');
131                 else if( is_msg("key 7") ) press('7');
132                 else if( is_msg("key 8") ) press('8');
133                 else if( is_msg("key 9") ) press('9');
134                 else if( is_msg("key A") ) press('a');
135                 else if( is_msg("key B") ) press('b');
136                 else if( is_msg("key C") ) press('c');
137                 else if( is_msg("key D") ) press('d');
138                 else if( is_msg("key E") ) press('e');
139                 else if( is_msg("book") ) press(KPBOOK);
140                 else if( is_msg("rplay") ) press(KPREV);
141                 else if( is_msg("stop") ) press(KPSTOP);
142                 else if( is_msg("play") ) press(KPPLAY);
143                 else if( is_msg("media_lt") ) press(LEFT);
144                 else if( is_msg("media_rt") ) press(RIGHT);
145                 else if( is_msg("media_up") ) press(UP);
146                 else if( is_msg("media_dn") ) press(DOWN);
147                 else if( is_msg("pause") ) press(' ');
148                 else if( is_msg("slow_lt") ) press(KPRECD);
149                 else if( is_msg("slow_rt") ) press(KPAUSE);
150                 else if( is_msg("fast_lt") ) press(KPBACK);
151                 else if( is_msg("fast_rt") ) press(KPFWRD);
152                 else if( is_msg("fscrn") ) press(KPFSCRN);
153                 else if( is_msg("mute") ) press(KPMUTE);
154                 else if( is_msg("vol_up") ) press(KPVOLUP);
155                 else if( is_msg("vol_dn") ) press(KPVOLDN);
156                 else if( is_msg("ch_up") ) press(KPCHUP);
157                 else if( is_msg("ch_dn") ) press(KPCHDN);
158                 else if( is_msg("key dot") ) press('.');
159                 else if( is_msg("key cc") ) press(KPCC);
160                 else if( is_msg("key tv") ) press(KPTV);
161                 else if( is_msg("hand") ) press(KPHAND);
162                 else if( is_msg("suspend") ) {
163                         system("sync; sleep 1; acpitool -s");
164                 }
165                 else if( is_msg("power") ) {
166                         system("sync; sleep 1; poweroff");
167                 }
168                 else {
169                         printf("AndroidControl::run: unkn msg: %s\n", msg);
170                         sleep(1);
171                 }
172         }
173 }
174
175 AndroidControl::~AndroidControl()
176 {
177         if( Thread::running() ) {
178                 done = 1;
179                 Thread::cancel();
180         }
181         Thread::join();
182 }
183