KlugyTools/Ecoute/src/interactive.c

304 lines
6.7 KiB
C

/*
* fileselector.c
* -------------- 18 Fevrier 2005.
*
* some code borrowed from 'Visual Hexdiff' :-)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#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;
if (flag) {
fprintf(stderr, "in %s, flag must be 0, was %d\n", __func__, flag);
}
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 ( ! 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 %-50s %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();
if (0 == foo) {
/* XXX ERROR MESSAGE AND QUIT ? */
}
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<affh; foo++) {
idx = foo+first;
if (idx >= 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; /* ??? */
foo = play_this_file(liste[idx].nom, liste[idx].son.type, 0);
#if DEBUG_LEVEL
fprintf(stderr, "play '%s' => %d\n",liste[idx].nom, foo);
#endif
break;
case 'D': case 'd':
idx = curseur+first;
/* second parameter is ignored */
dump_this_file(liste[idx].nom, 0);
break;
case 'I': case 'i':
idx = curseur+first;
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_techniques(); break;
case 'Q':
flag_exit = 1;
break;
}
} while ( ! flag_exit );
#if DEBUG_LEVEL
fprintf(stderr, " %s exit interactive\n", __func__);
#endif
return -1;
}
/*==------------------------------------------------------------------==*/