Newsgroup: it.fan.marco-ditri
Titolo: mp3 player

E` mpg123  che richiede  mp3 perfetti-o-quasi. Purtroppo,  perche`, dato
Per questo ho scritto una soluzione.
Attenzione: l'ho scritto per me, non per voi. Quindi non e`
configurabile se non tramite i sorgenti.
Si aspetta in LISTDIR la playlist indicata sulla riga di comando e un
CD montato in /cdrom. Un ulteriore parametro sulla riga di comando
chiede che le canzoni siano suonate a caso.
scamble() e` una piccola meraviglia che ho trovato sul DDJ di qualche
mese fa.
Un ^C passa alla canzone successiva, due ^C terminano il programma.
SIGUSR1 fa suonare in loop la canzone attuale.
Dovrebbe essere BugFree(tm), ma se trovate qualcosa di strano fatemelo
sapere. Richieste di nuove feature saranno ignorate con una risata.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/statfs.h>
#define ISOFS_SUPER_MAGIC 0x9660
#define LISTDIR "/home/md/.xmms"
const char *copyname(char *);
void run_player(const char *);
void scramble(void *[], int);
void haltinc(int);
void haltreset(int);
void toggleloop(int);
void err_quit(const char *, ...);
void err_sys(const char *, ...);
struct node {
    const char *song;
    struct node *next;
};
/* global flags */
int haltflag = 0;
int loop = 0;
int main(int argc, char *argv[])
{
    struct statfs sb;
    FILE *fp;
    char buf[1024];
    struct node *list, *cur, *last;
    int i, elements = 0;
    struct node **songs;
    if (argc < 2)
	err_quit("Usage: mp playlist");
    if (statfs("/cdrom", &sb) < 0)
	err_sys("[!] stat(\"/dev/cdrom\") failed");
    if (sb.f_type != ISOFS_SUPER_MAGIC)
	err_quit("[!] /cdrom is not mounted!");
    if (argv[1][0] == '-' && argv[1][1] == '\0') {
	int newfd;
	if ((newfd = dup(0)) < 0)
	    err_sys("[!] dup(0)");
	if ((fp = fdopen(newfd, "r")) == NULL)
	    err_sys("[!] fdopen(0)");
    } else {
	snprintf(buf, 1024, LISTDIR "/%s", argv[1]);
	if ((fp = fopen(buf, "r")) == NULL)
	    err_sys("[!] Cannot open %s", buf);
    }
    last = list = cur = malloc(sizeof(struct node));
    while (fgets(buf, 1024, fp) != NULL) {
	if ((cur->song = copyname(buf)) == NULL)
	    continue;		/* skip comments */
	last = cur;
	cur = cur->next = malloc(sizeof(struct node));
	elements++;
    }
    last->next = NULL;		/* mark the last element */
    free(cur);			/* this element won't be used */
    if (ferror(fp))
	err_sys("[!] Error while reading playlist file");
    fclose(fp);
    signal(SIGINT, haltinc);
    signal(SIGALRM, haltreset);
    signal(SIGUSR1, toggleloop);
    songs = malloc(elements * sizeof(struct node));
    cur = list;
    for (i = 0; i < elements; i++) {
	songs[i] = cur;
	cur = cur->next;
    }
    if (argv[2]) {
	puts("[*] Scambling playlist...");
	srand(time(NULL));
	scramble((void **) songs, elements);
    }
    for (i = 0; i < elements; i++) {
again:	printf("[*] Playing %s\n", songs[i]->song);
	run_player(songs[i]->song);
	if (haltflag >= 2)
	    err_quit("[*] Program halted. Goodbye.");
	if (loop)
	    goto again;
    }
    exit(0);
}
const char *copyname(char *s)
{
    char *p, *q, *new;
    if (*s == '#' || *s == '\n' || *s == '\0')
	return NULL;
    p = new = malloc(strlen(s) + 1);
    q = s;
    /* copy the file name skipping CR, LF and NULs */
    for (; *q && *q != '\n' && *q != '\r'; *p++ = *q++);
    *p = '\0';
    return new;
}
void run_player(const char *file)
{
    int pid = fork();
    if (pid < 0)
	err_sys("[!] Cannot fork");
    if (pid == 0) {
	execl("/usr/bin/mpg123", "mpg123",
	      "--aggressive", "-v", "-q", file, NULL);
	perror("[!] execl failed");
	abort();
	exit(0);
    }
    while (1) {
	int status;
	if (waitpid(pid, &status, 0) == -1) {
	    if (errno != EINTR)			/* something bad happened */
		err_sys("[!] waitpid failed");
	    printf("\n[?] DEBUG: interrupted\n");
	} else {
	    if (WIFSIGNALED(status))
		printf("\n[!] Child got signal %d", WTERMSIG(status));
	    else if (WIFEXITED(status)) {
		int s = WEXITSTATUS(status);
		if (s)
		    printf("\n[!] Child exited with status %d", s);
	    }
	    printf("\n\n");
	    break;
	}
    }
    return;
}
/* randomize the contents of an array of n pointers */
void scramble(void *x[], int n)
{
    void *temp;
    int src, dest;
    for (dest = n - 1; dest > 0; dest--) {
	src = rand() % (dest + 1);
	temp = x[dest]; x[dest] = x[src]; x[src] = temp;
    }
}
/* Signals handling */
void haltinc(int dummy)
{
    haltflag++;
    alarm(1);
}
void haltreset(int dummy)
{
    haltflag = 0;
}
void toggleloop(int dummy)
{
    if (loop) {
	loop = 0;
	puts("\n\n[*] Looping disabled\n");
    } else {
	loop = 1;
	puts("\n\n[*] Looping enabled\n");
    }
}
/* Error routines */
void err_sys(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    fprintf(stderr, ": %s\n", strerror(errno));
    va_end(ap);
    exit(1);
}
void err_quit(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    fputs("\n", stderr);
    va_end(ap);
    exit(1);
}
-- 
ciao, | [Per rispondere togli "toglimi" dal mio indirizzo.]
Marco | * The Internet is full. Go away.  -- Joel Furr *
      | (Ri)scoprire fidonet: 
http://bbs.mi.linux.it

 ICFAQ 3.01 - Manuale italiano di Internet 
http://bertola.eu.org/icfaq/
 <
---------------------> NO, NON FACCIO PARTE DEL GCN <---------------------