/* I would guess that this is the main file for Cmp3. When you do something, this code cares. Of course, it is probably buggy so don't think it can make your life meaningful just yet. */ #define CMP3_NO_NEED_VARS /* Don't get extern globals from cmp3funcs.h */ #include "keydef.h" #include "cmp3funcs.h" #include "cmp3id3.h" /*--- Global variables defined, let everyone else just extern them ---*/ LLIST list_left, list_right; WINDOW *pad_left, /* Pads on the inside */ *pad_right, *pad_list, *win_left, /* Outside windows */ *win_right, *win_list; int shmid, /* ID for shared memory block */ curwin; /* Which window has focus */ shmdata_t *shmptr; /* Pointer to shared memory block */ int noDirChange = 0; /* Don't change directory, passed on cmd line */ INI cmp3rc = NULL; char directory[MAX_FULL]; /* The Code That Cares */ int main(int argc, char **argv) { int command; int lastleftline = 0; int lastrightline = 0; char *init_dir = NULL; char *home_dir = NULL; char cmp3_config[4096]; if (argc > 1) docmdline(argc, argv); shm_init(); cmp3rc = ini_create(); home_dir = getenv("HOME"); strcpy (cmp3_config, home_dir); strcat (cmp3_config, "/.cmp3rc"); if (ini_load(cmp3rc, cmp3_config) == INI_FAIL) { ini_destroy(cmp3rc); cmp3rc = NULL; } curs_init(); initialize(); curwin = FOCUSED_LEFT; wnoutrefresh(stdscr); wnoutrefresh(win_left); wrefresh(win_right); if (noDirChange == 0) { init_dir = ini_getValueString(cmp3rc, "cmp3_options", "initial_directory"); if (init_dir != NULL) chdir(init_dir); } getcwd(directory, MAX_FULL); init_dir = strdup(directory); init_lists(directory, 0, 0); refreshpads(); while (1) { command=getch(); switch(command) { /**************************************************************************** * Q (quit) */ case CMP3_KEY_QUIT: if ((ini_getValueBool(cmp3rc, "cmp3_options", "quit_confirm", 1) == 0) || (dialogbox("Really Quit?") == 1)) { kill(shmptr->managpid,SIGINT); free(init_dir); enditall(1); } dialog_clean(); break; /**************************************************************************** * Enter */ case CMP3_KEY_ENTER: if (curwin == FOCUSED_LEFT) { char startatlast = 0; if (dirchange(directory, ((list_left_t*)ll_data(list_left))->name) == 0) break; if (strcmp(((list_left_t*)ll_data(list_left))->name, "..") == 0) { startatlast = 1; } else { lastleftline = ll_curnum(list_left); lastrightline = ll_curnum(list_right); } free_lists(); pads_clean(); if (startatlast == 1) { init_lists(directory, lastleftline, lastrightline); lastleftline = lastrightline = 0; } else init_lists(directory, 0, 0); refreshpads(); } else { char fullpath[MAX_FULL]; char *name; if (ll_data(list_right) == NULL) break; name = ((list_right_t*) ll_data(list_right))->name; strcpy(fullpath, directory); strcat(fullpath, "/"); strcat(fullpath, name); if (isPlaylist(fullpath)) readlist(fullpath); else pl_addentry(fullpath); } break; /**************************************************************************** * Down */ case CMP3_KEY_DOWN1: case CMP3_KEY_DOWN2: { LLIST thelist; int *curline; curline = getcurline(&thelist); if (ll_curnum(thelist) == ll_total(thelist) - 1) break; ll_next(thelist); ll_prnprev(thelist); ll_prncur(thelist); /* Scroll if needed */ if (ll_curnum(thelist) != ll_total(thelist)) if (*curline + (LINES-15) < ll_curnum(thelist)) if (ll_curnum(thelist) != ll_total(thelist) - 1) *curline += 1; refreshpad(curwin); } break; /**************************************************************************** * Up */ case CMP3_KEY_UP1: case CMP3_KEY_UP2: { LLIST thelist; int *curline; curline = getcurline(&thelist); if (ll_curnum(thelist) == 0) break; if (*curline != 0) { if (*curline >= ll_curnum(thelist)-1) *curline -= 1; if (*curline == ll_curnum(thelist)) *curline -= 1; } ll_prev(thelist); ll_prncur(thelist); ll_prnnext(thelist); refreshpad(curwin); } break; /**************************************************************************** * Page down or V */ case CMP3_KEY_PGDN1: case CMP3_KEY_PGDN2: { int *curline, i; LLIST thewin; curline = getcurline(&thewin); if ((int)(ll_curnum(thewin) + LINES - 14) < (ll_total(thewin) - 1)) { *curline += LINES-14; if (*curline > (ll_total(thewin) - 14)) *curline = ll_total(thewin) - (LINES-13); ll_next(thewin); ll_prnprev(thewin); for (i=0; i < LINES-15; i++) if (ll_next(thewin) == NULL) { *curline = ll_total(thewin) - LINES - 14; ll_reset(thewin); ll_prev(thewin); break; } ll_prncur(thewin); } else { *curline = ll_total(thewin) - LINES + 13; if (ll_curnum(thewin) != ll_total(thewin) - 1) { i = curwin; curwin = FOCUSED_NONE; ll_prncur(thewin); curwin = i; ll_reset(thewin); ll_prev(thewin); ll_prncur(thewin); } } refreshpad(curwin); } break; /**************************************************************************** * Page up or U */ case CMP3_KEY_PGUP1: case CMP3_KEY_PGUP2: { int *curline, i; LLIST thewin; curline = getcurline(&thewin); if ((int)(ll_curnum(thewin) - (LINES-14)) > 0 ) { *curline -= LINES-14; ll_prev(thewin); ll_prnnext(thewin); for (i=0; i < LINES-15; i++) if (ll_prev(thewin) == NULL) { *curline = 0; ll_reset(thewin); ll_next(thewin); break; } ll_prncur(thewin); } else { *curline = 0; if (ll_curnum(thewin) != 0) { i = curwin; curwin = FOCUSED_NONE; ll_prncur(thewin); curwin = i; ll_reset(thewin); ll_next(thewin); ll_prncur(thewin); } } refreshpad(curwin); } break; /**************************************************************************** * Left, Right or Tab */ case CMP3_KEY_SWITCH1: case CMP3_KEY_SWITCH2: case CMP3_KEY_SWITCH3: curwin = switchwin(curwin); break; /**************************************************************************** * Volume control (+ and -) */ case CMP3_KEY_VOLUP1: case CMP3_KEY_VOLUP2: volup(); break; case CMP3_KEY_VOLDWN1: case CMP3_KEY_VOLDWN2: voldown(); break; /**************************************************************************** * Delete */ case CMP3_KEY_DELETE: if (curwin == FOCUSED_LEFT) break; if (ll_data(list_right) == NULL) break; if ((ini_getValueBool(cmp3rc, "cmp3_options", "delete_confirm", 1) == 0) || (dialogbox("Delete this file?") == 1)) { char fullpath[MAX_FULL]; strcpy(fullpath, directory); strcat(fullpath,"/"); strcat(fullpath,((list_right_t*)ll_data(list_right))->name); remove(fullpath); /* XXX Ick */ pads_clean(); free_lists(); init_lists(directory, 0, 0); } dialog_clean(); break; /**************************************************************************** * L (list mode) * blends into refresh */ case CMP3_KEY_LISTMODE: { int curwinbackup; curwinbackup = curwin; curwin = FOCUSED_LIST; dolist(); curwin = curwinbackup; } /**************************************************************************** * R (refresh screen) */ case CMP3_KEY_REFRESH: if (command == CMP3_KEY_REFRESH) { pads_clean(); free_lists(); init_lists(directory, 0, 0); } after_list(); break; /**************************************************************************** * P (pause song) */ case CMP3_KEY_PAUSE: /* XXX - find out if bufferring and pause all pids */ if (shmptr->pid) { if (!shmptr->pause) { shmptr->pause=1; kill(shmptr->pid,SIGSTOP); } else { shmptr->pause=0; kill(shmptr->pid,SIGCONT); } } break; /**************************************************************************** * F5 (restart song) - drops into kill */ case CMP3_KEY_RESTART: if (!shmptr->pid) break; pl_dupfirst(); if (shmptr->repeat == 1) shmptr->listlen -= 1; /**************************************************************************** * K (kill song) */ case CMP3_KEY_KILL1: case CMP3_KEY_KILL2: if (shmptr->pid) kill(shmptr->pid,SIGKILL); shmptr->pause=0; break; /**************************************************************************** * H (home directory) * A (ass directory) - if specified */ #ifdef ASS_LOC case CMP3_KEY_CHDIRASS: #endif /* ASS_LOC */ case CMP3_KEY_CHDIR: case CMP3_KEY_CHDIRHOME: if (command == CMP3_KEY_CHDIRHOME) strcpy(directory, init_dir); else if (command == CMP3_KEY_CHDIR) { char dirnamebuffer[MAX_FULL]; memset(dirnamebuffer, ' ', MAX_FULL); memcpy(dirnamebuffer, directory, strlen(directory)); if (inputbox("Change Directory?", dirnamebuffer, MAX_FULL) == 0) { dialog_clean(); break; } dialog_clean(); strcpy(directory, dirnamebuffer); } #ifdef ASS_LOC else strcpy(directory, ASS_LOC); #endif /* ASS_LOC */ pads_clean(); free_lists(); init_lists(directory, 0, 0); lastleftline = lastrightline = 0; refreshpads(); break; /**************************************************************************** * d (add directory) */ case CMP3_KEY_ADDDIR: { list_right_t* file; if ((ini_getValueBool(cmp3rc, "cmp3_options", "other_confirm", 1) == 0) || (dialogbox("Add Entire Directory?") == 1)) { ll_reset(list_right); while ((file = ll_next(list_right)) != NULL) if (!isPlaylist(file->name)) { char fullpath[MAX_FULL]; strcpy(fullpath, directory); strcat(fullpath, "/"); strcat(fullpath, file->name); pl_addentry(fullpath); } ll_next(list_right); } dialog_clean(); } break; /**************************************************************************** * D (recursively add directory) */ case CMP3_KEY_RECURADDIR: if ((ini_getValueBool(cmp3rc, "cmp3_options", "other_confirm", 1) == 0) || (dialogbox("Recurse Directory?") == 1)) { recursdir(directory, RECURS_DEPTH); } dialog_clean(); break; /**************************************************************************** * C (clear playlist) */ case CMP3_KEY_CLEARPL: if (shmptr->listlen < 2) break; if ((ini_getValueBool(cmp3rc, "cmp3_options", "other_confirm", 1) == 0) || (dialogbox("Clear Entire Playlist?") == 1)) { if (shmptr->pid) { pl_clear(); } } dialog_clean(); break; /**************************************************************************** * S (suspend mode) */ case CMP3_KEY_SUSPEND: if (!(shmptr->pid)) break; if ((ini_getValueBool(cmp3rc, "cmp3_options", "suspend_confirm", 1) == 0) || (dialogbox("Do you want to suspend?") == 1)) { enditall(1); } dialog_clean(); break; /**************************************************************************** * W (write playlist) */ case CMP3_KEY_WRITEPL: { char filenamebuffer[MAX_FULL]; if (shmptr->listlen < 2) break; memset(filenamebuffer, ' ', MAX_FULL); memcpy(filenamebuffer, DEFAULT_ASSFILE, strlen(DEFAULT_ASSFILE)); if (inputbox("Save List?", filenamebuffer, MAX_FULL) == 1) { #ifdef ASS_LOC char temp[MAX_FULL]; if (filenamebuffer[0] != '/') { strcpy(temp,ASS_LOC); strcat(temp,"/"); strcat(temp, filenamebuffer); writelist(temp); } else { writelist(filenamebuffer); } #else /* ASS_LOC */ writelist(filenamebuffer); #endif /* ASS_LOC */ } dialog_clean(); } break; /**************************************************************************** * Repeat Mode */ case CMP3_KEY_REPEAT: if (shmptr->repeat == 0) { mvprintw(LINES - 2, 3, "R"); shmptr->repeat = 1; } else { mvprintw(LINES - 2, 3, " "); shmptr->repeat = 0; } break; /**************************************************************************** * F1 (help) */ case CMP3_KEY_HELP: showhelp(); after_list(); break; /**************************************************************************** * My personal cd changing code * "disk" is a perl script that changes my cd changer, so this probably * won't do you much good. */ #ifdef MY_CD case '1': case '2': case '3': case '4': { char temp[] = "disk ! >& /dev/null"; temp[5] = command; system(temp); } break; #endif /* MY_CD */ /**************************************************************************** * Default - unpause if paused */ default: if (shmptr->pause) { kill(shmptr->pid,SIGCONT); shmptr->pause=0; } /* Helpful to find out what number for a key */ /* attron(A_BLINK); attron(A_REVERSE); mvprintw(2,COLS/3,"Hit q to quit you idiot: %d entered",command); attroff(A_BLINK); attroff(A_REVERSE); */ break; } /* switch */ } /* while */ enditall(1); return(0); } /**************************************************************************** * Spawn a manager process * Returns: nothing ****************************************************************************/ int spawn_manager() { int manapid; manapid=fork(); if (manapid == -1) { perror("Can't fork\n"); enditall(0); } if (!manapid) { manageit(); exit(0); } return(manapid); } /**************************************************************************** * Initialize shared memory segment * If shared memory segment exists already, use it.. otherwise spawn * a manager process. Shared memory stays in block pointed by shmptr * Returns: nothing ****************************************************************************/ void shm_init() { char *home; int proccheck=1; struct shmid_ds shminfo; static int initialized = 0; if (initialized != 0) return; home = getenv("HOME"); shmid = shmget(ftok(home,69), sizeof(shmdata_t), 0600 | IPC_CREAT | IPC_EXCL); /* if SOMETHING is already running (what?) */ if ((shmid == -1) && (errno == EEXIST)) { shmid=shmget(ftok(home,69), sizeof(shmdata_t), 0600 | IPC_CREAT); } else { proccheck = 0; spawn_manager(); } shmptr = (shmdata_t*) shmat(shmid,NULL,0); if (shmptr == (shmdata_t*) -1) { perror("can't attach shared memory"); enditall(69); } /* Check if any manager process is attached to it */ if (proccheck && ((shmctl(shmid, IPC_STAT, &shminfo) == 0))) { if (shminfo.shm_nattch < 2) spawn_manager(); } /* why? */ while (shmptr->managpid == 0) printf("\r"); initialized = 1; return; } /**************************************************************************** * Check command line inserts for ass files or commands * Returns: nothing ****************************************************************************/ void docmdline(int argc, char **argv) { if (!Strcmp(argv[1], "version")) { printf("Cmp3 %s - %s\n\n", CMP3_VER, CMP3_COOLLINE); printf("mpg123 located at %s\n", EXEC_LOC); printf("ogg123 located at %s\n", OGG_LOC); #ifdef ASS_LOC printf("Ass repository located at %s\n", ASS_LOC); #endif /* ASS_LOC */ enditall(69); } #ifdef ASS_LOC if (!Strcmp(argv[1],"list")) { char temp[MAX_WIDTH]; sprintf(temp,"ls %s/*.ass",ASS_LOC); system(temp); enditall(69); } #endif /* ASS_LOC */ shm_init(); if ((!Strcmp(argv[1],"skip")) || (!Strcmp(argv[1], "next"))) { if (shmptr->pid) kill(shmptr->pid,SIGKILL); enditall(69); } if (!Strcmp(argv[1],"quit")) { if (shmptr->managpid) kill(shmptr->managpid,SIGINT); enditall(69); } if (!Strcmp(argv[1],"song")) { if (shmptr->pid) { if (shmptr->pause == 1) { printf("Paused: "); } else { printf("Playing: "); } printf("%s\n", shmptr->plhead); } else { printf("No song playing\n"); } enditall(69); } if (!Strcmp(argv[1],"pause")) { if (shmptr->pid) { if (shmptr->pause) { shmptr->pause=0; kill(shmptr->pid,SIGCONT); } else { shmptr->pause=1; kill(shmptr->pid,SIGSTOP); } } enditall(69); } if (!Strcmp(argv[1], "restart")) { if (shmptr->pid) { pl_dupfirst(); kill(shmptr->pid, SIGINT); if (shmptr->repeat == 1) shmptr->listlen -= 1; } enditall(69); } if (!Strcmp(argv[1], "info")) { if (shmptr->listlen > 0) { id3info_t songinfo; if (readid3(&songinfo, shmptr->plhead) == 0) { printf("Filename: %s\n", shmptr->plhead); printf("Name: %.30s\n", songinfo.name); printf("Artist: %.30s\n", songinfo.artist); printf("Album: %.4s %.30s\n", songinfo.year, songinfo.album); printf("Comment: %.30s\n", songinfo.comment); printf("Genre: %s\n", songinfo.genre ? "Unlisted" : id3genre[(int) songinfo.genre]); } else { printf("No id3 tag information for %s\n", shmptr->plhead); } } enditall(69); } if ((!Strcmp(argv[1], "playlist")) || (!Strcmp(argv[1], "songs"))) { if (shmptr->listlen > 0) { int i; char *ptr; printf("%s -> %s\n", shmptr->pause ? "Paused " : "Playing", shmptr->plhead); ptr = shmptr->plhead + strlen(shmptr->plhead) + 1; for (i = 1; i < shmptr->listlen; i++) { printf(" %s\n", ptr); ptr += strlen(ptr) + 1; } } enditall(69); } if (!Strcmp(argv[1], "adddir")) { char directory[MAX_FULL]; if (argc > 2) chdir(argv[2]); getcwd(directory, MAX_FULL); recursdir(directory, RECURS_DEPTH); enditall(69); } if (!Strcmp(argv[1],"random")) { if (shmptr->pid) pl_randomize(1); enditall(69); } if (!Strcmp(argv[1]+(strlen(argv[1])-4),".mp3")) { if (argv[1][0] == '/') pl_addentry(argv[1]); else { char fullpath[MAX_FULL]; getcwd(fullpath, MAX_FULL); strcat(fullpath, "/"); strcat(fullpath, argv[1]); pl_addentry(fullpath); } enditall(69); } if (isPlaylist(argv[1])) { readlist(argv[1]); enditall(69); } if (argv[1][0] == '/') { if (isdir("", argv[1]) == 1) { chdir(argv[1]); noDirChange = 1; return; } } else { if (isdir(".", argv[1]) == 1) { chdir(argv[1]); noDirChange = 1; return; } } printf("Cmp3 %s - %s\n\n", CMP3_VER, CMP3_COOLLINE); printf( "Usage: cmp3 [file.ass] [directory] [pause] [skip] [info] [quit]\n" " [random] [restart] [adddir directory] [song] [playlist]\n" " [version]"); #ifdef ASS_LOC printf(" [list]"); #endif /* ASS_LOC */ printf ("\n"); if (!shmptr->pid) kill(shmptr->managpid,SIGINT); enditall(69); return; } /**************************************************************************** * Get curent line out of the info area and set thelist to point to * the list that is currently focused * Returns: pointer to curline number ****************************************************************************/ int *getcurline(void **thelist) { if (curwin == FOCUSED_LEFT) { *thelist = list_left; return( &(((info_left_t*) ll_info(list_left, NULL))->line) ); } else { *thelist = list_right; return( &(((info_right_t*) ll_info(list_right, NULL))->line) ); } } /* EOF */