source: trunk/src/org/apollo/io/AudioPathManager.java@ 1434

Last change on this file since 1434 was 1434, checked in by bln4, 5 years ago

Implementation of ProfileManager. Refactor + additional content for how new profiles are created. The refactoring split out the creation of the default profile from user profiles. Refactoring revealed a long term bug that was causing user profiles to generate with incorrect information. The additional content fixed this bug by introducing the ${USER.NAME} variable, so that the default profile frameset can specify resource locations located in the users resource directory.

org.expeditee.auth.AuthenticatorBrowser
org.expeditee.auth.account.Create
org.expeditee.gui.Browser
org.expeditee.gui.management.ProfileManager
org.expeditee.setting.DirectoryListSetting
org.expeditee.setting.ListSetting
org.expeditee.settings.UserSettings

Implementation of ResourceManager as a core location to get resources from the file system. Also the additional variable ${CURRENT_FRAMESET} to represent the current frameset, so that images can be stored in the directory of the current frameset. This increases portability of framesets.

org.expeditee.gui.FrameIO
org.expeditee.gui.management.ResourceManager
org.expeditee.gui.management.ResourceUtil
Audio:

#NB: Audio used to only operate on a single directory. This has been updated to work in a same way as images. That is: when you ask for a specific resouce, it looks to the user settings to find a sequence of directories to look at in order until it manages to find the desired resource.


There is still need however for a single(ish) source of truth for the .banks and .mastermix file. Therefore these files are now always located in resource-<username>\audio.
org.apollo.agents.MelodySearch
org.apollo.audio.structure.AudioStructureModel
org.apollo.audio.util.MultiTrackPlaybackController
org.apollo.audio.util.SoundDesk
org.apollo.gui.FrameLayoutDaemon
org.apollo.io.AudioPathManager
org.apollo.util.AudioPurger
org.apollo.widgets.FramePlayer
org.apollo.widgets.SampledTrack

Images:

org.expeditee.items.ItemUtils

Frames:

org.expeditee.gui.FrameIO

Fixed a error in the FramePlayer class caused by an incorrect use of toArray().

org.apollo.widgets.FramePlayer


Added several short cut keys to allow for the Play/Pause (Ctrl + P), mute (Ctrl + M) and volume up/down (Ctrl + +/-) when hovering over SampledTrack widgets.

org.apollo.widgets.SampledTrack


Changed the way that Authenticate.login parses the new users profile to be more consistance with other similar places in code.

org.expeditee.auth.account.Authenticate


Encapsulated _body, _surrogateItemsBody and _primaryItemsBody in Frame class. Also changed getBody function to take a boolean flag as to if it should respect the current surrogate mode. If it should then it makes sure that labels have not changed since last time getBody was called.

org.expeditee.gui.Frame

File size: 6.8 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.ArrayList;
10import java.util.List;
11import java.util.Random;
12import java.util.function.Predicate;
13
14import org.apollo.audio.structure.AudioStructureModel;
15import org.apollo.util.ApolloSystemLog;
16import org.apollo.util.RegExpFileFilter;
17import org.expeditee.gui.DisplayController;
18import org.expeditee.gui.FrameIO;
19import org.expeditee.gui.management.ResourceManager;
20import org.expeditee.settings.UserSettings;
21
22/**
23 * Generates audio paths.
24 *
25 * @author Brook Novak
26 *
27 */
28public class AudioPathManager {
29
30 private AudioPathManager() {
31 // util constructor
32 }
33
34 /** Suffixed with the native file separator */
35 public static String AUDIO_USERNAME_HOME_DIRECTORY = null;
36
37 /** Stores all virtual names created by this repository. */
38 private static final String VIRTUAL_NAME_BASEFILE = ".vnames";
39
40 public static final int PREAMBLE_LENGTH = 6;
41
42 private static long counter = 0;
43
44 private static Random rand = new Random(System.currentTimeMillis());
45
46 // TODO: this function called during startup? In browser construction? When FrameIO.changeParentAndSubFolders() is called? Separation of apollo from expeditee core?
47 public static void activateAndScanAudioDirs() {
48 // If we are in old regime then there is no AUDIO_USERNAME_PRIVATE_PATH.
49 AUDIO_USERNAME_HOME_DIRECTORY = FrameIO.AUDIO_USERNAME_PRIVATE_PATH == null ? FrameIO.AUDIO_PATH : FrameIO.AUDIO_USERNAME_PRIVATE_PATH;
50
51 // Load counter
52 loadCounter();
53 }
54
55 /**
56 * Loads the counter
57 */
58 private static void loadCounter() {
59 List<String> audioFileNames = getAudioFileNames();
60
61 long count = 0;
62 for (String f : audioFileNames) {
63
64 int start = -1, end = -1;
65 for (int i = 0; i < f.length(); i++) {
66 if (Character.isDigit(f.charAt(i)) && start == -1) {
67 start = i;
68 } else if (!Character.isDigit(f.charAt(i)) && start != -1) {
69 end = i;
70 break;
71 }
72 }
73
74 if (start >= 0 && end == -1) {
75 end = f.length();
76 }
77
78 if (start > 0 && end >= start) { // not start >= 0 since missing preable
79
80 String tmp = f.substring(start, end);
81 long l = Long.parseLong(tmp);
82 if (l >= count)
83 count = l + 1;
84 }
85 }
86 counter = count;
87 }
88
89 /**
90 * @return
91 * The list of audio files in the audio home directory.
92 * Can be empty. Null if directory does not exist or failed to
93 * read list of files.
94 */
95 public static List<String> getAudioFileNames() {
96 Predicate<File> isFile = file -> {
97 File dirForFile = file.toPath().getParent().toFile();
98 if (!dirForFile.exists()) {
99 if (!dirForFile.mkdir()) {
100 ApolloSystemLog.println("Unable to create missing audio directory: " + dirForFile.toString());
101 }
102 }
103 if (file.isFile()) {
104 return true;
105 }
106 return false;
107 };
108 List<File> allFilesInAudioDirectories = ResourceManager.gatherAudioResources(isFile, DisplayController.getCurrentFrame());
109 List<String> audioFileNames = new ArrayList<String>();
110 RegExpFileFilter regExpFileFilter = new RegExpFileFilter("^[A-Z]+\\d+.*$");
111 for (File file: allFilesInAudioDirectories) {
112 if (regExpFileFilter.accept(file, file.getAbsolutePath())) {
113 audioFileNames.add(file.getName());
114 }
115 }
116 return audioFileNames;
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_USERNAME_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 UserSettings.UserName.get() + 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_USERNAME_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.