/* * wmmp3 * Copyright (c)1999 Patrick Crosby . * This software covered by the GPL. See COPYING file for details. * * mpg123ctl.c * * This file contains all the functions for controlling the * mpg123 backend processes. * * Random play functionality courtesy of: * Matthew D. Campbell * * $Id: mpg123ctl.c,v 1.15 1999/10/12 04:41:20 pcrosby Exp $ */ #include "mpg123ctl.h" #define MAXDIRS 100 #define MAX_TITLE_LEN 9 void set_playlist(); void signal_play(); void play(); void play_next(); void play_prev(); void init_ctl(); void push_dir(char *s); void push_dirname(char *s); char *pop_dir(); char *next_mp3dir(); char *prev_mp3dir(); char *current_mp3dir(); void show_directory_name(); void load_next_dir(); void load_prev_dir(); void alarmhandler(int sig); void scroll_title(); void finish(); void dostuff(); char *dirs[MAXDIRS]; int top = 0; int max_dirs = 0; int current_dir = 0; char *dirnames[MAXDIRS]; int ntop = 0; int nmax_dirs = 0; char mpg123_cmd[512]; char mp3ext[12]; char playlistext[12]; int next_song = 0; int num_songs = 0; int play_pid = 0; char title[512]; int scroll_pos = 0; int do_scroll = 0; int always_scroll = 0; int repeat_flag = 0; int random_flag = 0; int *rand_song_num = NULL; int is_playing() { if (play_pid > 0) return 1; else return 0; } /* * patch received from Steven Jorgensen to fix following function */ void set_playlist() { char *directory; DIR *dp; struct dirent *entry; char filename[512]; int i, tempnum, temppos; directory = (char *) current_mp3dir(); if (directory) { dp = opendir(directory); if (dp == NULL) { char *new_directory; new_directory = (char *) next_mp3dir(); dp = opendir(new_directory); while (new_directory && (strcmp(new_directory, directory) != 0) && (dp == NULL)) { strcpy(directory, new_directory); new_directory = (char *) next_mp3dir(); dp = opendir(new_directory); } if (new_directory) strcpy(directory, new_directory); } if (dp != NULL) { show_directory_name(); num_songs = 0; empty_hash(); entry = readdir(dp); while (entry != NULL) { if (strstr(entry->d_name, mp3ext)) { sprintf(filename, "%s/%s", directory, entry->d_name); insert_song(num_songs, entry->d_name, filename); num_songs++; } entry = readdir(dp); } next_song = 0; /* Create Pseudo-random permutation of list */ srand(time(NULL)); rand_song_num = (int *)malloc(sizeof(int)*num_songs); if (!rand_song_num) { /* This shouldn't happen - the list isn't that big */ fprintf(stderr, "Error: cannot allocate randomized list\n"); exit(1); } for (i=0; i= num_songs) { if (repeat_flag == 0) { load_next_dir(); } else { next_song = 0; } } song = get_song(next_song); if (random_flag) { song = get_song(rand_song_num[next_song]); } if (song) { strcpy(title, song->title); strcat(title, " "); scroll_pos = 0; do_scroll = 1; scroll_title(); play(song->filename); next_song++; signal(SIGCHLD, signal_play); signal(SIGALRM, alarmhandler); alarm(1); } } void play_prev() { struct hash_elt *song; if (next_song <= 1) { next_song = 0; } else { next_song = next_song - 2; } play_next(); } void user_play() { if (play_pid == 0) { signal(SIGCHLD, signal_play); set_playlist(); play_next(); } } void stop() { int status; if (play_pid > 0) { signal(SIGCHLD, SIG_IGN); kill(play_pid, SIGINT); kill(play_pid, SIGTERM); kill(play_pid, SIGKILL); waitpid(play_pid, &status, 0); play_pid = 0; } } void next() { stop(); play_next(); } void back() { stop(); play_prev(); } /* * initialization functions */ void init_ctl() { signal(SIGINT, finish); signal(SIGCHLD, dostuff); set_playlist(); } void set_mpg123(char *s) { strcpy(mpg123_cmd, s); } void set_mp3ext(char *s) { strcpy(mp3ext, s); } void set_playlistext(char *s) { strcpy(playlistext, s); } void set_alwaysscroll(char *s) { char *temp = s; while (*temp) { *temp = tolower(*temp); temp++; } if ( !strcmp(s, "on") || !strcmp(s, "yes") || !strcmp(s, "1") || !strcmp(s, "true")) { always_scroll = 1; } else { always_scroll = 0; } } void push_dir(char *s) { dirs[top] = (char *) malloc(strlen(s) + 1); strcpy(dirs[top], s); top++; max_dirs++; } void push_dirname(char *s) { /* from Steven Jorgensen */ if ((strlen(s) + 1) < 10) dirnames[ntop] = (char *) malloc(10); else dirnames[ntop] = (char *) malloc(strlen(s) + 1); strcpy(dirnames[ntop], s); ntop++; nmax_dirs++; } char *pop_dir() { max_dirs--; return (dirs[top--]); } void add_mp3dir(char *s) { push_dir(s); } void add_mp3dirname(char *s) { push_dirname(s); } /* * directory manipulation */ char *next_mp3dir() { if (current_dir < (max_dirs - 1)) { current_dir++; } return (dirs[current_dir]); } char *prev_mp3dir() { if (current_dir > 0) { current_dir--; } return (dirs[current_dir]); } char *current_mp3dir() { return (dirs[current_dir]); } void show_directory_name() { if (dirnames[current_dir] != NULL) { while (strlen(dirnames[current_dir]) < 9) { strcat(dirnames[current_dir], " "); } draw_string(dirnames[current_dir], 5, 5); } else { draw_string("no dirname", 5, 5); } } void dir_up(int button_num) { if (!is_playing()) { button_down(button_num); load_prev_dir(); } } void dir_down(int button_num) { if (!is_playing()) { button_down(button_num); load_next_dir(); } } void load_next_dir() { next_mp3dir(); set_playlist(); } void load_prev_dir() { prev_mp3dir(); set_playlist(); } /* * song title functions */ void alarmhandler(int sig) { if ((play_pid > 0) && (do_scroll == 1)) { scroll_title(); signal(SIGALRM, alarmhandler); alarm(1); } } void scroll_title() { char s[MAX_TITLE_LEN + 1]; int i; int title_len; title_len = strlen(title); if (do_scroll) { for (i = 0; i < MAX_TITLE_LEN; i++) { s[i] = title[(i + scroll_pos) % title_len]; } s[i] = '\0'; draw_string(s, 5, 19); scroll_pos++; if (scroll_pos > title_len) { scroll_pos = 0; if (!always_scroll) { do_scroll = 0; } } } else { draw_string(title, 5, 19); } RedrawWindow(); } void turn_on_scroll() { if ((!do_scroll) && (is_playing())) { do_scroll = 1; scroll_pos = 0; signal(SIGALRM, alarmhandler); alarm(1); } } /* * toggles */ void random_toggle(int button_num) { /* button_gray(button_num); */ if (random_flag == 0) { button_down(button_num); random_flag = 1; } else { button_up(button_num); random_flag = 0; } } void repeat_toggle(int button_num) { if (repeat_flag == 0) { button_down(button_num); repeat_flag = 1; } else { button_up(button_num); repeat_flag = 0; } } /* * cleanup */ void finish() { stop(); } /* * misc */ void dostuff() { /* empty */ }