source: trunk/src_apollo/org/apollo/io/AudioPathManager.java@ 355

Last change on this file since 355 was 355, checked in by bjn8, 16 years ago

Many fixes and usability improvements.

File size: 6.4 KB
Line 
1package org.apollo.io;
2
3import java.io.BufferedReader;
4import java.io.File;
5import java.io.FileReader;
6import java.io.FileWriter;
7import java.io.IOException;
8import java.io.UnsupportedEncodingException;
9import java.util.Random;
10
11import org.apollo.audio.structure.AudioStructureModel;
12import org.apollo.util.ApolloSystemLog;
13import org.apollo.util.RegExpFileFilter;
14
15/**
16 * Generates audio paths.
17 *
18 * @author Brook Novak
19 *
20 */
21public class AudioPathManager {
22
23 private AudioPathManager() {
24 // util constructor
25 }
26
27 /** Suffixed with the native file separator */
28 public static final String AUDIO_HOME_DIRECTORY = "audio" + File.separatorChar;
29 // TODO: TMP FOR WORKING IN LINUX LABS: Avoids using my quota
30 //public static final String AUDIO_HOME_DIRECTORY = "/research/bjn8/apollosaudio/";
31
32 /** Stores all virtual names created by this repository. */
33 private static final String VIRTUAL_NAME_BASEFILE = ".vnames";
34
35 public static final int PREAMBLE_LENGTH = 6;
36
37 private static long counter = 0;
38
39 private static Random rand = new Random(System.currentTimeMillis());
40
41 /**
42 * Class initializer.
43 * Ensures that the home directory(ies) exist and preps the counter
44 */
45 static {
46
47 // Ensure audio directory exists
48 File dir = new File(AUDIO_HOME_DIRECTORY);
49 if (!dir.exists()) {
50 if (!dir.mkdir()) {
51 ApolloSystemLog.println("Unable to create missing audio home directory");
52 }
53 }
54
55 // Load counter
56 loadCounter(dir);
57 }
58
59 /**
60 * Loads the counter
61 * @param dir The dir where the audio files live.
62 */
63 private static void loadCounter(File dir) {
64 String[] files = getAudioFileNames(dir);
65 if (files == null) { // Due to IO exception
66 ApolloSystemLog.printError("Failed to read audio directory");
67 return;
68 }
69 long count = 0;
70 if (files != null) {
71 for (String f : files) {
72
73 int start = -1, end = -1;
74 for (int i = 0; i < f.length(); i++) {
75 if (Character.isDigit(f.charAt(i)) && start == -1) {
76 start = i;
77 } else if (!Character.isDigit(f.charAt(i)) && start != -1) {
78 end = i;
79 break;
80 }
81 }
82
83 if (start >= 0 && end == -1) end = f.length();
84
85 if (start > 0 && end >= start) { // not start >= 0 since missing preable
86
87 String tmp = f.substring(start, end);
88 long l = Long.parseLong(tmp);
89 if (l >= count)
90 count = l + 1;
91 }
92 }
93 }
94
95 counter = count;
96 }
97
98 /**
99 * @param dir
100 * @return
101 * Null if an IO exception occurs
102 */
103 private static String[] getAudioFileNames(File dir) {
104 return dir.list(new RegExpFileFilter("^[A-Z]+\\d+.*$"));
105 }
106
107 /**
108 * @return
109 * The list of audio files in the audio home directory.
110 * Can be empty. Null if directory does not exist or failed to
111 * read list of files.
112 */
113 public static String[] getAudioFileNames() {
114 File audioDir = new File(AUDIO_HOME_DIRECTORY);
115 if (!audioDir.exists() || !audioDir.isDirectory()) return null;
116 return getAudioFileNames(audioDir);
117 }
118
119
120 /**
121 * @return The current counter.
122 */
123 public static long getCounter() {
124 return counter;
125 }
126
127 /**
128 * Generates a filename that is unique within the AUDIO_HOME_DIRECTORY.
129 *
130 * @param extension
131 * The extension of the filename to generate. Exclude period.
132 *
133 * @return
134 * A free unused filename with the given extension. Excludes directory.
135 * Even if the path return is not used, it will never be re-generated.
136 */
137 public static String generateLocateFileName(String extension) {
138
139 String filename = generateRandomFilenameBase() + "." + extension;
140
141 File f = new File(AUDIO_HOME_DIRECTORY + filename);
142
143 if (AudioStructureModel.getInstance().getTrackGraphInfo(filename, null) != null ||
144 f.exists()) { // recurse: until found a free path:
145 return generateLocateFileName(extension);
146 }
147
148 return filename;
149 }
150
151 private static String generateRandomFilenameBase() {
152
153 counter++;
154 if (counter < 0) counter = 0; // wraps positivey
155
156 // Generate random alpha preamble
157 byte[] bytes = new byte[PREAMBLE_LENGTH];
158 rand.nextBytes(bytes);
159
160
161 for (int i = 0; i < PREAMBLE_LENGTH; i++) {
162 if (bytes[i] < 0) bytes[i] *= -1;
163 int alphacap = (65 + (Math.abs(bytes[i]) % 26)); // A-Z in US ASCII encoding
164 bytes[i] = (byte) alphacap;
165
166 }
167
168 // Decode ASCII Byte array to javas UTF-16 encoding
169 String preamble = null;
170
171 try {
172 preamble = new String(bytes, "US-ASCII");
173 } catch (UnsupportedEncodingException e) {
174 e.printStackTrace();
175 preamble = "AUDIO";
176 }
177
178 // Build the filename string
179 return preamble + counter;
180
181 }
182
183
184
185 /**
186 * Lots of room for improvement here, ensures that a virtual filename is unique .. stores
187 * allocated virtual filenames on file.
188 *
189 * @return
190 * The new virtual filename.
191 */
192 public static String generateVirtualFilename() {
193
194 // Ensure that the name base file exists. Assumes the audio home directory exists.
195 File vnameBase = new File(AUDIO_HOME_DIRECTORY + VIRTUAL_NAME_BASEFILE);
196 if (!vnameBase.exists()) {
197 try {
198 vnameBase.createNewFile();
199 } catch (IOException e) {
200 e.printStackTrace();
201 }
202 }
203
204 String vname = null;
205
206 while (vname == null) {
207 vname = generateRandomFilenameBase() + ".vrt";
208 assert(vname != null);
209
210 BufferedReader in = null;
211 String line = null;
212
213 try {
214
215 // Open the vbase for reading
216 in = new BufferedReader(new FileReader(vnameBase));
217
218 // Read the sbase file and check all names
219 while ((line = in.readLine()) != null) {
220 line = line.trim();
221 if (line.equalsIgnoreCase(vname)) break;
222 }
223
224 } catch (Exception e) {
225 e.printStackTrace();
226 break; // just use the last generated filename...
227
228 // Clean up
229 } finally {
230 if (in != null) {
231 try {
232 in.close();
233 } catch (IOException e) {
234 e.printStackTrace();
235 }
236 }
237 }
238
239 // Check to see if name is infact unique
240 if (AudioStructureModel.getInstance().getLinkedTrackGraphInfo(vname, null) == null &&
241 (line == null || !line.equalsIgnoreCase(vname))) {
242 // If so, then enter new entry into the db.
243 FileWriter out = null;
244
245 try {
246 // Open the vbase for appending
247 out = new FileWriter(vnameBase, true);
248 out.write("\n" + vname);
249
250 } catch (IOException e) {
251 e.printStackTrace();
252
253 // Clean up
254 } finally {
255 if (out != null) {
256 try {
257 out.close();
258 } catch (IOException e) {
259 e.printStackTrace();
260 }
261 }
262 }
263
264 } else vname = null;
265 }
266
267 // Return the generated vname
268 return vname;
269
270 }
271}
Note: See TracBrowser for help on using the repository browser.