302 lines
6.4 KiB
C
302 lines
6.4 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<74>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);
|
|||
|
fprintf(stderr, "%s %s %d\n", __func__, de->d_name, devine);
|
|||
|
|
|||
|
/* 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<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; /* ??? */
|
|||
|
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;
|
|||
|
}
|
|||
|
/*==------------------------------------------------------------------==*/
|