1 /*
2  * Copyright (C) 2008 - 2016 The Geeqie Team
3  *
4  * This program 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  * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #include <glib/gprintf.h>
20 
21 #include "lirc.h"
22 
23 #include "misc.h"
24 
25 #ifdef HAVE_LIRC
26 #include <lirc/lirc_client.h>
27 #include "layout_image.h"
28 
29 gint lirc_fd = -1;
30 struct lirc_config *config = NULL;
31 guint input_tag = 0; /* event source id */
32 GIOChannel *gio_chan;
33 
34 /*
35  *-----------------------------------------------------------------------------
36  * LIRC callback
37  *-----------------------------------------------------------------------------
38  */
39 
lirc_cleanup(void)40 static void lirc_cleanup(void)
41 {
42 	if (config)
43 		{
44 		g_source_remove(input_tag);
45 		lirc_freeconfig(config);
46 		config = NULL;
47 		}
48 	if (lirc_fd != -1)
49 		{
50 		lirc_deinit();
51 		lirc_fd = -1;
52 		}
53 	if (gio_chan)
54 		{
55 		g_io_channel_shutdown(gio_chan, TRUE, NULL);
56 		g_io_channel_unref(gio_chan);
57 		}
58 }
59 
lirc_input_callback(GIOChannel * source,GIOCondition condition,gpointer data)60 static gboolean lirc_input_callback(GIOChannel *source, GIOCondition condition,
61 				    gpointer data)
62 {
63 	LayoutWindow *lw = data;
64 	gchar *ptr;
65 	gint ret;
66 	gint x = 0;
67 	gint y = 0;
68 
69 	/* LIRC code and corresponding geeqie command (and parameters)*/
70 	gchar *code;
71 	gchar *cmd;
72 
73 	/* parameters for geeqie command */
74 	gint i_parm;
75 	gfloat fl_parm;
76 
77 	while ((ret = lirc_nextcode(&code)) == 0 && code)
78 		{
79 		while ((ret = lirc_code2char(config, code, &cmd)) == 0 && cmd)
80 			{
81 			if (g_ascii_strncasecmp("LEFT", cmd, 4) == 0)
82 				{
83 				ptr = cmd + 4;
84 				while (g_ascii_isspace(*ptr)) ptr++;
85 				i_parm = atoi(ptr);
86 
87 				if (i_parm <= 0) i_parm = 1;
88 				x -= i_parm;
89 				}
90 			else if (g_ascii_strncasecmp("RIGHT", cmd, 5) == 0)
91 				{
92 				ptr = cmd + 5;
93 				while (g_ascii_isspace(*ptr)) ptr++;
94 				i_parm = atoi(ptr);
95 
96 				if (i_parm <= 0) i_parm = 1;
97 				x += i_parm;
98 				}
99 			else if (g_ascii_strncasecmp("UP", cmd, 2) == 0)
100 				{
101 				ptr = cmd + 2;
102 				while (g_ascii_isspace(*ptr)) ptr++;
103 				i_parm = atoi(ptr);
104 
105 				if (i_parm <= 0) i_parm = 1;
106 				y -= i_parm;
107 				}
108 			else if (g_ascii_strncasecmp("DOWN", cmd, 4) == 0)
109 				{
110 				ptr = cmd + 4;
111 				while (g_ascii_isspace(*ptr)) ptr++;
112 				i_parm = atoi(ptr);
113 
114 				if (i_parm <= 0) i_parm = 1;
115 				y += i_parm;
116 				}
117 			else if (g_ascii_strcasecmp("PREV", cmd) == 0)
118 				{
119 				layout_image_prev(lw);
120 				}
121 			else if (g_ascii_strcasecmp("NEXT", cmd) == 0)
122 				{
123 				layout_image_next(lw);
124 				}
125 			else if (g_ascii_strncasecmp("ZOOM_IN", cmd, 7) == 0)
126 				{
127 				ptr = cmd + 7;
128 				while (g_ascii_isspace(*ptr)) ptr++;
129 				fl_parm = atoi(ptr) / 10.0;
130 
131 				if (fl_parm <= 0.01) fl_parm = get_zoom_increment();
132 				layout_image_zoom_adjust(lw, fl_parm, FALSE);
133 				}
134 			else if (g_ascii_strncasecmp("ZOOM_OUT", cmd, 8) == 0)
135 				{
136 				ptr = cmd + 8;
137 				while (g_ascii_isspace(*ptr)) ptr++;
138 				fl_parm = atoi(ptr) / 10.0;
139 
140 				if (fl_parm <= 0.01) fl_parm = get_zoom_increment();
141 				layout_image_zoom_adjust(lw, -fl_parm, FALSE);
142 				}
143 			else if (g_ascii_strcasecmp("ZOOM_MAX", cmd) == 0)
144 				{
145 				layout_image_zoom_set(lw, 0.0, FALSE);
146 				}
147 			else if (g_ascii_strcasecmp("FULL_SCREEN", cmd) == 0)
148 				{
149 				layout_image_full_screen_toggle(lw);
150 				}
151 			else if (g_ascii_strncasecmp("SET_ZOOM", cmd, 8) == 0)
152 				{
153 				ptr = cmd + 8;
154 				while (g_ascii_isspace(*ptr)) ptr++;
155 				i_parm = atoi(ptr);
156 
157 				if (i_parm <= 0) i_parm = 1;
158 				layout_image_zoom_set(lw, 1.0, FALSE);
159 				}
160 			else if (g_ascii_strncasecmp("SET_INV_ZOOM", cmd, 12) == 0)
161 				{
162 				ptr = cmd + 12;
163 				while (g_ascii_isspace(*ptr)) ptr++;
164 				i_parm = atoi(ptr);
165 
166 				if (i_parm <= 0) i_parm = 1;
167 				layout_image_zoom_set(lw, -i_parm, FALSE);
168 				}
169 			else if (g_ascii_strcasecmp("FIRST", cmd) == 0)
170 				{
171 				layout_image_first(lw);
172 				}
173 			else if (g_ascii_strcasecmp("LAST", cmd) == 0)
174 				{
175 				layout_image_last(lw);
176 				}
177 			else if (g_ascii_strcasecmp("PAUSE", cmd) == 0)
178 				{
179 				layout_image_slideshow_pause_toggle(lw);
180 				}
181 			else if (g_ascii_strcasecmp("ROTATE_90", cmd) == 0)
182 				{
183 				layout_image_alter_orientation(lw, ALTER_ROTATE_90);
184 				}
185 			else if (g_ascii_strcasecmp("ROTATE_90_CC", cmd) == 0)
186 				{
187 				layout_image_alter_orientation(lw, ALTER_ROTATE_90_CC);
188 				}
189 			else if (g_ascii_strcasecmp("INFO", cmd) == 0)
190 				{
191 				layout_image_overlay_toggle(lw);
192 				}
193 			else if (g_ascii_strcasecmp("EXIT", cmd) == 0)
194 				{
195 				exit_program();
196 				}
197 			}
198 		free(code);
199 		if (ret == -1) break;
200 		}
201 	if (x != 0 || y != 0)
202 		{
203 		layout_image_scroll(lw, x, y, FALSE);
204 		}
205 
206 	if (ret == -1)
207 		{
208 		/* something went badly wrong */
209 		g_fprintf(stderr, _("disconnected from LIRC\n"));
210 		lirc_cleanup();
211 		return (gboolean)FALSE;
212 		}
213 	return (gboolean)TRUE;
214 }
215 
layout_image_lirc_init(LayoutWindow * lw)216 void layout_image_lirc_init(LayoutWindow *lw)
217 {
218 	gint flags;
219 	gboolean lirc_verbose = (get_debug_level() >= 2);
220 
221 	lirc_fd = lirc_init(GQ_APPNAME_LC, lirc_verbose);
222 	if (lirc_fd == -1)
223 		{
224 		DEBUG_1("Initializing LIRC... failed");
225 		return;
226 		}
227 
228 	DEBUG_1("Initializing LIRC... OK");
229 	if (lirc_readconfig(NULL, &config, NULL) == -1)
230 		{
231 		lirc_deinit();
232 
233 		g_fprintf(stderr,
234 			_("could not read LIRC config file\n"
235 			"please read the documentation of LIRC to \n"
236 			"know how to create a proper config file\n"));
237 		fflush(stderr);
238 
239 		DEBUG_1("Failed to read LIRC config file");
240 		return;
241 		}
242 	if (lirc_verbose) fflush(stderr);
243 
244 	gio_chan = g_io_channel_unix_new(lirc_fd);
245 	input_tag = g_io_add_watch(gio_chan, G_IO_IN,
246 				   lirc_input_callback, lw);
247 	fcntl(lirc_fd, F_SETOWN, getpid());
248 	flags = fcntl(lirc_fd, F_GETFL, 0);
249 	if (flags != -1) fcntl(lirc_fd, F_SETFL, flags|O_NONBLOCK);
250 }
251 
252 #endif /* HAVE_LIRC */
253 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
254