Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / cinelerra / androidcontrol.C
diff --git a/cinelerra-5.1/cinelerra/androidcontrol.C b/cinelerra-5.1/cinelerra/androidcontrol.C
new file mode 100644 (file)
index 0000000..784dea2
--- /dev/null
@@ -0,0 +1,149 @@
+
+#include "keys.h"
+#include "mwindow.h"
+#include "mwindowgui.h"
+#include "androidcontrol.h"
+#include "preferences.h"
+
+
+int AndroidControl::open(unsigned short port)
+{
+       sockfd = socket(PF_INET,SOCK_DGRAM,0);
+       if( sockfd < 0 ) { perror("socket:"); return -1; }
+
+       struct linger lgr;
+       lgr.l_onoff = 0;
+       lgr.l_linger = 0;
+
+       if( setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &lgr, sizeof(lgr)) < 0 ) {
+               perror("setlinger:");
+               return -1;
+       }
+
+       struct sockaddr_in sadr;
+       memset(&sadr,0,sizeof(sadr));
+       sadr.sin_family = AF_INET;
+       sadr.sin_port = htons(port);
+       sadr.sin_addr.s_addr = 0;
+
+       if( bind(sockfd,(struct sockaddr *)&sadr,sizeof(sadr)) < 0 ) {
+               perror("bind:");
+               return -1;
+       }
+
+       return 0;
+}
+
+void AndroidControl::close()
+{
+       if( sockfd >= 0 ) {
+               ::close(sockfd);
+               sockfd = -1;
+       }
+}
+
+AndroidControl::AndroidControl(MWindowGUI *mwindow_gui)
+ : Thread(1, 0, 0)
+{
+       this->mwindow_gui = mwindow_gui;
+       Thread::start();
+}
+
+bool AndroidControl::is_msg(const char *cp)
+{
+       if( msg_len != (int)strlen(cp) ) return false;
+       if( strncmp(cp, msg, msg_len) ) return false;
+       return true;
+}
+
+void AndroidControl::press(int key)
+{
+// printf("press 0x%04x\n",key);
+       if( mwindow_gui->keyboard_listener(key) ) return;
+       mwindow_gui->remote_control->remote_key(key);
+}
+
+void AndroidControl::run()
+{
+       unsigned short port = mwindow_gui->mwindow->preferences->android_port;
+       done = open(port) >= 0 ? 0 : 1;
+
+       while( !done ) {
+               struct sockaddr sadr;
+               socklen_t sadr_len;
+               enable_cancel();
+               int ret = recvfrom(sockfd, buf, sizeof(buf), 0, &sadr, &sadr_len);
+               if( ret < 0 ) {
+                       perror("AndroidControl::run: recvfrom");
+                       sleep(1);
+               }
+               disable_cancel();
+               // validate message
+               msg = buf;  msg_len = ret;
+               // cinelerra android remote magic number
+               if( msg[0] != 'C' || msg[1] != 'A' || msg[2] != 'R' ) continue;
+               // version number
+               if( msg[3] != 1 ) continue;
+               msg += 4;  msg_len -= 4;
+               // pin
+               const char *pin = mwindow_gui->mwindow->preferences->android_pin;
+               int len = sizeof(mwindow_gui->mwindow->preferences->android_pin);
+               while( len > 0 && msg_len > 0 && *pin != 0 && *msg != 0 ) {
+                       if( *pin != *msg ) break;
+                       ++pin;  --len;
+                       ++msg;  --msg_len;
+               }
+               if( !len || !msg_len || *pin != *msg ) continue;
+               ++msg; --msg_len;
+               if( msg_len <= 0 ) continue;
+               if( is_msg("stop") ) press(KPSTOP);
+               else if( is_msg("play") ) press(KPPLAY);
+               else if( is_msg("rplay") ) press(KPREV);
+               else if( is_msg("pause") ) press(' ');
+                       else if( is_msg("fast_lt") ) press(KPBACK);
+               else if( is_msg("media_up") ) press(UP);
+               else if( is_msg("fast_rt") ) press(KPFWRD);
+               else if( is_msg("menu") ) press(KPMENU);
+               else if( is_msg("media_lt") ) press(LEFT);
+               else if( is_msg("media_rt") ) press(RIGHT);
+               else if( is_msg("slow_lt") ) press(KPRECD);
+               else if( is_msg("media_dn") ) press(DOWN);
+               else if( is_msg("slow_rt") ) press(KPAUSE);
+               else if( is_msg("key 0") ) press('0');
+               else if( is_msg("key 1") ) press('1');
+               else if( is_msg("key 2") ) press('2');
+               else if( is_msg("key 3") ) press('3');
+               else if( is_msg("key 4") ) press('4');
+               else if( is_msg("key 5") ) press('5');
+               else if( is_msg("key 6") ) press('6');
+               else if( is_msg("key 7") ) press('7');
+               else if( is_msg("key 8") ) press('8');
+               else if( is_msg("key 9") ) press('9');
+               else if( is_msg("key A") ) press('a');
+               else if( is_msg("key B") ) press('b');
+               else if( is_msg("key C") ) press('c');
+               else if( is_msg("key D") ) press('d');
+               else if( is_msg("key E") ) press('e');
+               else if( is_msg("key F") ) press('f');
+               else if( is_msg("suspend") ) {
+                       system("sync; sleep 1; pm-suspend");
+               }
+               else if( is_msg("power") ) {
+                       system("sync; sleep 1; poweroff");
+               }
+               else {
+                       printf("AndroidControl::run: unkn msg: %s\n", msg);
+                       sleep(1);
+               }
+       }
+}
+
+AndroidControl::~AndroidControl()
+{
+       if( Thread::running() ) {
+               done = 1;
+               Thread::cancel();
+               Thread::join();
+       }
+}
+