/* * fileselector.c * -------------- 18 Fevrier 2005. * * some code borrowed from 'Visual Hexdiff' :-) */ #include #include #include #include #include #include #include #include "ecoute.h" extern char *strdup(const char *); /* WTF? */ /*==------------------------------------------------------------------==*/ typedef struct { long smplrate; short channels; short type; } FICH_SON; typedef struct { long taille; char *nom; int idx; time_t epochtime; FICH_SON son; } FICH; static FICH *liste; static int taille; /* taille de la liste */ static int nombre; /* nbre d'entrées dans la liste */ #define TCHONK 42 /*==------------------------------------------------------------------==*/ /* * return 1 if we can safely read the file */ int teste_fichier(char *nom, struct stat *stb, int flag) { int foo; foo = stat(nom, stb); if (foo) { fprintf(stderr, "in %s stat -> %d\n", __func__, errno); } if (S_ISDIR(stb->st_mode)) return 0; /* XXX * check if the file is readable */ return 1; } /*==------------------------------------------------------------------==*/ /* * dedicated comparaison functions for sorting in the file selector. * */ static int cmp_name_asc(const void *a, const void *b) { return strcmp( ((FICH *)a)->nom, ((FICH *)b)->nom); } static int cmp_name_dsc(const void *a, const void *b) { return strcmp( ((FICH *)b)->nom, ((FICH *)a)->nom); } static int cmp_idx_asc(const void *a, const void *b) { return ((FICH *)a)->idx - ((FICH *)b)->idx; } static int cmp_idx_dsc(const void *a, const void *b) { return ((FICH *)b)->idx - ((FICH *)a)->idx; } static int cmp_size_asc(const void *a, const void *b) { return ((FICH *)a)->taille - ((FICH *)b)->taille; } static int cmp_size_dsc(const void *a, const void *b) { return ((FICH *)b)->taille - ((FICH *)a)->taille; } /* and sorting by date ? */ /*==------------------------------------------------------------------==*/ int trier_la_liste(int mode) { #if DEBUG_LEVEL fprintf(stderr, "tri de la liste, mode=%d\n", mode); #endif switch(mode) { case 1: qsort(liste, nombre, sizeof(FICH), cmp_name_asc); break; case 2: qsort(liste, nombre, sizeof(FICH), cmp_name_dsc); break; case 3: qsort(liste, nombre, sizeof(FICH), cmp_size_asc); break; case 4: qsort(liste, nombre, sizeof(FICH), cmp_size_dsc); break; case 10: qsort(liste, nombre, sizeof(FICH), cmp_idx_asc); break; case 11: qsort(liste, nombre, sizeof(FICH), cmp_idx_dsc); break; } return -1; } /*==------------------------------------------------------------------==*/ int faire_la_liste(void) { DIR *dir; struct dirent *de; struct stat statbuf; int foo, type; int devine; long magicbits; if ( NULL == (liste = malloc(TCHONK*sizeof(FICH))) ) { fprintf(stderr, "\nno memory in file-listing\n"); abort(); } dir = opendir("."); if (dir == NULL) { abort(); } /* XXX hard failure */ nombre = 0; while ( (de=readdir(dir)) != NULL) { #if DEBUG_LEVEL #endif if ( ! teste_fichier(de->d_name, &statbuf, 0) ) { continue; } type = type_du_fichier(de->d_name); if (type < 0) { continue; } /* use the magic system (new 13 mai, may be bugged) */ devine = magic_detect(de->d_name, &magicbits); #if DEBUG_LEVEL fprintf(stderr, "%s %s %d\n", __func__, de->d_name, devine); #endif /* strdup is a 'non-portable' function ? */ liste[nombre].nom = strdup(de->d_name); liste[nombre].taille = statbuf.st_size; liste[nombre].idx = nombre; liste[nombre].son.type = type; liste[nombre].epochtime = 15000; #if DEBUG_LEVEL > 1 fprintf(stderr, "%4d: %-20s %8ld %4d\n", nombre, liste[nombre].nom, liste[nombre].taille, type); #endif nombre++; /* if needed, increase the size of the list */ if (nombre >= taille) { liste = realloc(liste, sizeof(FICH)*(taille+TCHONK)); taille += TCHONK; } } foo = closedir(dir); return nombre; /* ??? */ } /*==------------------------------------------------------------------==*/ int print_entry(WINDOW *w, int number, int line) { int ln; ln = strlen(liste[number].nom); mvwprintw(w, line, 2, "%3d %-40s %9d ", liste[number].idx, liste[number].nom, liste[number].taille); return 0; } /*==------------------------------------------------------------------==*/ int fileselector(void) { int foo; WINDOW *wfs; int first, curseur, idx, affh; int key, flag_exit; char chaine[100]; #if DEBUG_LEVEL fprintf(stderr, ">>> %s ( )\n", __func__); #endif foo = faire_la_liste(); affh = LINES-7; /* * create a subwindow for list of files */ wfs = derwin(stdscr, affh, COLS-2, 2, 1); #if DEBUG_LEVEL > 1 bordure(wfs, 0); #endif wrefresh(wfs); first = curseur = 0; flag_exit = 0; #if DEBUG_LEVEL fprintf(stderr, " %s enter interactive\n", __func__); #endif do { #if DEBUG_LEVEL > 1 sprintf(chaine, "nombre:%3d first:%3d curseur:%3d", nombre, first, curseur); mvwaddstr(wfs, 0, 50, chaine); #endif for (foo=0; foo= nombre) break; if (curseur==foo) wstandout(wfs); /* * display the entry, need more work :( */ print_entry(wfs, idx, foo); if (curseur==foo) wstandend(wfs); } wrefresh(wfs); key = getch(); /* * ici il faudrait effacer le curseur ? */ switch (key) { case KEY_UP: if (curseur) curseur--; else if (first>0) first--; break; case KEY_DOWN: if ((curseur+first) >= (nombre-1)) break; if (curseur < affh-1) curseur++; else if (first<(nombre-affh)) first++; break; case KEY_HOME: curseur = first = 0; break; /* the show must go on */ case '\r': case 'p': idx = curseur+first; /* ??? */ play_this_file(liste[idx].nom, liste[idx].son.type, 0); break; case 'D': case 'd': idx = curseur+first; /* ??? FIXME */ dump_this_file(liste[idx].nom, 0); break; case 'I': case 'i': idx = curseur+first; /* ??? FIXME */ info_about_this_file(liste[idx].nom, liste[idx].son.type); break; case 'A': case 'a': about(); break; case 'H': case 'h': case '?': help(); break; case 'n': trier_la_liste(1); break; case 'N': trier_la_liste(2); break; case 's': trier_la_liste(3); break; case 'S': trier_la_liste(4); break; case 'u': trier_la_liste(10); break; case 'U': trier_la_liste(11); break; case '$': infos_driver_son(); break; case 'Q': case 'q': flag_exit = 1; break; } } while ( ! flag_exit ); #if DEBUG_LEVEL fprintf(stderr, " %s exit interactive\n", __func__); #endif return -1; } /*==------------------------------------------------------------------==*/