1 /*
2  * This file is part of MPlayer.
3  *
4  * MPlayer is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * MPlayer is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #include "config.h"
20 
21 #include <lirc/lirc_client.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 
29 #include "mp_msg.h"
30 #include "help_mp.h"
31 #include "input.h"
32 #include "lirc.h"
33 
34 static struct lirc_config *lirc_config;
35 char *lirc_configfile;
36 
37 static char* cmd_buf = NULL;
38 
39 int
mp_input_lirc_init(void)40 mp_input_lirc_init(void) {
41   int lirc_sock;
42   int mode;
43 
44   mp_msg(MSGT_LIRC, MSGL_V, "Setting up LIRC support...\n");
45   if((lirc_sock=lirc_init("mplayer",1))==-1){
46     mp_msg(MSGT_LIRC,MSGL_ERR,MSGTR_LIRCopenfailed);
47     return -1;
48   }
49 
50   mode = fcntl(lirc_sock, F_GETFL);
51   if (mode < 0 || fcntl(lirc_sock, F_SETFL, mode | O_NONBLOCK) < 0) {
52     mp_msg(MSGT_LIRC, MSGL_ERR, "setting non-blocking mode failed: %s\n",
53 	strerror(errno));
54     lirc_deinit();
55     return -1;
56   }
57 
58   if(lirc_readconfig( lirc_configfile,&lirc_config,NULL )!=0 ){
59     mp_msg(MSGT_LIRC,MSGL_ERR,MSGTR_LIRCcfgerr,
60 		    lirc_configfile == NULL ? "~/.lircrc" : lirc_configfile);
61     lirc_deinit();
62     return -1;
63   }
64 
65   return lirc_sock;
66 }
67 
mp_input_lirc_read(int fd,char * dest,int s)68 int mp_input_lirc_read(int fd,char* dest, int s) {
69   int r,cl = 0;
70   char *code = NULL,*c = NULL;
71 
72   // We have something in the buffer return it
73   if(cmd_buf != NULL) {
74     int l = strlen(cmd_buf), w = l > s ? s : l;
75     memcpy(dest,cmd_buf,w);
76     l -= w;
77     if(l > 0)
78       memmove(cmd_buf,&cmd_buf[w],l+1);
79     else {
80       free(cmd_buf);
81       cmd_buf = NULL;
82     }
83     return w;
84   }
85 
86   // Nothing in the buffer, poll the lirc fd
87   if(lirc_nextcode(&code) != 0) {
88     mp_msg(MSGT_LIRC,MSGL_ERR,"Lirc error :(\n");
89     return MP_INPUT_DEAD;
90   }
91 
92   if(!code) return MP_INPUT_NOTHING;
93 
94   // We put all cmds in a single buffer separated by \n
95   while((r = lirc_code2char(lirc_config,code,&c))==0 && c!=NULL) {
96     int l = strlen(c);
97     if(l <= 0)
98       continue;
99     cmd_buf = realloc(cmd_buf,cl+l+2);
100     memcpy(&cmd_buf[cl],c,l);
101     cl += l+1;
102     cmd_buf[cl-1] = '\n';
103     cmd_buf[cl] = '\0';
104   }
105 
106   free(code);
107 
108   if(r < 0)
109     return MP_INPUT_DEAD;
110   else if(cmd_buf) // return the first command in the buffer
111     return mp_input_lirc_read(fd,dest,s);
112   else
113     return MP_INPUT_RETRY;
114 
115 }
116 
117 void
mp_input_lirc_close(int fd)118 mp_input_lirc_close(int fd) {
119   free(cmd_buf);
120   cmd_buf = NULL;
121   lirc_freeconfig(lirc_config);
122   lirc_deinit();
123 }
124