wmail: handle allocation failures.
[dockapps.git] / wmmp3 / mpg123ctl.c
blob83cd5dc250db14be1cdf6f77bf7510065fa5ef44
1 /*
2 * wmmp3
3 * Copyright (c)1999 Patrick Crosby <xb@dotfiles.com>.
4 * This software covered by the GPL. See COPYING file for details.
6 * mpg123ctl.c
8 * This file contains all the functions for controlling the
9 * mpg123 backend processes.
11 * Random play functionality courtesy of:
12 * Matthew D. Campbell <matt@campbellhome.dhs.org>
14 * $Id: mpg123ctl.c,v 1.15 1999/10/12 04:41:20 pcrosby Exp $
17 #include "mpg123ctl.h"
19 #define MAXDIRS 100
20 #define MAX_TITLE_LEN 9
22 void set_playlist();
23 void signal_play();
24 void play();
25 void play_next();
26 void play_prev();
27 void init_ctl();
28 void push_dir(char *s);
29 void push_dirname(char *s);
30 char *pop_dir();
31 char *next_mp3dir();
32 char *prev_mp3dir();
33 char *current_mp3dir();
34 void show_directory_name();
35 void load_next_dir();
36 void load_prev_dir();
37 void alarmhandler(int sig);
38 void scroll_title();
39 void finish();
40 void dostuff();
42 char *dirs[MAXDIRS];
43 int top = 0;
44 int max_dirs = 0;
45 int current_dir = 0;
47 char *dirnames[MAXDIRS];
48 int ntop = 0;
49 int nmax_dirs = 0;
51 char mpg123_cmd[512];
52 char mp3ext[12];
53 char playlistext[12];
55 int next_song = 0;
56 int num_songs = 0;
57 int play_pid = 0;
59 char title[512];
60 int scroll_pos = 0;
61 int do_scroll = 0;
62 int always_scroll = 0;
64 int repeat_flag = 0;
65 int random_flag = 0;
66 int *rand_song_num = NULL;
68 int is_playing()
70 if (play_pid > 0)
71 return 1;
72 else
73 return 0;
77 * patch received from Steven Jorgensen to fix following function
80 void set_playlist()
82 char *directory;
83 DIR *dp;
84 struct dirent *entry;
85 char filename[512];
87 int i, tempnum, temppos;
89 directory = (char *) current_mp3dir();
91 if (directory)
93 dp = opendir(directory);
94 if (dp == NULL) {
95 char *new_directory;
96 new_directory = (char *) next_mp3dir();
97 dp = opendir(new_directory);
98 while (new_directory && (strcmp(new_directory, directory) != 0) &&
99 (dp == NULL)) {
100 strcpy(directory, new_directory);
101 new_directory = (char *) next_mp3dir();
102 dp = opendir(new_directory);
104 if (new_directory)
105 strcpy(directory, new_directory);
107 if (dp != NULL) {
108 show_directory_name();
109 num_songs = 0;
110 empty_hash();
111 entry = readdir(dp);
112 while (entry != NULL) {
113 if (strstr(entry->d_name, mp3ext)) {
114 sprintf(filename, "%s/%s", directory, entry->d_name);
115 insert_song(num_songs, entry->d_name, filename);
116 num_songs++;
118 entry = readdir(dp);
120 next_song = 0;
122 /* Create Pseudo-random permutation of list */
123 srand(time(NULL));
124 rand_song_num = (int *)malloc(sizeof(int)*num_songs);
125 if (!rand_song_num) {
126 /* This shouldn't happen - the list isn't that big */
127 fprintf(stderr,
128 "Error: cannot allocate randomized list\n");
129 exit(1);
131 for (i=0; i<num_songs; i++) rand_song_num[i] = i;
132 for (i=0; i<num_songs; i++) {
133 tempnum = rand_song_num[i];
134 temppos = rand()%num_songs;
135 rand_song_num[i] = rand_song_num[temppos];
136 rand_song_num[temppos] = tempnum;
144 * functions that actually control mpg123
147 void signal_play()
149 int status;
151 waitpid(play_pid, &status, 0);
152 play_pid = 0;
153 play_next();
156 void play(char *song_name)
158 if ((play_pid = fork()) == 0) {
159 execl(mpg123_cmd, mpg123_cmd, "-q",
160 song_name, 0);
161 _exit(1);
165 void play_next()
167 struct hash_elt *song;
169 if (next_song >= num_songs) {
170 if (repeat_flag == 0) {
171 load_next_dir();
172 } else {
173 next_song = 0;
176 song = get_song(next_song);
177 if (random_flag) {
178 song = get_song(rand_song_num[next_song]);
180 if (song) {
181 strcpy(title, song->title);
182 strcat(title, " ");
183 scroll_pos = 0;
184 do_scroll = 1;
185 scroll_title();
187 play(song->filename);
188 next_song++;
189 signal(SIGCHLD, signal_play);
190 signal(SIGALRM, alarmhandler);
191 alarm(1);
195 void play_prev()
197 struct hash_elt *song;
199 if (next_song <= 1) {
200 next_song = 0;
202 else {
203 next_song = next_song - 2;
206 play_next();
209 void user_play()
211 if (play_pid == 0) {
212 signal(SIGCHLD, signal_play);
213 set_playlist();
214 play_next();
218 void stop()
220 int status;
222 if (play_pid > 0) {
223 signal(SIGCHLD, SIG_IGN);
224 kill(play_pid, SIGINT);
225 kill(play_pid, SIGTERM);
226 kill(play_pid, SIGKILL);
227 waitpid(play_pid, &status, 0);
228 play_pid = 0;
232 void next()
234 stop();
235 play_next();
238 void back()
240 stop();
241 play_prev();
245 * initialization functions
248 void init_ctl()
250 signal(SIGINT, finish);
251 signal(SIGCHLD, dostuff);
252 set_playlist();
255 void set_mpg123(char *s)
258 strcpy(mpg123_cmd, s);
261 void set_mp3ext(char *s)
263 strcpy(mp3ext, s);
266 void set_playlistext(char *s)
268 strcpy(playlistext, s);
271 void set_alwaysscroll(char *s) {
272 char *temp = s;
273 while (*temp) {
274 *temp = tolower(*temp);
275 temp++;
277 if ( !strcmp(s, "on") || !strcmp(s, "yes") || !strcmp(s, "1") ||
278 !strcmp(s, "true")) {
279 always_scroll = 1;
280 } else {
281 always_scroll = 0;
286 void push_dir(char *s)
288 dirs[top] = (char *) malloc(strlen(s) + 1);
289 strcpy(dirs[top], s);
290 top++;
291 max_dirs++;
294 void push_dirname(char *s)
296 /* from Steven Jorgensen */
297 if ((strlen(s) + 1) < 10)
298 dirnames[ntop] = (char *) malloc(10);
299 else
300 dirnames[ntop] = (char *) malloc(strlen(s) + 1);
301 strcpy(dirnames[ntop], s);
302 ntop++;
303 nmax_dirs++;
306 char *pop_dir()
308 max_dirs--;
309 return (dirs[top--]);
312 void add_mp3dir(char *s)
314 push_dir(s);
317 void add_mp3dirname(char *s)
319 push_dirname(s);
323 * directory manipulation
326 char *next_mp3dir()
328 if (current_dir < (max_dirs - 1)) {
329 current_dir++;
331 return (dirs[current_dir]);
334 char *prev_mp3dir()
336 if (current_dir > 0) {
337 current_dir--;
339 return (dirs[current_dir]);
342 char *current_mp3dir()
344 return (dirs[current_dir]);
347 void show_directory_name()
349 if (dirnames[current_dir] != NULL) {
350 while (strlen(dirnames[current_dir]) < 9) {
351 strcat(dirnames[current_dir], " ");
353 draw_string(dirnames[current_dir], 5, 5);
354 } else {
355 draw_string("no dirname", 5, 5);
359 void dir_up(int button_num)
361 if (!is_playing()) {
362 button_down(button_num);
363 load_prev_dir();
367 void dir_down(int button_num)
369 if (!is_playing()) {
370 button_down(button_num);
371 load_next_dir();
375 void load_next_dir()
377 next_mp3dir();
378 set_playlist();
381 void load_prev_dir()
383 prev_mp3dir();
384 set_playlist();
388 * song title functions
391 void alarmhandler(int sig)
393 if ((play_pid > 0) && (do_scroll == 1)) {
394 scroll_title();
395 signal(SIGALRM, alarmhandler);
396 alarm(1);
400 void scroll_title()
402 char s[MAX_TITLE_LEN + 1];
403 int i;
404 int title_len;
406 title_len = strlen(title);
407 if (do_scroll) {
408 for (i = 0; i < MAX_TITLE_LEN; i++) {
409 s[i] = title[(i + scroll_pos) % title_len];
411 s[i] = '\0';
412 draw_string(s, 5, 19);
413 scroll_pos++;
414 if (scroll_pos > title_len) {
415 scroll_pos = 0;
416 if (!always_scroll) {
417 do_scroll = 0;
420 } else {
421 draw_string(title, 5, 19);
423 RedrawWindow();
426 void turn_on_scroll()
428 if ((!do_scroll) && (is_playing())) {
429 do_scroll = 1;
430 scroll_pos = 0;
431 signal(SIGALRM, alarmhandler);
432 alarm(1);
437 * toggles
440 void random_toggle(int button_num)
442 /* button_gray(button_num); */
443 if (random_flag == 0) {
444 button_down(button_num);
445 random_flag = 1;
446 } else {
447 button_up(button_num);
448 random_flag = 0;
452 void repeat_toggle(int button_num)
454 if (repeat_flag == 0) {
455 button_down(button_num);
456 repeat_flag = 1;
457 } else {
458 button_up(button_num);
459 repeat_flag = 0;
464 * cleanup
467 void finish()
469 stop();
473 * misc
475 void dostuff()
477 /* empty */