1 /*
2  * Schism Tracker - a cross-platform Impulse Tracker clone
3  * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4  * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5  * copyright (c) 2009 Storlek & Mrs. Brisby
6  * copyright (c) 2010-2012 Storlek
7  * URL: http://schismtracker.org/
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #ifndef DMOZ_H
25 #define DMOZ_H
26 
27 #include <stdint.h>
28 #include "sndfile.h" /* for song_sample_t */
29 
30 /* need these for struct stat */
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 
34 enum {
35 	TYPE_BROWSABLE_MASK   = 0x1, /* if (type & TYPE_BROWSABLE_MASK) it's readable as a library */
36 	TYPE_FILE_MASK        = 0x2, /* if (type & TYPE_FILE_MASK) it's a regular file */
37 	TYPE_DIRECTORY        = 0x4 | TYPE_BROWSABLE_MASK, /* if (type == TYPE_DIRECTORY) ... guess what! */
38 	TYPE_NON_REGULAR      = 0x8, /* if (type == TYPE_NON_REGULAR) it's something weird, e.g. a socket */
39 
40 	/* (flags & 0xF0) are reserved for future use */
41 
42 	/* this has to match TYPE_BROWSABLE_MASK for directories */
43 	TYPE_EXT_DATA_MASK    = 0xFFF01, /* if (type & TYPE_EXT_DATA_MASK) the extended data has been checked */
44 
45 	TYPE_MODULE_MASK      = 0xF00, /* if (type & TYPE_MODULE_MASK) it's loadable as a module */
46 	TYPE_MODULE_MOD       = 0x100 | TYPE_BROWSABLE_MASK | TYPE_FILE_MASK,
47 	TYPE_MODULE_S3M       = 0x200 | TYPE_BROWSABLE_MASK | TYPE_FILE_MASK,
48 	TYPE_MODULE_XM        = 0x300 | TYPE_BROWSABLE_MASK | TYPE_FILE_MASK,
49 	TYPE_MODULE_IT        = 0x400 | TYPE_BROWSABLE_MASK | TYPE_FILE_MASK,
50 
51 	TYPE_INST_MASK        = 0xF000, /* if (type & TYPE_INST_MASK) it's loadable as an instrument */
52 	TYPE_INST_ITI         = 0x1000 | TYPE_FILE_MASK, /* .iti (native) instrument */
53 	TYPE_INST_XI          = 0x2000 | TYPE_FILE_MASK, /* fast tracker .xi */
54 	TYPE_INST_OTHER       = 0x3000 | TYPE_FILE_MASK, /* gus patch, soundfont, ...? */
55 
56 	TYPE_SAMPLE_MASK      = 0xF0000, /* if (type & TYPE_SAMPLE_MASK) it's loadable as a sample */
57 	TYPE_UNKNOWN          = 0x10000 | TYPE_FILE_MASK, /* any unrecognized file, loaded as raw pcm data */
58 	TYPE_SAMPLE_PLAIN     = 0x20000 | TYPE_FILE_MASK, /* au, aiff, wav (simple formats) */
59 	TYPE_SAMPLE_EXTD      = 0x30000 | TYPE_FILE_MASK, /* its, s3i (tracker formats with extended stuff) */
60 	TYPE_SAMPLE_COMPR     = 0x40000 | TYPE_FILE_MASK, /* ogg, mp3 (compressed audio) */
61 
62 	TYPE_INTERNAL_FLAGS   = 0xF00000,
63 	TYPE_HIDDEN           = 0x100000,
64 };
65 
66 /* A brief description of the sort_order field:
67 
68 When sorting the lists, items with a lower sort_order are given higher placement, and ones with a
69 higher sort order are placed toward the bottom. Items with equal sort_order are sorted by their
70 basename (using strverscmp).
71 
72 Defined sort orders:
73 	-1024 ... 0     System directories, mount points, volumes, etc.
74 	-10             Parent directory
75 	0               Subdirectories of the current directory
76 	>= 1            Files. Only 1 is used for the "normal" list, but this is incremented for each sample
77 			when loading libraries to keep them in the correct order.
78 			Higher indices might be useful for moving unrecognized file types, backups, #autosave#
79 			files, etc. to the bottom of the list (rather than omitting these files entirely). */
80 
81 typedef struct dmoz_file dmoz_file_t;
82 struct dmoz_file {
83 	char *path; /* the full path to the file (needs free'd) */
84 	char *base; /* the basename (needs free'd) */
85 	int sort_order; /* where to sort it */
86 
87 	unsigned long type; /* combination of TYPE_* flags above */
88 
89 	/*struct stat stat;*/
90 	time_t timestamp; /* stat.st_mtime */
91 	size_t filesize; /* stat.st_size */
92 
93 	/* if ((type & TYPE_EXT_DATA_MASK) == 0) nothing below this point will
94 	be defined (call dmoz_{fill,filter}_ext_data to define it) */
95 
96 	const char *description; /* i.e. "Impulse Tracker sample" -- does NOT need free'd */
97 	char *artist; /* needs free'd (may be -- and usually is -- NULL) */
98 	char *title; /* needs free'd */
99 
100 	/* This will usually be NULL; it is only set when browsing samples within a library, or if
101 	a sample was played from within the sample browser. */
102 	song_sample_t *sample;
103 	int sampsize; /* number of samples (for instruments) */
104 	int instnum;
105 
106 	/* loader MAY fill this stuff in */
107 	char *smp_filename;
108 	unsigned int smp_speed;
109 	unsigned int smp_loop_start;
110 	unsigned int smp_loop_end;
111 	unsigned int smp_sustain_start;
112 	unsigned int smp_sustain_end;
113 	unsigned int smp_length;
114 	unsigned int smp_flags;
115 
116 	unsigned int smp_defvol;
117 	unsigned int smp_gblvol;
118 	unsigned int smp_vibrato_speed;
119 	unsigned int smp_vibrato_depth;
120 	unsigned int smp_vibrato_rate;
121 };
122 
123 typedef struct dmoz_dir {
124 	char *path; /* full path (needs free'd) */
125 	char *base; /* basename of the directory (needs free'd) */
126 	int sort_order; /* where to sort it */
127 } dmoz_dir_t;
128 
129 typedef struct dmoz_filelist {
130 	int num_files, alloc_size;
131 	dmoz_file_t **files;
132 
133 	int selected; /* communication with cache */
134 } dmoz_filelist_t;
135 
136 typedef struct dmoz_dirlist {
137 	int num_dirs, alloc_size;
138 	dmoz_dir_t **dirs;
139 
140 	int selected; /* communication with cache */
141 } dmoz_dirlist_t;
142 
143 /* For any of these, pass NULL for dirs to handle directories and files in the same list.
144 for load_library, provide one of the dmoz_read_whatever_library functions, or NULL. */
145 int dmoz_read(const char *path, dmoz_filelist_t *files, dmoz_dirlist_t *dirs,
146 	int (*load_library)(const char *,dmoz_filelist_t *,dmoz_dirlist_t *));
147 void dmoz_free(dmoz_filelist_t *files, dmoz_dirlist_t *dirs);
148 
149 void dmoz_sort(dmoz_filelist_t *flist, dmoz_dirlist_t *dlist);
150 
151 /* this function is in audio_loadsave.cc instead of dmoz.c, because of modplugness */
152 int dmoz_read_sample_library(const char *path, dmoz_filelist_t *flist, dmoz_dirlist_t *dlist);
153 int dmoz_read_instrument_library(const char *path, dmoz_filelist_t *flist, dmoz_dirlist_t *dlist);
154 
155 /* if ((file->type & TYPE_EXT_DATA_MASK) == 0), call this function to get the title and description */
156 int dmoz_filter_ext_data(dmoz_file_t *file);
157 
158 /* same as dmoz_filter_ext_data, but always returns 1 (for async title reading) */
159 int dmoz_fill_ext_data(dmoz_file_t *file);
160 
161 /* filters stuff based on... whatever you like :) */
162 void dmoz_filter_filelist(dmoz_filelist_t *flist, int (*grep)(dmoz_file_t *f), int *pointer, void (*onmove)(void));
163 
164 /* butt */
165 int song_preload_sample(dmoz_file_t *f);
166 
167 
168 /* Path handling functions */
169 
170 /* Normalize a path (remove /../ and stuff, condense multiple slashes, etc.)
171 this will return NULL if the path could not be normalized (not well-formed?).
172 the returned string must be free()'d. */
173 char *dmoz_path_normal(const char *path);
174 
175 /* Return nonzero if the path is an absolute path (e.g. /bin, c:\progra~1, sd:/apps, etc.) */
176 int dmoz_path_is_absolute(const char *path);
177 
178 /* Concatenate two paths, adding separators between them as necessary. The returned string must be free()'d.
179 The second version can be used if the string lengths are already known to avoid redundant strlen() calls.
180 Additionally, if 'b' is an absolute path (as determined by dmoz_path_is_absolute), ignore 'a' and return a
181 copy of 'b'. */
182 char *dmoz_path_concat(const char *a, const char *b);
183 char *dmoz_path_concat_len(const char *a, const char *b, int alen, int blen);
184 
185 
186 /* Adding files and directories
187 For all of these, path and base should be free()-able. */
188 
189 /* If st == NULL, it is assumed to be a directory, and the timestamp/filesize fields are set to zero.
190 This way, it's possible to add platform directories ("/", "C:\", whatever) without having to call stat first.
191 The return value is the newly created file struct. */
192 dmoz_file_t *dmoz_add_file(dmoz_filelist_t *flist, char *path, char *base, struct stat *st, int sort_order);
193 
194 /* The return value is the newly created dir struct. */
195 dmoz_dir_t *dmoz_add_dir(dmoz_dirlist_t *dlist, char *path, char *base, int sort_order);
196 
197 /* Add a directory to either the dir list (if dlist != NULL) or the file list otherwise. This is basically a
198 convenient shortcut for adding a directory. */
199 void dmoz_add_file_or_dir(dmoz_filelist_t *flist, dmoz_dirlist_t *dlist,
200 			  char *path, char *base, struct stat *st, int sort_order);
201 
202 /* this is called by main to actually do some dmoz work. returns 0 if there is no dmoz work to do...
203 */
204 int dmoz_worker(void);
205 
206 /* these update the file selection cache for the various pages */
207 void dmoz_cache_update_names(const char *path, const char *filen, const char *dirn);
208 void dmoz_cache_update(const char *path, dmoz_filelist_t *fl, dmoz_dirlist_t *dl);
209 void dmoz_cache_lookup(const char *path, dmoz_filelist_t *fl, dmoz_dirlist_t *dl);
210 
211 #endif /* ! DMOZ_H */
212