dockapps/wmmp3/mpg123ctl.c

480 lines
7.5 KiB
C

/*
* wmmp3
* Copyright (c)1999 Patrick Crosby <xb@dotfiles.com>.
* 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 <matt@campbellhome.dhs.org>
*
* $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; i++) rand_song_num[i] = i;
for (i=0; i<num_songs; i++) {
tempnum = rand_song_num[i];
temppos = rand()%num_songs;
rand_song_num[i] = rand_song_num[temppos];
rand_song_num[temppos] = tempnum;
}
}
}
}
/*
* functions that actually control mpg123
*/
void signal_play()
{
int status;
waitpid(play_pid, &status, 0);
play_pid = 0;
play_next();
}
void play(char *song_name)
{
if ((play_pid = fork()) == 0) {
execl(mpg123_cmd, mpg123_cmd, "-q",
song_name, 0);
_exit(1);
}
}
void play_next()
{
struct hash_elt *song;
if (next_song >= 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 */
}