#include "stdinc.h"
#include "utils.h"
#include "mp3.h"
struct mp3_player g_player;
int mp3_file_open(struct mp3_player *plyer)
{
char fpath[86];
sprintf(fpath, "%s/%s", plyer->pcurs->path, plyer->pcurs->name);
plyer->pcurs->fd = open(fpath, O_RDONLY);
if (-1 == plyer->pcurs->fd)
ERR_PRINT_RET(-1);
return 0;
}
int mp3_file_close(struct mp3_player *plyer)
{
close(plyer->pcurs->fd);
return 0;
}
int mp3_get_trailer(struct mp3_player *plyer)
{
char tag[5];
lseek(plyer->pcurs->fd, -128L, SEEK_END);
read(plyer->pcurs->fd, tag, 3);
if (strncmp(tag, "TAG", 3)) {
plyer->pcurs->trailer= NULL;
return 0;
}
plyer->pcurs->trailer =
(struct mp3_trailer*)malloc(sizeof(struct mp3_trailer));
lseek(plyer->pcurs->fd, -128L, SEEK_END);
read(plyer->pcurs->fd, plyer->pcurs->trailer, sizeof(struct mp3_trailer));
DBG("Title: %s\n", plyer->pcurs->trailer->title);
DBG("Artist: %s\n", plyer->pcurs->trailer->artist);
DBG("Album: %s\n", plyer->pcurs->trailer->album);
DBG("Year: %s\n", plyer->pcurs->trailer->year);
DBG("Comment: %s\n", plyer->pcurs->trailer->comment);
return 0;
}
static int postfix_match(char* fn, char* pf)
{
char* tfn;
for (tfn=fn; *tfn!='.' && *tfn!=0; tfn++);
if (*tfn==0 || pf==0)
return -1;
tfn++;
return strcmp(tfn, pf);
}
int mp3_init_sglist(struct mp3_player *plyer, const char *path)
{
DIR *dir;
struct dirent *ptr;
struct mp3_info *item;
int i = 0;
INIT_LIST_HEAD(&plyer->sghead);
dir = opendir(path);
while (NULL != (ptr=readdir(dir))) {
if (0 != postfix_match(ptr->d_name, "mp3"))
continue;
item = (struct mp3_info*)malloc(sizeof(struct mp3_info));
if (item==NULL) {
list_for_each_entry(item, &plyer->sghead, sglist) {
free(item);
}
return -1;
}
item->sgid = i + 1;
strcpy(item->name, ptr->d_name);
strcpy(item->path, path);
list_add_tail(&item->sglist, &plyer->sghead);
i++;
}
plyer->sg_nr = i;
return 0;
}
int mp3_set_volume(struct mp3_player *plyer, int vol)
{
#if defined(SND_OSS)
plyer->vol = vol;
if (-1 == ioctl(plyer->mixfd,
SOUND_MIXER_WRITE_VOLUME,
&vol))
ERR_PRINT_RET(-1);
if (-1 == ioctl(plyer->mixfd,
SOUND_MIXER_READ_VOLUME,
&vol))
ERR_PRINT_RET(-1);
//plyer->vol = vol;
#elif defined(SND_ALSA)
char cmd[86];
if (vol > 100)
vol = 100;
if (vol < 0)
vol = 0;
//sprintf(cmd, "amixer cset name='Voice Playback Master Volume' %d%% ", vol);
sprintf(cmd, "amixer cset name='PCM Playback Volume' %d%% > /dev/null ", vol);
system(cmd);
plyer->vol = vol;
#endif
return 0;
}
static int mp3_tmpfile_open(struct mp3_player *plyer)
{
plyer->tmpfp = fopen(TMP_FILE_NAME, "w+");
if (NULL == plyer->tmpfp)
ERR_PRINT_RET(-1);
return 0;
}
static void mp3_tmpfile_close(struct mp3_player *plyer)
{
fclose(plyer->tmpfp);
}
static int mp3_get_total_time(struct mp3_player *plyer)
{
pid_t pid;
if (-1==(pid=fork())) {
ERR_PRINT_EXT(EXIT_FAILURE);
} else if (0 == pid) {
char **args; //命令
args = (char**)malloc((plyer->sg_nr + 2) * sizeof(char**));
args[0] = "madplay";
args[1] = "-QI";
int i = 2;
struct mp3_info *item;
list_for_each_entry(item, &plyer->sghead, sglist) {
char fpath[86];
sprintf(fpath, "%s/%s", item->path, item->name);
args[i] = strdup(fpath);
i++;
}
args[i] = NULL;
for (i=0; args[i]!=NULL; i++) {
DBG("args[%d] = %s\n", i, args[i]);
}
if (execv("/usr/bin/madplay", args))
//if (execv("/opt/Enjoylinux/madplay/libs/madplay-0.15.2b/madplay", args))
ERR_PRINT_EXT(EXIT_FAILURE);
} else {
int status;
waitpid(pid, &status, 0);
DBG("get_total process is over!, status = %d\n", status);
if (0 == status) {
struct mp3_info *item;
char buf[256];
list_for_each_entry(item, &plyer->sghead, sglist) {
item->total_time = atoi(fgets(buf, 256, plyer->tmpfp));
DBG("TOTAL TIME = %d\n", item->total_time);
}
}
}
return 0;
}
void mp3_update_cur_time(struct mp3_player *plyer)
{
char buf[256];
fflush(plyer->tmpfp);
fseek(plyer->tmpfp, 0, SEEK_SET);
if (NULL==fgets(buf, 256, plyer->tmpfp))
return;
//DBG("cur_time = %s\n", buf);
plyer->cur_time = atoi(buf);
}
int mp3_player_init(struct mp3_player *plyer, const char *path)
{
if (-1 == mp3_tmpfile_open(plyer))
return -1;
if (-1 == mp3_init_sglist(plyer, path))
return -1;
list_for_each_entry(plyer->pcurs, &plyer->sghead, sglist) {
DBG("NAME: %s\n", plyer->pcurs->name);
if (-1 == mp3_file_open(plyer))
return -1;
if (-1 == mp3_get_trailer(plyer))
return -1;
if (-1 == mp3_file_close(plyer))
return -1;
}
if (-1 == mp3_get_total_time(plyer))
return -1;
plyer->stat = PLY_STAT_STOP;
plyer->mode = PLY_MODE_REPALL;
plyer->vol = PLY_VOL_DEF;
plyer->cur_time = 0;
plyer->pcurs = //初始化歌曲列表后,将第一个歌曲结构赋给 pcurs
list_entry((&plyer->sghead)->next, typeof(struct mp3_info), sglist);
DBG("CUR NAME: %s\n", plyer->pcurs->name);
#if defined(SND_OSS)
plyer->mixfd = open(PLY_VOL_DEV, O_RDWR);
if (-1 == plyer->mixfd)
ERR_PRINT_RET(-1);
#elif defined(SND_ALSA)
#endif
mp3_set_volume(plyer, plyer->vol);
return 0;
}
int mp3_prev_song(struct mp3_player *plyer)
{
struct list_head *pos = &plyer->pcurs->sglist;
if (pos->prev == &plyer->sghead)
pos = pos->prev;
plyer->pcurs =
list_entry(pos->prev, typeof(struct mp3_info), sglist);
plyer->cur_time = 0;
return 0;
}
int mp3_next_song(struct mp3_player *plyer)
{
struct list_head *pos = &plyer->pcurs->sglist;
if (pos->next == &plyer->sghead)
pos = pos->next;
plyer->pcurs =
list_entry(pos->next, typeof(struct mp3_info), sglist);
plyer->cur_time = 0;
return 0;
}
int mp3_pick_next(struct mp3_player *plyer)
{
int i;
struct list_head *pos = &plyer->pcurs->sglist;
switch (plyer->mode) {
case PLY_MODE_REPONE:
break;
case PLY_MODE_REPALL:
if (pos->next == &plyer->sghead)
pos = pos->next;
plyer->pcurs =
list_entry(pos->next, typeof(struct mp3_info), sglist);
break;
case PLY_MODE_RANDOM:
i = get_random_nr() % plyer->sg_nr + 1;
list_for_each_entry(plyer->pcurs, &plyer->sghead, sglist) {
if (i == plyer->pcurs->sgid)
break;
}
break;
default:
break;
}
plyer->cur_time = 0;
//DBG("%s\n", plyer->pcurs->name);
return 0;
}