2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <booh@altern.org>
21 /***************************************
23 ***************************************/
30 gliv_image
*im1
= NULL
; /* Displayed. */
36 static pthread_mutex_t imlib_mutex
, ogl_mutex
;
38 /***************************************
39 * Locks or unlocks a mutex. *
40 ***************************************/
43 if (rt
.load_requested
)
48 pthread_mutex_lock(&imlib_mutex
);
52 pthread_mutex_unlock(&imlib_mutex
);
56 pthread_mutex_lock(&ogl_mutex
);
60 pthread_mutex_unlock(&ogl_mutex
);
65 /***************************************
66 * Changes the imlib_context and *
67 * destroys the given Imlib_Image. *
68 ***************************************/
69 void free_imlib_image(Imlib_Image
* im
)
75 imlib_context_set_image(im
);
80 /***************************************
81 * Frees a gliv_image structure. *
82 ***************************************/
83 void destroy_image(gliv_image
* im
)
89 printf("\nUnloading : %s", im
->filename
);
92 glDeleteTextures((GLsizei
) (im
->nb_w
* im
->nb_h
), im
->textures
);
96 free_imlib_image(im
->im
);
97 free_imlib_image(im
->gl_im
);
104 /***************************************
105 * Shuffles the given array. *
106 ***************************************/
107 static void randomize_array(char **array
)
112 srandom((unsigned) (time(NULL
) + getpid()));
114 for (i
= 0; i
< total
; i
++) {
116 r
= random() % total
;
122 /***************************************
123 * Adds a filename to the list. This *
124 *function is only used by ftw when the*
125 * -R flag is given. *
126 ***************************************/
127 static int add_to_list(const char *file
, const struct stat
*st
, int flag
)
130 /* It is not a directory, we don't care if it is an image or not. */
132 names
= realloc(names
, total
* sizeof(char *));
133 names
[total
- 1] = strdup(file
);
138 /***************************************
139 * Recursively adds all files to the *
140 * list by descending directories. The *
141 * image list is the variable 'names'. *
142 ***************************************/
143 static void build_image_list(char **array
, unsigned int nb
)
147 for (i
= 0; i
< nb
; i
++) {
148 ftw(array
[i
], add_to_list
, 8);
153 /***************************************
154 * Sets global variables according *
155 * to command-line arguments. *
156 ***************************************/
157 static void getopt_parser(struct gengetopt_args_info
*args
)
159 if (!args
->inputs_num
) {
160 cmdline_parser_print_help();
164 rt
.fullscreen
= args
->full_screen_flag
|| args
->maximize_flag
;
165 rt
.verbose
= args
->verbose_flag
;
166 rt
.info
= args
->info_flag
;
167 rt
.maximize
= args
->maximize_flag
;
169 if (args
->recursive_flag
) {
170 build_image_list(args
->inputs
, args
->inputs_num
);
173 total
= args
->inputs_num
;
174 names
= args
->inputs
;
178 /* Don't use a thread for only one image. */
179 rt
.load_requested
= 1;
181 rt
.load_requested
= args
->load_requested_flag
;
183 if (args
->shuffle_flag
)
184 randomize_array(names
);
186 if (args
->delay_given
&& args
->delay_arg
>= 0)
187 rt
.delay
= args
->delay_arg
;
192 /***************************************
193 * "Hides" the cursor by changing it *
194 * to a transparent one. *
195 ***************************************/
196 static void alarm_func(int unused
)
198 if (!rt
.cursor_hidden
)
199 set_transparent_cursor();
202 /***************************************
203 * Frees OpenGL memory and disconnects *
204 * from glX at exit. *
205 ***************************************/
206 static void clean_exit(void)
208 signal(SIGALRM
, SIG_IGN
);
210 glDeleteTextures((GLsizei
) (im1
->nb_w
* im1
->nb_h
), im1
->textures
);
212 if (!rt
.load_requested
) {
213 pthread_join(thread
, (void *) &im1
);
214 glDeleteTextures((GLsizei
) (im1
->nb_w
* im1
->nb_h
), im1
->textures
);
218 /***************************************
219 * Exits cleanly but acts as if we *
220 * were killed by the received signal. *
221 ***************************************/
222 static void exit_with_signal(int sig
)
226 /* Don't intercept the signal once more. */
227 signal(sig
, SIG_DFL
);
229 /* Sometimes the window stays here, so destroy it. */
230 XDestroyWindow(dpy
, win
);
233 /* Kill ourselves with the intercepted signal. */
237 /***************************************
238 *Fills run-time fields with predefined*
239 * values or command line arguments. *
240 ***************************************/
241 static void init_rt(int argc
, char *argv
[])
243 /* Processes command line. */
244 struct gengetopt_args_info
*args
;
245 args
= malloc(sizeof(struct gengetopt_args_info
));
246 cmdline_parser(argc
, argv
, args
);
250 /* Predefined values. */
254 rt
.state
= STATE_LOADED
;
257 /***************************************
258 * Catches signals that would make *
260 ***************************************/
261 static void install_sig_handlers(void)
264 signal(SIGHUP
, exit_with_signal
);
267 signal(SIGINT
, exit_with_signal
);
270 signal(SIGQUIT
, exit_with_signal
);
273 signal(SIGILL
, exit_with_signal
);
276 signal(SIGSEGV
, exit_with_signal
);
279 signal(SIGTERM
, exit_with_signal
);
282 signal(SIGBUS
, exit_with_signal
);
286 /***************************************
288 ***************************************/
289 int main(int argc
, char *argv
[])
292 struct timespec time_to_sleep
= { tv_sec
:0, tv_nsec
:1000000 };
297 printf("%s %s\n\n", PACKAGE
, VERSION
);
303 install_sig_handlers();
306 signal(SIGALRM
, alarm_func
);
308 rt
.cursor_hidden
= 0;
311 pthread_mutex_init(&imlib_mutex
, NULL
);
312 pthread_mutex_init(&ogl_mutex
, NULL
);
314 imlib_set_cache_size(1024 * 1024);
315 imlib_context_set_color(0, 0, 0, ~0);
317 if (!total
|| !(im1
= load_next_image(0))) {
318 fputs("Error : no valid images on command line.\n", stderr
);
324 XMapWindow(dpy
, win
);
326 if (!rt
.load_requested
)
330 if (rt
.state
== STATE_WAITING
)
331 /* Waiting for ClientMessage from the loading thread. */
332 while (!XPending(dpy
))
333 nanosleep(&time_to_sleep
, NULL
);
335 XNextEvent(dpy
, &ev
);
337 if (process_event(&ev
))
340 nanosleep(&time_to_sleep
, NULL
);
343 /* for (;;) never ends but ... */