diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..99a62ac --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,24 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Java CI with Maven + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 21 + uses: actions/setup-java@v1 + with: + java-version: 21 + - name: Build with Maven + run: mvn -B package --file MpcMaid/pom.xml diff --git a/.github/workflows/mavenpublish.yml b/.github/workflows/mavenpublish.yml new file mode 100644 index 0000000..a9b7844 --- /dev/null +++ b/.github/workflows/mavenpublish.yml @@ -0,0 +1,17 @@ +name: Publish package to GitHub Packages +on: + release: + types: [created] +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 21 + uses: actions/setup-java@v1 + with: + java-version: 21 + - name: Publish package + run: mvn -B deploy --file MpcMaid/pom.xml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3685562 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target +.settings \ No newline at end of file diff --git a/MpcMaid/FileAndTextTransferHandler.java b/MpcMaid/FileAndTextTransferHandler.java index c849e9a..8d5e7b7 100755 --- a/MpcMaid/FileAndTextTransferHandler.java +++ b/MpcMaid/FileAndTextTransferHandler.java @@ -1,4 +1,4 @@ -/** + /** * @See http://www.davidgrant.ca/drag_drop_from_linux_kde_gnome_file_managers_konqueror_nautilus_to_java_applications * * @See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4899516 @@ -21,7 +21,7 @@ public FileAndTextTransferHandler() { try { uriListFlavor = new DataFlavor(URI_LIST_MIME_TYPE); } catch (ClassNotFoundException e) { - e.printStackTrace(); + logger.log(Level.ERROR, e, e::getMessage); } } @@ -33,7 +33,7 @@ public FileAndTextTransferHandler(Utilisateur u) { try { uriListFlavor = new DataFlavor(URI_LIST_MIME_TYPE); } catch (ClassNotFoundException e) { - e.printStackTrace(); + logger.log(Level.ERROR, e, e::getMessage); } this.user = u; @@ -71,14 +71,14 @@ public boolean importData(JComponent c, Transferable t) { String str = ((String) t.getTransferData(stringFlavor)); - System.out.println(str); + logger.log(Level.INFO, str); return true; } } catch (UnsupportedFlavorException ufe) { - System.out.println("importData: unsupported data flavor"); + logger.log(Level.ERROR, "importData: unsupported data flavor", ufe); } catch (IOException ieo) { - System.out.println("importData: I/O exception"); + logger.log(Level.ERROR, "importData: I/O exception", ieo); } return false; } @@ -140,9 +140,9 @@ private static List textURIListToFileList(String data) { File file = new File(uri); list.add(file); } catch (URISyntaxException e) { - e.printStackTrace(); + logger.log(Level.ERROR, e, e::getMessage); } catch (IllegalArgumentException e) { - e.printStackTrace(); + logger.log(Level.ERROR, e, e::getMessage); } } return list; diff --git a/MpcMaid/README.txt b/MpcMaid/README.txt index 29ecd33..90b3063 100755 --- a/MpcMaid/README.txt +++ b/MpcMaid/README.txt @@ -12,7 +12,7 @@ Basic Operations: Advanced Features: Slicing tool: Drag and drop your loop file (no longer than 2 bars) to have it chopped into slices based on a beat detection mechanism. Then directly export the chopped slices as multiple .WAV files, one corresponding .PGM program file and one MIDI groove .MID file. Multisample Creation: On drag and drop of .wav files with a consistent naming (that includes the note name, e-g "C#3", "E5" or "D 4"), you can automatically create Multisample program: MPC Maid calculates the allocation of the samples across pads and the tuning of each pad to reconstitute a complete chromatic scale. - Batch Create Program: Automatically creates a program (.pgm) that lists every .wav sample in each directory and sub-directory, recursively from a given base directory. This allows for instant conversion of any .wav sound library into an MPC-readable library. + Batch Create Program: Automatically creates a program (.pgm) that lists every .wav sample in each directory and subdirectory, recursively from a given base directory. This allows for instant conversion of any .wav sound library into an MPC-readable library. Copy Settings to All Pads: You want to quickly change parameters for every pad? Set your parameters on one pad, then copy them to every other pad, except of course the sample name, tuning and midi note. diff --git a/MpcMaid/TestDragDropLinux.java b/MpcMaid/TestDragDropLinux.java index e7895b7..6e4542a 100755 --- a/MpcMaid/TestDragDropLinux.java +++ b/MpcMaid/TestDragDropLinux.java @@ -37,9 +37,9 @@ private static List textURIListToFileList(String data) { File file = new File(uri); list.add(file); } catch (URISyntaxException e) { - e.printStackTrace(); + logger.log(Level.ERROR, e, e::getMessage); } catch (IllegalArgumentException e) { - e.printStackTrace(); + logger.log(Level.ERROR, e, e::getMessage); } } return list; @@ -78,7 +78,7 @@ public void drop(DropTargetDropEvent event) { try { uriListFlavor = new DataFlavor(URI_LIST_MIME_TYPE); } catch (ClassNotFoundException e) { - e.printStackTrace(); + logger.log(Level.ERROR, e, e::getMessage); } try { @@ -88,17 +88,17 @@ public void drop(DropTargetDropEvent event) { for (Object o : data) { model.addElement(o); } - System.out.println(data); + logger.log(Level.INFO, data); } else if (transferable.isDataFlavorSupported(uriListFlavor)) { String data = (String) transferable.getTransferData(uriListFlavor); List files = textURIListToFileList(data); for (Object o : files) { model.addElement(o); } - System.out.println(files); + logger.log(Level.INFO, files); } } catch (Exception e) { - e.printStackTrace(); + logger.log(Level.ERROR, e, e::getMessage); } setModel(model); diff --git a/MpcMaid/changelog.txt b/MpcMaid/changelog.txt index 39ba2cb..58c0bb6 100755 --- a/MpcMaid/changelog.txt +++ b/MpcMaid/changelog.txt @@ -1,4 +1,4 @@ -Tested on windows +Tested on Microsoft Windows Automatic assign of samples to pads/sample layers Improved validation (focus + beep) Added preferences (MPC500/1000, audition mode) @@ -7,12 +7,12 @@ Replaced audio player with a more stable one (sometime crashes when heavily stim Added automated support for multisamples Fixed frame height difference between first window and other windows Added Edit/Remove all samples -Renamed Options to Preferences for non Mac OS platforms +Renamed Options to Preferences for non macOS platforms Added splash screen and about dialog Fixed bug one file name on export slices pgm Fixed tuning reading error Added protection for multisamples notes that are out of pads range (below B0 or above D6); samples with no note in their name, or outside of this range are not imported -Added Batch Create Program feature, to create default listing programs in each directory and sub-directory from a given base directory. +Added Batch Create Program feature, to create default listing programs in each directory and subdirectory from a given base directory. Listing program created by Batch Create Program now have a name based on the directory name, shortened to 14 chars plus the page number in case we need more than 1 page to store every sample. Fixed bug in set sample name (programmatically write) Fixed bug on Export: files longer than 16 chars with the extensions were shortened incorrectly, hence would not be played by the program diff --git a/MpcMaid/mpcmaid_beta.jar b/MpcMaid/mpcmaid_beta.jar deleted file mode 100755 index a23d355..0000000 Binary files a/MpcMaid/mpcmaid_beta.jar and /dev/null differ diff --git a/MpcMaid/pom.xml b/MpcMaid/pom.xml new file mode 100644 index 0000000..8d2f94a --- /dev/null +++ b/MpcMaid/pom.xml @@ -0,0 +1,185 @@ + + 4.0.0 + com.mpcmaid + mpcmaid + 1.0-RC1 + + 21 + 21 + UTF-8 + + + + github + GitHub Packages + https://maven.pkg.github.com/malkav30/mpcmaid + + + + + junit + junit + 4.12 + test + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.0.0 + + + com.puppycrawl.tools + checkstyle + 8.10 + + + com.github.ngeor + checkstyle-rules + 1.1.0 + + + + com/github/ngeor/checkstyle.xml + true + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + + + org.jacoco + jacoco-maven-plugin + 0.8.1 + + + maven-assembly-plugin + + + package + + single + + + + + false + + jar-with-dependencies + + + + com.mpcmaid.MPCMaid + + + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.0 + + + org.apache.maven.plugins + maven-checkstyle-plugin + + com/github/ngeor/checkstyle.xml + true + + + + + + + + + jacoco + + + env.TRAVIS + + + + + + org.jacoco + jacoco-maven-plugin + + + prepare-agent + validate + + prepare-agent + + + + report + test + + report + + + + + + + + + + + travis + + + env.TRAVIS + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + checkstyle + test + + check + + + + + + org.eluder.coveralls + coveralls-maven-plugin + 4.3.0 + + + + + + diff --git a/MpcMaid/src/com/mpcmaid/audio/LocationRange.java b/MpcMaid/src/com/mpcmaid/audio/LocationRange.java deleted file mode 100755 index 414a244..0000000 --- a/MpcMaid/src/com/mpcmaid/audio/LocationRange.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.mpcmaid.audio; - -/** - * Represents a location range - * - * @author cyrille martraire - */ -public final class LocationRange { - - private final int from; - - private final int to; - - public LocationRange(int from, int to) { - this.from = from; - this.to = to; - } - - public int getFrom() { - return from; - } - - public int getTo() { - return to; - } - - public int getMidLocation() { - return (from + to) / 2; - } - - public String toString() { - return "LocationRange [" + from + " - " + to + "]"; - } - -} diff --git a/MpcMaid/src/com/mpcmaid/gui/Utils.java b/MpcMaid/src/com/mpcmaid/gui/Utils.java deleted file mode 100755 index a64cc25..0000000 --- a/MpcMaid/src/com/mpcmaid/gui/Utils.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.mpcmaid.gui; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public class Utils { - - public static final String EXTENSION = ".WAV"; - - /** - * @return true if the given file has the expected extension - */ - public final static boolean hasCorrectExtension(File file) { - return file.getName().toUpperCase().endsWith(EXTENSION); - } - - public static String noExtension(File file) { - return noExtension(file.getName()); - } - - /** - * @return The given name without its extension (the term after the last - * dot) - */ - public static String noExtension(final String name) { - String s = name; - final int indexOf = s.lastIndexOf('.'); - if (indexOf != -1) { - return s.substring(0, indexOf); - } - return s; - } - - /** - * Shorten the name if it is too long, then ensure its unicity thanks to a - * postfix incremental number - */ - public static String escapeName(final String name, final int length, final boolean brutal, final int renameCount) { - String escaped = escapeName(name, length, brutal); - if (renameCount != -1 && !escaped.equals(name)) { - if (renameCount > 0) { - final String postfix = String.valueOf(renameCount); - if (escaped.length() + postfix.length() <= length) { - escaped = escaped + postfix; - } else { - escaped = escaped.substring(0, length - postfix.length()) + postfix; - } - } - } - return escaped; - } - - /** - * Shorten the name if it is too long, either brutally, or with some trim so - * that it does not end on a space, underscore or dot - */ - public static String escapeName(final String name, final int length, final boolean brutal) { - String s = name; - if (s.length() <= length) { - return s; - } - s = s.substring(0, length).trim(); - if (brutal) { - return s; - } - String s2 = null; - while (true) { - s2 = escapeEnding(s); - if (s == s2) { - return s.trim(); - } - s = s2; - } - } - - private final static String escapeEnding(String s) { - if (s.endsWith(".")) { - return s.substring(0, s.length() - 1); - } - if (s.endsWith(" ")) { - return s.substring(0, s.length() - 1); - } - if (s.endsWith("_")) { - return s.substring(0, s.length() - 1); - } - return s; - } - - // File utils - public final static void copy(File src, File dst) throws IOException { - InputStream in = new FileInputStream(src); - OutputStream out = new FileOutputStream(dst); - - // Transfer bytes from in to out - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - in.close(); - out.close(); - } - - public String toString() { - return "Utils: "; - } -} diff --git a/MpcMaid/src/com/mpcmaid/pgm/Buffer.java b/MpcMaid/src/com/mpcmaid/pgm/Buffer.java deleted file mode 100755 index 597012c..0000000 --- a/MpcMaid/src/com/mpcmaid/pgm/Buffer.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.mpcmaid.pgm; - -public interface Buffer { - - public abstract String getString(final int offset); - - public abstract void setString(final int offset, String string); - - public abstract short getShort(final int index); - - public abstract void setShort(final int index, final short value); - - public abstract byte getByte(final int index); - - public abstract void setByte(final int index, final int value); - - public abstract Range getRange(final int index); - - public abstract void setRange(final int index, final Range value); - -} \ No newline at end of file diff --git a/MpcMaid/src/com/mpcmaid/pgm/MultisampleBuilder.java b/MpcMaid/src/com/mpcmaid/pgm/MultisampleBuilder.java deleted file mode 100755 index 63ca5ba..0000000 --- a/MpcMaid/src/com/mpcmaid/pgm/MultisampleBuilder.java +++ /dev/null @@ -1,280 +0,0 @@ -package com.mpcmaid.pgm; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -/** - * Finds out a configuration of a multisample program from a mere set of sample - * files names. - * - * Uses the sample filenames to guess their pitch, then assigns each sample to - * one or several pads so that to rebuild a full chromatic scale (from note 35 - * to note 98). - * - * @author cyrille martraire - */ -public class MultisampleBuilder { - - private final int firstNote = 35; - - private final int padNumber = 64; - - private final Collection warnings = new ArrayList(); - - private static final String[] NOTES = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; - - private static final String[] NOTES_BIS = { "C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ", "G#", "A ", "A#", "B " }; - - /** - * @param sampleNames - * A list of String of the sample names without extension - */ - public Slot[] assign(List samples) { - try { - return asssignBare(samples); - } catch (Exception e) { - e.printStackTrace(); - return new Slot[64]; - } - } - - /** - * Converts a list of samples into a list of filenames without extension - */ - private static List sampleNames(List samples) { - final List list = new ArrayList(); - Iterator it = samples.iterator(); - while (it.hasNext()) { - final Sample sample = (Sample) it.next(); - final String sampleName = sample.getSampleName(); - System.out.println(sampleName); - list.add(sampleName); - } - return list; - } - - public Collection getWarnings() { - return warnings; - } - - private Slot[] asssignBare(List samples) { - if (samples.size() < 2) { - return null; - } - - final List sampleNames = sampleNames(samples); - final int commonIndex = longuestPrefix(sampleNames); - if (commonIndex == 0) { - return null; - } - - // build slots, returns a sorted list - final List slots = collectSlots(samples, commonIndex); - if (slots.size() <= 2) { - return null; - } - - // interpolate notes in between - final Slot[] multisample = new Slot[64]; - Slot last = null; - Iterator it = slots.iterator(); - while (it.hasNext()) { - final Slot slot = (Slot) it.next(); - final int note = slot.getNote(); - - // fill exact slot first, to be sure it wins - multisample[note - firstNote] = slot; - - // cross note is half way between previous sample slot and this - // sample slot - int crossNote = last == null ? firstNote - 1 : ((note + last.getNote()) / 2); - - if (last != null) { - // fill from previous slot till cross note - for (int transposeUp = last.getNote() + 1; transposeUp <= crossNote; transposeUp++) { - final int index = transposeUp - firstNote; - if (multisample[index] == null) { - final Slot transposed = last.transpose(transposeUp); - if (Math.abs(transposed.getTuning()) <= 36) { - multisample[index] = transposed; - } - } - } - } - - // fill from cross note till current slot - for (int transposeDown = crossNote + 1; transposeDown < note; transposeDown++) { - final int index = transposeDown - firstNote; - if (multisample[index] == null) { - final Slot transposed = slot.transpose(transposeDown); - if (Math.abs(transposed.getTuning()) <= 36) { - multisample[index] = transposed; - } - } - } - - last = slot; - } - - // finish till the end of the scale - for (int transposeUp = last.getNote() + 1; transposeUp < firstNote + padNumber; transposeUp++) { - final int index = transposeUp - firstNote; - if (multisample[index] == null) { - final Slot transposed = last.transpose(transposeUp); - if (Math.abs(transposed.getTuning()) <= 36) { - multisample[index] = transposed; - } - } - } - - return multisample; - } - - protected List collectSlots(final List samples, int commonIndex) { - final List slots = new ArrayList(); - Iterator it = samples.iterator(); - while (it.hasNext()) { - final Sample sample = (Sample) it.next(); - - final String word = sample.getSampleName(); - final String variablePart = word.substring(commonIndex); - final int note = extractNote(variablePart); - - if (note != -1 && note >= firstNote && note <= firstNote + padNumber) { - slots.add(new Slot(sample, note, 0)); - } else { - warnings.add("File: " + word - + " is not consistently named, will be ignored when building the multisamples"); - } - } - Collections.sort(slots); - return slots; - } - - protected static int longuestPrefix(final List words) { - int commonIndex = 16;// max - String last = null; - Iterator it = words.iterator(); - while (it.hasNext()) { - String word = (String) it.next(); - if (last != null) { - final int index = longuestPrefix(commonIndex, word, last); - if (index < commonIndex) { - commonIndex = index; - } - } - last = word; - } - return commonIndex; - } - - private static int longuestPrefix(int index, String word, String last) { - for (int i = 0; i < index && i < word.length() && i < last.length(); i++) { - if (word.charAt(i) != last.charAt(i)) { - return i; - } - } - return index; - } - - public static String noteName(final int note) { - final int chromatic = (note - 24) % 12; - final int octave = (note - 24) / 12; - final String noteName = NOTES[chromatic] + octave; - return noteName; - } - - public static int extractNote(final String noteName) { - for (int i = NOTES.length - 1; i >= 0; i--) { - String candidate = NOTES_BIS[i]; - int indexOf = noteName.lastIndexOf(candidate); - if (indexOf == -1) { - candidate = NOTES[i]; - indexOf = noteName.lastIndexOf(candidate); - } - if (indexOf != -1) { - final char octaveDigit = noteName.charAt(indexOf + candidate.length()); - int octave = 3; - if (Character.isDigit(octaveDigit)) { - octave = Integer.parseInt("" + octaveDigit); - } - return 24 + octave * 12 + i; - } - } - return -1; - } - - public String toString() { - return "MultisampleBuilder first note: " + noteName(firstNote) + ", " + padNumber + " pads"; - } - - /** - * Represents one sample used in a multisample program, including the - * chromatic note it is supposed to play and the tuning required to play - * this note - * - * @author cyrille martraire - */ - public class Slot implements Comparable { - - private final Object source; - - private final int note; - - private final double tuning; - - public Slot(Object source, int note, double tuning) { - this.source = source; - this.note = note; - this.tuning = tuning; - } - - public Slot transpose(final int anotherNote) { - final int requiredTuning = anotherNote - note; - return new Slot(source, anotherNote, requiredTuning); - } - - public Object getSource() { - return source; - } - - public int getNote() { - return note; - } - - public double getTuning() { - return tuning; - } - - public int compareTo(Object o) { - final Slot other = (Slot) o; - return note - other.note; - } - - /** - * @return true if this Slot is equal to the given Slot - */ - public boolean equals(Object arg0) { - if (!(arg0 instanceof Slot)) { - return false; - } - final Slot other = (Slot) arg0; - if (this == other) { - return true; - } - return note == other.note; - } - - public int hashCode() { - return note; - } - - public String toString() { - return "Slot " + note + " " + source + " tuning=" + tuning; - } - - } -} diff --git a/MpcMaid/src/com/mpcmaid/pgm/Profile.java b/MpcMaid/src/com/mpcmaid/pgm/Profile.java deleted file mode 100755 index 471f93c..0000000 --- a/MpcMaid/src/com/mpcmaid/pgm/Profile.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.mpcmaid.pgm; - -/** - * Represents the profile of an MPC - * - * @author cyrille martraire - */ -public final class Profile { - - private final String name; - - private final int rowNumber; - - private final int colNumber; - - private final int sliderNumber; - - private final int filterNumber; - - public final static Profile MPC500 = new Profile("MPC500", 4, 3, 1, 1); - - public final static Profile MPC1000 = new Profile("MPC1000", 4, 4, 2, 2); - - public Profile(String name, int rowNumber, int colNumber, int sliderNumber, int filterNumber) { - this.name = name; - this.rowNumber = rowNumber; - this.colNumber = colNumber; - this.sliderNumber = sliderNumber; - this.filterNumber = filterNumber; - } - - public String getName() { - return name; - } - - public int getPadNumber() { - return rowNumber * colNumber; - } - - public int getRowNumber() { - return rowNumber; - } - - public int getColNumber() { - return colNumber; - } - - public int getSliderNumber() { - return sliderNumber; - } - - public int getFilterNumber() { - return filterNumber; - } - - public String toString() { - return "Profile " + name; - } - - public static Profile getProfile(String name) { - return "MPC1000".equalsIgnoreCase(name) ? MPC1000 : MPC500; - } - -} diff --git a/MpcMaid/src/apple/dts/samplecode/osxadapter/OSXAdapter.java b/MpcMaid/src/main/java/apple/dts/samplecode/osxadapter/OSXAdapter.java old mode 100755 new mode 100644 similarity index 80% rename from MpcMaid/src/apple/dts/samplecode/osxadapter/OSXAdapter.java rename to MpcMaid/src/main/java/apple/dts/samplecode/osxadapter/OSXAdapter.java index 4088ea2..5f51df4 --- a/MpcMaid/src/apple/dts/samplecode/osxadapter/OSXAdapter.java +++ b/MpcMaid/src/main/java/apple/dts/samplecode/osxadapter/OSXAdapter.java @@ -51,7 +51,7 @@ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Copyright © 2003-2007 Apple, Inc., All Rights Reserved +Copyright � 2003-2007 Apple, Inc., All Rights Reserved */ @@ -61,18 +61,22 @@ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; public class OSXAdapter implements InvocationHandler { - protected Object targetObject; - protected Method targetMethod; - protected String proxySignature; + private static final Logger logger = System.getLogger(OSXAdapter.class.getName()); + + protected final Object targetObject; + protected final Method targetMethod; + protected final String proxySignature; static Object macOSXApplication; // Pass this method an Object and Method equipped to perform application shutdown logic - // The method passed should return a boolean stating whether or not the quit should occur + // The method passed should return a boolean stating whether the quit should occur public static void setQuitHandler(Object target, Method quitHandler) { setHandler(new OSXAdapter("handleQuit", target, quitHandler)); } @@ -87,11 +91,10 @@ public static void setAboutHandler(Object target, Method aboutHandler) { // If we're setting a handler, enable the About menu item by calling // com.apple.eawt.Application reflectively try { - Method enableAboutMethod = macOSXApplication.getClass().getDeclaredMethod("setEnabledAboutMenu", new Class[] { boolean.class }); - enableAboutMethod.invoke(macOSXApplication, new Object[] { Boolean.valueOf(enableAboutMenu) }); + Method enableAboutMethod = macOSXApplication.getClass().getDeclaredMethod("setEnabledAboutMenu", boolean.class); + enableAboutMethod.invoke(macOSXApplication, enableAboutMenu); } catch (Exception ex) { - System.err.println("OSXAdapter could not access the About Menu"); - ex.printStackTrace(); + logger.log(Level.ERROR, "OSXAdapter could not access the About Menu: " + ex.getMessage(), ex); } } @@ -105,11 +108,10 @@ public static void setPreferencesHandler(Object target, Method prefsHandler) { // If we're setting a handler, enable the Preferences menu item by calling // com.apple.eawt.Application reflectively try { - Method enablePrefsMethod = macOSXApplication.getClass().getDeclaredMethod("setEnabledPreferencesMenu", new Class[] { boolean.class }); - enablePrefsMethod.invoke(macOSXApplication, new Object[] { Boolean.valueOf(enablePrefsMenu) }); + Method enablePrefsMethod = macOSXApplication.getClass().getDeclaredMethod("setEnabledPreferencesMenu", boolean.class); + enablePrefsMethod.invoke(macOSXApplication, enablePrefsMenu); } catch (Exception ex) { - System.err.println("OSXAdapter could not access the About Menu"); - ex.printStackTrace(); + logger.log(Level.ERROR, "OSXAdapter could not access the About Menu: " + ex.getMessage(), ex); } } @@ -123,11 +125,11 @@ public static void setFileHandler(Object target, Method fileHandler) { public boolean callTarget(Object appleEvent) { if (appleEvent != null) { try { - Method getFilenameMethod = appleEvent.getClass().getDeclaredMethod("getFilename", (Class[])null); + Method getFilenameMethod = appleEvent.getClass().getDeclaredMethod("getFilename", (Class)null); String filename = (String) getFilenameMethod.invoke(appleEvent, (Object[])null); - this.targetMethod.invoke(this.targetObject, new Object[] { filename }); + this.targetMethod.invoke(this.targetObject, filename); } catch (Exception ex) { - + logger.log(Level.ERROR, ex::getMessage, ex); } } return true; @@ -138,20 +140,19 @@ public boolean callTarget(Object appleEvent) { // setHandler creates a Proxy object from the passed OSXAdapter and adds it as an ApplicationListener public static void setHandler(OSXAdapter adapter) { try { - Class applicationClass = Class.forName("com.apple.eawt.Application"); + Class applicationClass = Class.forName("com.apple.eawt.Application"); if (macOSXApplication == null) { - macOSXApplication = applicationClass.getConstructor((Class[])null).newInstance((Object[])null); + macOSXApplication = applicationClass.getConstructor((Class)null).newInstance((Object[])null); } - Class applicationListenerClass = Class.forName("com.apple.eawt.ApplicationListener"); - Method addListenerMethod = applicationClass.getDeclaredMethod("addApplicationListener", new Class[] { applicationListenerClass }); + Class applicationListenerClass = Class.forName("com.apple.eawt.ApplicationListener"); + Method addListenerMethod = applicationClass.getDeclaredMethod("addApplicationListener", applicationListenerClass); // Create a proxy object around this handler that can be reflectively added as an Apple ApplicationListener Object osxAdapterProxy = Proxy.newProxyInstance(OSXAdapter.class.getClassLoader(), new Class[] { applicationListenerClass }, adapter); - addListenerMethod.invoke(macOSXApplication, new Object[] { osxAdapterProxy }); + addListenerMethod.invoke(macOSXApplication, osxAdapterProxy); } catch (ClassNotFoundException cnfe) { - System.err.println("This version of Mac OS X does not support the Apple EAWT. ApplicationEvent handling has been disabled (" + cnfe + ")"); + logger.log(Level.ERROR, "This version of Mac OS X does not support the Apple EAWT. ApplicationEvent handling has been disabled (" + cnfe.getMessage() + ")", cnfe); } catch (Exception ex) { // Likely a NoSuchMethodException or an IllegalAccessException loading/invoking eawt.Application methods - System.err.println("Mac OS X Adapter could not talk to EAWT:"); - ex.printStackTrace(); + logger.log(Level.ERROR, "OSXAdapter could not talk to EAWT: " + ex.getMessage(), ex); } } @@ -171,7 +172,7 @@ public boolean callTarget(Object appleEvent) throws InvocationTargetException, I if (result == null) { return true; } - return Boolean.valueOf(result.toString()).booleanValue(); + return Boolean.parseBoolean(result.toString()); } // InvocationHandler implementation @@ -181,7 +182,8 @@ public Object invoke (Object proxy, Method method, Object[] args) throws Throwab boolean handled = callTarget(args[0]); setApplicationEventHandled(args[0], handled); } - // All of the ApplicationListener methods are void; return null regardless of what happens + // All the ApplicationListener methods are void; return null regardless of what happens + //noinspection SuspiciousInvocationHandlerImplementation return null; } @@ -196,12 +198,11 @@ protected boolean isCorrectMethod(Method method, Object[] args) { protected void setApplicationEventHandled(Object event, boolean handled) { if (event != null) { try { - Method setHandledMethod = event.getClass().getDeclaredMethod("setHandled", new Class[] { boolean.class }); + Method setHandledMethod = event.getClass().getDeclaredMethod("setHandled", boolean.class); // If the target method returns a boolean, use that as a hint - setHandledMethod.invoke(event, new Object[] { Boolean.valueOf(handled) }); + setHandledMethod.invoke(event, handled); } catch (Exception ex) { - System.err.println("OSXAdapter was unable to handle an ApplicationEvent: " + event); - ex.printStackTrace(); + logger.log(Level.ERROR, "OSXAdapter was unable to handle an ApplicationEvent: " + event + "cause " + ex.getMessage(), ex); } } } diff --git a/MpcMaid/src/com/centerkey/utils/BareBonesBrowserLaunch.java b/MpcMaid/src/main/java/com/centerkey/utils/BareBonesBrowserLaunch.java old mode 100755 new mode 100644 similarity index 82% rename from MpcMaid/src/com/centerkey/utils/BareBonesBrowserLaunch.java rename to MpcMaid/src/main/java/com/centerkey/utils/BareBonesBrowserLaunch.java index 5d52618..4c7ec7e --- a/MpcMaid/src/com/centerkey/utils/BareBonesBrowserLaunch.java +++ b/MpcMaid/src/main/java/com/centerkey/utils/BareBonesBrowserLaunch.java @@ -1,49 +1,48 @@ -///////////////////////////////////////////////////////// -// Bare Bones Browser Launch // -// Version 1.5 (December 10, 2005) // -// By Dem Pilafian // -// Supports: Mac OS X, GNU/Linux, Unix, Windows XP // -// Example Usage: // -// String url = "http://www.centerkey.com/"; // -// BareBonesBrowserLaunch.openURL(url); // -// Public Domain Software -- Free to Use as You Like // -///////////////////////////////////////////////////////// - -//EDIT cyrille martraire: I think we should close Process after call to exec() - -package com.centerkey.utils; - -import java.io.IOException; -import java.lang.reflect.Method; -import javax.swing.JOptionPane; - -public class BareBonesBrowserLaunch { - - private static final String errMsg = "Error attempting to launch web browser"; - - public static void openURL(String url) { - String osName = System.getProperty("os.name"); - try { - if (osName.startsWith("Mac OS")) { - Class fileMgr = Class.forName("com.apple.eio.FileManager"); - Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[] { String.class }); - openURL.invoke(null, new Object[] { url }); - } else if (osName.startsWith("Windows")) - Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url); - else { // assume Unix or Linux - String[] browsers = { "firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape" }; - String browser = null; - for (int count = 0; count < browsers.length && browser == null; count++) - if (Runtime.getRuntime().exec(new String[] { "which", browsers[count] }).waitFor() == 0) - browser = browsers[count]; - if (browser == null) - throw new Exception("Could not find web browser"); - else - Runtime.getRuntime().exec(new String[] { browser, url }); - } - } catch (Exception e) { - JOptionPane.showMessageDialog(null, errMsg + ":\n" + e.getLocalizedMessage()); - } - } - -} +///////////////////////////////////////////////////////// +// Bare Bones Browser Launch // +// Version 1.5 (December 10, 2005) // +// By Dem Pilafian // +// Supports: Mac OS X, GNU/Linux, Unix, Windows XP // +// Example Usage: // +// String url = "http://www.centerkey.com/"; // +// BareBonesBrowserLaunch.openURL(url); // +// Public Domain Software -- Free to Use as You Like // +///////////////////////////////////////////////////////// + +//EDIT cyrille martraire: I think we should close Process after call to exec() + +package com.centerkey.utils; + +import java.lang.reflect.Method; +import javax.swing.JOptionPane; + +public class BareBonesBrowserLaunch { + + private static final String errMsg = "Error attempting to launch web browser"; + + public static void openURL(String url) { + String osName = System.getProperty("os.name"); + try { + if (osName.startsWith("Mac OS")) { + Class fileMgr = Class.forName("com.apple.eio.FileManager"); + Method openURL = fileMgr.getDeclaredMethod("openURL", String.class); + openURL.invoke(null, url); + } else if (osName.startsWith("Windows")) + Runtime.getRuntime().exec(new String[]{"rundll32 url.dll,FileProtocolHandler " + url}); + else { // assume Unix or Linux + String[] browsers = { "firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape" }; + String browser = null; + for (int count = 0; count < browsers.length && browser == null; count++) + if (Runtime.getRuntime().exec(new String[] { "which", browsers[count] }).waitFor() == 0) + browser = browsers[count]; + if (browser == null) + throw new Exception("Could not find web browser"); + else + Runtime.getRuntime().exec(new String[] { browser, url }); + } + } catch (Exception e) { + JOptionPane.showMessageDialog(null, errMsg + ":\n" + e.getLocalizedMessage()); + } + } + +} diff --git a/MpcMaid/src/MPCMaid.java b/MpcMaid/src/main/java/com/mpcmaid/MPCMaid.java old mode 100755 new mode 100644 similarity index 65% rename from MpcMaid/src/MPCMaid.java rename to MpcMaid/src/main/java/com/mpcmaid/MPCMaid.java index 4304fe8..0e58e3c --- a/MpcMaid/src/MPCMaid.java +++ b/MpcMaid/src/main/java/com/mpcmaid/MPCMaid.java @@ -1,7 +1,12 @@ +package com.mpcmaid; + import java.awt.Dimension; import java.awt.Toolkit; import java.io.File; import java.net.URL; +import java.util.Objects; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import javax.swing.ImageIcon; import javax.swing.JLabel; @@ -23,10 +28,12 @@ public final class MPCMaid { // splash screen private static JWindow screen = null; + private final static Logger logger = System.getLogger(MPCMaid.class.getName()); + public static void showSplash() { screen = new JWindow(); final URL resource = MainFrame.class.getResource("mpcmaidlogo400_400.png"); - final JLabel label = new JLabel(new ImageIcon(resource)); + final JLabel label = new JLabel(new ImageIcon(Objects.requireNonNull(resource))); screen.getContentPane().add(label); screen.setLocationRelativeTo(null); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); @@ -75,38 +82,37 @@ public static void main(String[] args) { if (showSplash) showSplash(); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - final BaseFrame baseFrame; - if (programFile != null && programFile.exists()) { - baseFrame = new MainFrame(programFile); - } else { - baseFrame = new MainFrame(); - } - // wait to show the splash - if (screen != null) { - try { - Thread.sleep(1500); - } catch (InterruptedException e) { - e.printStackTrace(); - } + SwingUtilities.invokeLater(() -> { + final BaseFrame baseFrame; + if (programFile != null && programFile.exists()) { + baseFrame = new MainFrame(programFile); + } else { + baseFrame = new MainFrame(); + } + // wait to show the splash + if (screen != null) { + try { + Thread.sleep(1500); + } catch (InterruptedException e) { + logger.log(Level.ERROR, e::getMessage, e); } - //baseFrame.setVisible(true); - baseFrame.show(); + } + baseFrame.setVisible(true); + //baseFrame.show(); - hideSplash(); - } - }); + hideSplash(); + }); } - public static final boolean isMacOsX() { + public static boolean isMacOsX() { return System.getProperty("mrj.version") != null; } - public static final void makeAsNativeAsPossible() { + public static void makeAsNativeAsPossible() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { + logger.log(Level.ERROR, e::getMessage, e); } try { if (isMacOsX()) { @@ -114,14 +120,17 @@ public static final void makeAsNativeAsPossible() { System.setProperty("com.apple.mrj.application.apple.menu.about.name", "MPC Maid"); } } catch (Exception e) { + logger.log(Level.ERROR, e::getMessage, e); } try { Preferences.getInstance().load(); - } catch (Exception ignore) { + } catch (Exception e) { + logger.log(Level.ERROR, e::getMessage, e); } } - public static final void showHelp() { + public static void showHelp() { + // This is not a log use case, so System.err. is the right implementation System.err.println("Usage: mpcmaid [-h] [-n] []"); System.err.println(); System.err.println(" -n Do not show splash screen"); diff --git a/MpcMaid/src/com/mpcmaid/audio/AudioWorker.java b/MpcMaid/src/main/java/com/mpcmaid/audio/AudioWorker.java similarity index 71% rename from MpcMaid/src/com/mpcmaid/audio/AudioWorker.java rename to MpcMaid/src/main/java/com/mpcmaid/audio/AudioWorker.java index b76fd80..d38af31 100644 --- a/MpcMaid/src/com/mpcmaid/audio/AudioWorker.java +++ b/MpcMaid/src/main/java/com/mpcmaid/audio/AudioWorker.java @@ -1,13 +1,10 @@ package com.mpcmaid.audio; +import javax.sound.sampled.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; - -import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.DataLine; -import javax.sound.sampled.LineUnavailableException; -import javax.sound.sampled.SourceDataLine; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; /** * A sample-playing thread which uses single dataline to play samples. @@ -16,6 +13,8 @@ public class AudioWorker extends Thread { private final BlockingQueue clipQueue; + private static final Logger logger = System.getLogger(AudioWorker.class.getName()); + AudioWorker(BlockingQueue queue) { this.clipQueue = queue; } @@ -27,11 +26,12 @@ public class AudioWorker extends Thread { */ public void run() { SourceDataLine dataLine = null; - while (true) { + //noinspection + while (true) { try { Sample sample; try { - sample = (Sample) clipQueue.poll(5, TimeUnit.SECONDS); + sample = clipQueue.poll(5, TimeUnit.SECONDS); if (sample == null) { if (dataLine != null && dataLine.isOpen() && !dataLine.isRunning()) { dataLine.close(); @@ -46,7 +46,7 @@ public void run() { } continue; } - AudioFormat format = sample.getFormat(); + AudioFormat format = sample.format(); if (dataLine == null) { DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); dataLine = (SourceDataLine) AudioSystem.getLine(info); @@ -64,14 +64,10 @@ public void run() { if (!dataLine.isRunning()) dataLine.start(); - dataLine.write(sample.getBytes(), 0, sample.getBytes().length); + dataLine.write(sample.bytes(), 0, sample.bytes().length); //dataLine.close(); - } catch (LineUnavailableException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (Throwable t) { - t.printStackTrace(); + } catch (LineUnavailableException | IllegalArgumentException e) { + logger.log(Level.ERROR, e::getMessage, e); } } } diff --git a/MpcMaid/src/main/java/com/mpcmaid/audio/LocationRange.java b/MpcMaid/src/main/java/com/mpcmaid/audio/LocationRange.java new file mode 100644 index 0000000..06740d3 --- /dev/null +++ b/MpcMaid/src/main/java/com/mpcmaid/audio/LocationRange.java @@ -0,0 +1,19 @@ +package com.mpcmaid.audio; + +/** + * Represents a location range + * + * @author cyrille martraire + */ +public record LocationRange(int from, int to) { + + + public int getMidLocation() { + return (from + to) / 2; + } + + public String toString() { + return "LocationRange [" + from + " - " + to + "]"; + } + +} diff --git a/MpcMaid/src/com/mpcmaid/audio/Marker.java b/MpcMaid/src/main/java/com/mpcmaid/audio/Marker.java old mode 100755 new mode 100644 similarity index 80% rename from MpcMaid/src/com/mpcmaid/audio/Marker.java rename to MpcMaid/src/main/java/com/mpcmaid/audio/Marker.java index c463494..c925656 --- a/MpcMaid/src/com/mpcmaid/audio/Marker.java +++ b/MpcMaid/src/main/java/com/mpcmaid/audio/Marker.java @@ -6,7 +6,7 @@ * * @author cyrille martraire */ -public final class Marker implements Comparable { +public final class Marker implements Comparable { private int location; public Marker(int location) { @@ -32,9 +32,8 @@ public Marker duplicate() { return new Marker(location); } - public int compareTo(Object o) { - final Marker other = (Marker) o; - return location - other.location; + public int compareTo(Marker o) { + return location - o.location; } public String toString() { diff --git a/MpcMaid/src/com/mpcmaid/audio/Markers.java b/MpcMaid/src/main/java/com/mpcmaid/audio/Markers.java old mode 100755 new mode 100644 similarity index 90% rename from MpcMaid/src/com/mpcmaid/audio/Markers.java rename to MpcMaid/src/main/java/com/mpcmaid/audio/Markers.java index 4858da8..bc4fb4f --- a/MpcMaid/src/com/mpcmaid/audio/Markers.java +++ b/MpcMaid/src/main/java/com/mpcmaid/audio/Markers.java @@ -22,7 +22,7 @@ public class Markers { public static final int NONE = -1; - private final List markers = new ArrayList(); + private final List markers = new ArrayList<>(); private int selectedMarker = 0; @@ -74,7 +74,7 @@ public void selectClosestMarker(final int location) { if (isUnset()) { return; } - int distance = Math.abs(markers.get(0).getLocation() - location); + int distance = Math.abs(markers.getFirst().getLocation() - location); int idx = 0; for (int c = 1; c < markers.size(); c++) { int cdistance = Math.abs(markers.get(c).getLocation() - location); @@ -92,11 +92,11 @@ public void nudgeMarker(final int ticks, Slicer adjustor) { int min = 0; if (marker != null) { if (markers.size() > selectedMarker + 1) { - final Marker nextMarker = (Marker) markers.get(selectedMarker + 1); + final Marker nextMarker = markers.get(selectedMarker + 1); max = nextMarker.getLocation(); } if (selectedMarker > 0) { - final Marker previousMarker = (Marker) markers.get(selectedMarker - 1); + final Marker previousMarker = markers.get(selectedMarker - 1); min = previousMarker.getLocation(); } int location = marker.move(ticks); @@ -113,12 +113,11 @@ public void nudgeMarker(final int ticks, Slicer adjustor) { } public Marker getSelectedMarker() { - final Marker marker = (Marker) markers.get(selectedMarker); - return marker; + return markers.get(selectedMarker); } public boolean isUnset() { - return markers.size() == 0; + return markers.isEmpty(); } public void deleteSelectedMarker() { @@ -145,8 +144,7 @@ public int getSelectedMarkerLocation() { } public float getDuration() { - final float duration = (float) maxLocation / samplingRate; - return duration; + return (float) maxLocation / samplingRate; } public int getLocation(final int markerIndex) { @@ -156,7 +154,7 @@ public int getLocation(final int markerIndex) { if (markerIndex >= markers.size()) { return maxLocation; } - final Marker marker = (Marker) markers.get(markerIndex); + final Marker marker = markers.get(markerIndex); if (marker == null) { return 0; } @@ -212,7 +210,7 @@ public Sequence exportMidiSequence(final File file, final int ppq) throws IOExce final MidiSequenceBuilder builder = new MidiSequenceBuilder(ppq); final Track track = builder.getTrack(); final int n = markers.size(); - int startTick = 0; + int startTick; int key = 35; for (int i = 0; i < n; i++) { final int location = getLocation(i); diff --git a/MpcMaid/src/com/mpcmaid/audio/Sample.java b/MpcMaid/src/main/java/com/mpcmaid/audio/Sample.java old mode 100755 new mode 100644 similarity index 65% rename from MpcMaid/src/com/mpcmaid/audio/Sample.java rename to MpcMaid/src/main/java/com/mpcmaid/audio/Sample.java index af1449b..8d302ef --- a/MpcMaid/src/com/mpcmaid/audio/Sample.java +++ b/MpcMaid/src/main/java/com/mpcmaid/audio/Sample.java @@ -5,45 +5,35 @@ import java.io.IOException; import java.io.InputStream; -import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.DataLine; -import javax.sound.sampled.LineUnavailableException; -import javax.sound.sampled.SourceDataLine; import javax.sound.sampled.AudioFileFormat.Type; /** * Represents an audio sample - * + * * @author cyrille martraire */ -public class Sample { - - private final byte[] bytes; - - private final AudioFormat format; - - private final int frameLength; +public record Sample(byte[] bytes, AudioFormat format, int frameLength) { public static Sample open(final File file) throws Exception { final AudioInputStream audioStream = AudioSystem.getAudioInputStream(file); return open(audioStream); } - protected static Sample open(final InputStream is) throws Exception { + static Sample open(final InputStream is) throws Exception { final AudioInputStream audioStream = AudioSystem.getAudioInputStream(is); return open(audioStream); } - private static Sample open(final AudioInputStream audioStream) throws LineUnavailableException, IOException { + private static Sample open(final AudioInputStream audioStream) throws IOException { final int frameLength = (int) audioStream.getFrameLength(); if (frameLength > 44100 * 8 * 2) { throw new IllegalArgumentException("The audio file is too long (must be shorter than 4 bars at 50BPM)"); } final AudioFormat format = audioStream.getFormat(); - final int frameSize = (int) format.getFrameSize(); + final int frameSize = format.getFrameSize(); final byte[] bytes = new byte[frameLength * frameSize]; final int result = audioStream.read(bytes); if (result < 0) { @@ -55,31 +45,25 @@ private static Sample open(final AudioInputStream audioStream) throws LineUnavai return new Sample(bytes, format, frameLength); } - public void play() throws Exception { + public void play() { SamplePlayer.getInstance().play(this); } public void save(File file) throws Exception { - final Type fileType = AudioFileFormat.Type.WAVE; + final Type fileType = Type.WAVE; final AudioInputStream stream = new AudioInputStream(new ByteArrayInputStream(bytes), format, frameLength); AudioSystem.write(stream, fileType, file); } - public Sample(byte[] buffer, AudioFormat format, int frameLength) { - this.bytes = buffer; - this.format = format; - this.frameLength = frameLength; - } - public int[][] asSamples() { final int numChannels = format.getChannels(); final int[][] toReturn = new int[numChannels][frameLength]; int sampleIndex = 0; - for (int t = 0; t < bytes.length;) { + for (int t = 0; t < bytes.length; ) { for (int channel = 0; channel < numChannels; channel++) { - int low = (int) bytes[t]; + int low = bytes[t]; t++; - int high = (int) bytes[t]; + int high = bytes[t]; t++; int sample = (high << 8) + (low & 0x00ff); toReturn[channel][sampleIndex] = sample; @@ -89,28 +73,15 @@ public int[][] asSamples() { return toReturn; } - public byte[] getBytes() { - return bytes; - } - - public AudioFormat getFormat() { - return format; - } - - public int getFrameLength() { - return frameLength; - } /** - * + * */ public Sample subRegion(int from, int to) { final int frameLength = to - from; - final int frameSize = (int) format.getFrameSize(); + final int frameSize = format.getFrameSize(); final byte[] region = new byte[frameLength * frameSize]; - for (int i = 0; i < region.length; i++) { - region[i] = bytes[from * frameSize + i]; - } + System.arraycopy(bytes, from * frameSize, region, 0, region.length); return new Sample(region, format, region.length); } diff --git a/MpcMaid/src/com/mpcmaid/audio/SamplePlayer.java b/MpcMaid/src/main/java/com/mpcmaid/audio/SamplePlayer.java old mode 100755 new mode 100644 similarity index 75% rename from MpcMaid/src/com/mpcmaid/audio/SamplePlayer.java rename to MpcMaid/src/main/java/com/mpcmaid/audio/SamplePlayer.java index 081aab7..f5ada9c --- a/MpcMaid/src/com/mpcmaid/audio/SamplePlayer.java +++ b/MpcMaid/src/main/java/com/mpcmaid/audio/SamplePlayer.java @@ -3,10 +3,12 @@ import java.io.File; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; /** - * An sample player which employs limited number of threads to play clips. Each - * thread creates it's own dataLine. + * A sample player which employs limited number of threads to play clips. Each + * thread creates its own dataLine. * * @pattern Singleton We only need one sample player for every window, so that * to control the overall polyphony. @@ -14,9 +16,11 @@ */ public final class SamplePlayer { + private final static Logger logger = System.getLogger(SamplePlayer.class.getName()); + private final static SamplePlayer INSTANCE = new SamplePlayer(); - private final static BlockingQueue queue = new ArrayBlockingQueue(1); + private final static BlockingQueue queue = new ArrayBlockingQueue<>(1); static { // only six sounds can be heard at once @@ -42,7 +46,7 @@ public void play(File file) { if (queue.isEmpty()) queue.add(Sample.open(file)); } catch (Exception e) { - e.printStackTrace(); + logger.log(Level.ERROR, e::getMessage, e); } } diff --git a/MpcMaid/src/com/mpcmaid/audio/Slicer.java b/MpcMaid/src/main/java/com/mpcmaid/audio/Slicer.java old mode 100755 new mode 100644 similarity index 85% rename from MpcMaid/src/com/mpcmaid/audio/Slicer.java rename to MpcMaid/src/main/java/com/mpcmaid/audio/Slicer.java index b48b698..4d86622 --- a/MpcMaid/src/com/mpcmaid/audio/Slicer.java +++ b/MpcMaid/src/main/java/com/mpcmaid/audio/Slicer.java @@ -20,7 +20,7 @@ public class Slicer { private final Sample sample; // cache - private int[][] channels; + private final int[][] channels; private int sensitivity = 130; @@ -48,18 +48,18 @@ public void extractMarkers() { * compare the energy of each window against the average local energy on a * number of neighbor windows; when this comparison is greater enough, we * got a beat. - * + *

* To reduce the number of fake beats, we also use a toggle state so that no * beat can be found immediately after a beat already found. - * + *

* When a beat has been found, its exact location is then adjusted to the * nearest zero-crossing location in the past. - * + *

* For each beat found, a corresponding marker is added to the list of * markers. */ public void extractMarkers(final int[][] channels) { - markers.clear(getFrameLength(), (int) sample.getFormat().getFrameRate()); + markers.clear(getFrameLength(), (int) sample.format().getFrameRate()); final int step = windowSize / overlapRatio; @@ -97,12 +97,11 @@ protected int[] getSamplesL(final int[][] channels) { private long localEnergy(int i, long[] energyHistory) { final int n = energyHistory.length; final int m = localEnergyWindowSize; - int from = 0; + int from; int to = m; if (i < m) { from = 0; - to = m; - } else if (i + m < n) { + } else if (i + m < n) { from = i; to = i + m; } else { @@ -111,7 +110,7 @@ private long localEnergy(int i, long[] energyHistory) { } long sum = 0; for (int j = from; j < to; j++) { - sum += Math.pow(energyHistory[j], 1); + sum += (long) Math.pow(energyHistory[j], 1); } return sum / m; } @@ -133,27 +132,27 @@ private long[] energyHistory(final int[][] channels, final int windowSize, final long sum = 0; // for the window size, cumulate energy for (int j = 0; j < windowSize; j++) { - sum += Math.pow(samplesL[i + j], 2); - sum += Math.pow(samplesR[i + j], 2); + sum += (long) Math.pow(samplesL[i + j], 2); + sum += (long) Math.pow(samplesR[i + j], 2); } energy[windowIndex++] = sum; } return energy; } - private final static int nearestZeroCrossing(final int[] samples, final int index, final int excursion) { + private static int nearestZeroCrossing(final int[] samples, final int index, final int excursion) { if (index == 0) { return 0; } int i = index; - final int min = index - excursion >= 0 ? index - excursion : 0; + final int min = Math.max(index - excursion, 0); while (!isZeroCross(samples, i) && i > min) { i--; } return i; } - private final static boolean isZeroCross(final int[] samples, final int index) { + private static boolean isZeroCross(final int[] samples, final int index) { if (index == 0) { return true; } @@ -174,7 +173,7 @@ public Sample getSample() { } public int getFrameLength() { - return sample.getFrameLength(); + return sample.frameLength(); } public void setSensitivity(final int sensitivity) { @@ -188,8 +187,7 @@ public int getSensitivity() { public int adjustNearestZeroCrossing(int location, final int excursion) { final int[] samplesL = channels[0]; - final int adjustedZc = nearestZeroCrossing(samplesL, location, excursion); - return adjustedZc; + return nearestZeroCrossing(samplesL, location, excursion); } // ------------------------------ @@ -205,14 +203,14 @@ public Sample getSelectedSlice() { public Sample getSlice(final int markerIndex) { final LocationRange range = markers.getRangeFrom(markerIndex); - return sample.subRegion(range.getFrom(), range.getTo()); + return sample.subRegion(range.from(), range.to()); } /** * Exports each slice as defined by the markers into a slice file */ - public List exportSlices(File path, String prefix) throws Exception { - final List files = new ArrayList(); + public List exportSlices(File path, String prefix) throws Exception { + final List files = new ArrayList<>(); final int n = markers.size(); for (int i = 0; i < n; i++) { final Sample slice = getSlice(i); diff --git a/MpcMaid/src/com/mpcmaid/gui/BaseFrame.java b/MpcMaid/src/main/java/com/mpcmaid/gui/BaseFrame.java old mode 100755 new mode 100644 similarity index 82% rename from MpcMaid/src/com/mpcmaid/gui/BaseFrame.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/BaseFrame.java index 334b71e..7bbfcfc --- a/MpcMaid/src/com/mpcmaid/gui/BaseFrame.java +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/BaseFrame.java @@ -52,38 +52,30 @@ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), */ -import java.awt.Container; -import java.awt.FlowLayout; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.File; - -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.KeyStroke; - import apple.dts.samplecode.osxadapter.OSXAdapter; - import com.mpcmaid.audio.SamplePlayer; +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.io.File; +import java.io.Serial; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; + /** * Main Frame subclass, to be subclassed again on each action method (open, - * saveAs.. etc) + * saveAs, etc.) * * @author cyrille martraire */ public class BaseFrame extends JFrame implements ActionListener { + private static final Logger logger = System.getLogger(BaseFrame.class.getName()); + + @Serial + private static final long serialVersionUID = -8081595568054819394L; + protected static int windowCounter = -1; protected JDialog aboutBox, prefs; @@ -96,10 +88,10 @@ public class BaseFrame extends JFrame implements ActionListener { // Check that we are on Mac OS X. This is crucial to loading and using the // OSXAdapter class. - public static boolean MAC_OS_X = (System.getProperty("os.name").toLowerCase().startsWith("mac os x")); + public static final boolean MAC_OS_X = (System.getProperty("os.name").toLowerCase().startsWith("mac os x")); // Ask AWT which menu modifier we should be using. - protected final static int MENU_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + protected final static int MENU_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx(); public BaseFrame() { super("MPCMaid"); @@ -113,7 +105,7 @@ public void init() { protected void initMenuBar() { JMenu fileMenu = new JMenu("File"); JMenuBar mainMenuBar = new JMenuBar(); - mainMenuBar.add(fileMenu = new JMenu("File")); + mainMenuBar.add(fileMenu); fileMenu.add(newMI = new JMenuItem("New")); newMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, MENU_MASK)); @@ -192,10 +184,9 @@ protected void initComponents() { // Determine the offset value and stagger new windows // (with a reset every ten windows). A somewhat // unscientific mechanism, but it works well enough. - int offset = 0; if ((windowCounter % 10) > 0) { - offset = ((windowCounter) % 10) * 20 + 20; - this.setLocation(new Double(getLocation().getX() + offset - 20).intValue(), new Double(getLocation().getY() + int offset = ((windowCounter) % 10) * 20 + 20; + this.setLocation(Double.valueOf(getLocation().getX() + offset - 20).intValue(), Double.valueOf(getLocation().getY() + offset).intValue()); } @@ -203,7 +194,7 @@ protected void initComponents() { setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setResizable(false); - loadInitialDocument(); + //loadInitialDocument(); makeGUI(); makeAboutDialog(); makePrefsDialog(); @@ -214,10 +205,7 @@ protected void initComponents() { } - protected void loadInitialDocument() { - } - - public void makePrefsDialog() { + public void makePrefsDialog() { } @@ -229,24 +217,12 @@ protected void makeGUI() { JButton play = new JButton("Play1"); final Container contentPane = getContentPane(); - contentPane.setLayout(new FlowLayout(2)); + contentPane.setLayout(new FlowLayout(FlowLayout.RIGHT)); contentPane.add(play); - play.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - SamplePlayer.getInstance().play(new File("clap 1.WAV")); - } - - }); + play.addActionListener(e -> SamplePlayer.getInstance().play(new File("clap 1.WAV"))); JButton play2 = new JButton("Play2"); contentPane.add(play2); - play2.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - SamplePlayer.getInstance().play(new File("bullshit1.wav")); - } - - }); + play2.addActionListener(e -> SamplePlayer.getInstance().play(new File("bullshit1.wav"))); } // Generic registration with the Mac OS X application menu @@ -260,13 +236,12 @@ private void registerForMacOSXEvents() { // all the methods we wish to // use as delegates for various // com.apple.eawt.ApplicationListener methods - OSXAdapter.setQuitHandler(this, getClass().getDeclaredMethod("quit", (Class[]) null)); - OSXAdapter.setAboutHandler(this, getClass().getDeclaredMethod("about", (Class[]) null)); - OSXAdapter.setPreferencesHandler(this, getClass().getDeclaredMethod("preferences", (Class[]) null)); - OSXAdapter.setFileHandler(this, getClass().getDeclaredMethod("loadFile", new Class[] { String.class })); + OSXAdapter.setQuitHandler(this, getClass().getDeclaredMethod("quit", (Class) null)); + OSXAdapter.setAboutHandler(this, getClass().getDeclaredMethod("about", (Class) null)); + OSXAdapter.setPreferencesHandler(this, getClass().getDeclaredMethod("preferences", (Class) null)); + OSXAdapter.setFileHandler(this, getClass().getDeclaredMethod("loadFile", String.class)); } catch (Exception e) { - System.err.println("Error while loading the OSXAdapter:"); - e.printStackTrace(); + logger.log(Level.ERROR,"Error while loading the OSXAdapter: " + e.getMessage(),e); } } } @@ -331,14 +306,14 @@ public void actionPerformed(ActionEvent e) { } public void newWindow() { - new BaseFrame().show(); + new BaseFrame().setVisible(true); } public void open() { } public void close() { - checkOnClose(); + //checkOnClose(); setVisible(false); windowCounter--; @@ -348,29 +323,19 @@ public void close() { } - protected void checkOnClose() { - - } - public void save() { - System.out.println(getTitle()); - System.out.println("Save..."); + logger.log(Level.INFO, getTitle()); + logger.log(Level.INFO, "Save..."); } public void saveAs() { - System.out.println(getTitle()); - System.out.println("Save As..."); + logger.log(Level.INFO, getTitle()); + logger.log(Level.INFO, "Save As..."); } public void export() { - System.out.println(getTitle()); - System.out.println("Export..."); - } - - public void loadFile(String path) { - // only supported if installed via an app bundle - final File file = new File(path); - System.out.println("load: " + path); + logger.log(Level.INFO, getTitle()); + logger.log(Level.INFO, "Export..."); } public String toString() { diff --git a/MpcMaid/src/com/mpcmaid/gui/BatchCreateCommand.java b/MpcMaid/src/main/java/com/mpcmaid/gui/BatchCreateCommand.java old mode 100755 new mode 100644 similarity index 78% rename from MpcMaid/src/com/mpcmaid/gui/BatchCreateCommand.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/BatchCreateCommand.java index 33330f9..4962fd4 --- a/MpcMaid/src/com/mpcmaid/gui/BatchCreateCommand.java +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/BatchCreateCommand.java @@ -42,14 +42,14 @@ public BatchCreateCommand(File root, Program pgm, final int padNumber) { public void batchCreate(File path) { final File[] memberFiles = path.listFiles(); boolean hasPgm = false; - for (int i = 0; i < memberFiles.length; i++) { - final File file = memberFiles[i]; - if (file.isDirectory()) { - batchCreate(file); - } else if (file.getName().toLowerCase().endsWith(".pgm")) { - hasPgm = true; - } - } + assert memberFiles != null; + for (final File file : memberFiles) { + if (file.isDirectory()) { + batchCreate(file); + } else if (file.getName().toLowerCase().endsWith(".pgm")) { + hasPgm = true; + } + } if (hasPgm) { return; } @@ -58,7 +58,7 @@ public void batchCreate(File path) { private void createPaginatedPrograms(File path, final File[] memberFiles) { // create as many programs needed to fill the m pads - List list = new ArrayList(); + List list = new ArrayList<>(); int page = 1; // constructs the folder name by escaping the path name plus a number to @@ -69,22 +69,21 @@ private void createPaginatedPrograms(File path, final File[] memberFiles) { pgmPostfix++; } - for (int i = 0; i < memberFiles.length; i++) { - final File file = memberFiles[i]; - if (!file.isDirectory() && file.getName().toLowerCase().endsWith(".wav")) { - list.add(file); - } - if (list.size() == padNumber) { - createProgram(pgm, new File(path, listingName + page + ".pgm"), list); - page++; - list.clear(); - } - - } + for (final File file : memberFiles) { + if (!file.isDirectory() && file.getName().toLowerCase().endsWith(".wav")) { + list.add(file); + } + if (list.size() == padNumber) { + createProgram(pgm, new File(path, listingName + page + ".pgm"), list); + page++; + list.clear(); + } + + } createProgram(pgm, new File(path, listingName + page + ".pgm"), list); } - private void createProgram(Program templatePgm, File newPgmFile, List files) { + private void createProgram(Program templatePgm, File newPgmFile, List files) { if (files.isEmpty()) { return; } @@ -92,10 +91,10 @@ private void createProgram(Program templatePgm, File newPgmFile, List files) { final Program newPgm = new Program(templatePgm); // import files and assign them to each pad (first layer) in turn - Iterator it = files.iterator(); + Iterator it = files.iterator(); int i = 0; while (it.hasNext()) { - final File file = (File) it.next(); + final File file = it.next(); importCount++; final Sample sample = Sample.importFile(file, 16, Sample.RENAMED, true, renameCount); if (sample == null || sample.isRejected()) { diff --git a/MpcMaid/src/com/mpcmaid/gui/BindingCapable.java b/MpcMaid/src/main/java/com/mpcmaid/gui/BindingCapable.java old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/src/com/mpcmaid/gui/BindingCapable.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/BindingCapable.java diff --git a/MpcMaid/src/com/mpcmaid/gui/FileDragHandler.java b/MpcMaid/src/main/java/com/mpcmaid/gui/FileDragHandler.java old mode 100755 new mode 100644 similarity index 53% rename from MpcMaid/src/com/mpcmaid/gui/FileDragHandler.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/FileDragHandler.java index b5b107c..c4b0bf1 --- a/MpcMaid/src/com/mpcmaid/gui/FileDragHandler.java +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/FileDragHandler.java @@ -3,7 +3,10 @@ import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.io.File; +import java.io.Serial; import java.util.List; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; import javax.swing.JComponent; import javax.swing.TransferHandler; @@ -14,40 +17,45 @@ * * @author cyrille martraire */ +@SuppressWarnings("unchecked") public class FileDragHandler extends TransferHandler { + private static final Logger logger = System.getLogger(FileDragHandler.class.getName()); + + @Serial + private static final long serialVersionUID = 2989210654686012401L; + public boolean importData(JComponent c, Transferable data) { if (!canImport(c, data.getTransferDataFlavors())) { return false; } try { - final List files = (List) data.getTransferData(DataFlavor.javaFileListFlavor); + final List files = (List) data.getTransferData(DataFlavor.javaFileListFlavor); process(files); } catch (Exception e) { - e.printStackTrace(); + logger.log(Level.ERROR, e::getMessage, e); } return true; } - protected void process(List files) { - for (int i = 0; i < files.size(); i++) { - File file = (File) files.get(i); - process(file); - } + protected void process(List files) { + for (File file : files) { + process(file); + } } protected void process(File file) { - System.out.println(file.getAbsolutePath()); + logger.log(Level.INFO, file.getAbsolutePath()); } public boolean canImport(JComponent c, DataFlavor[] flavors) { final DataFlavor fileFlavor = DataFlavor.javaFileListFlavor; - for (int i = 0; i < flavors.length; i++) { - if (fileFlavor.equals(flavors[i])) { - return true; - } - } + for (DataFlavor flavor : flavors) { + if (fileFlavor.equals(flavor)) { + return true; + } + } return false; } } \ No newline at end of file diff --git a/MpcMaid/src/com/mpcmaid/gui/MainFrame.java b/MpcMaid/src/main/java/com/mpcmaid/gui/MainFrame.java old mode 100755 new mode 100644 similarity index 73% rename from MpcMaid/src/com/mpcmaid/gui/MainFrame.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/MainFrame.java index 3567eee..8b2b7a1 --- a/MpcMaid/src/com/mpcmaid/gui/MainFrame.java +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/MainFrame.java @@ -6,20 +6,18 @@ import java.awt.FileDialog; import java.awt.Font; import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseWheelEvent; -import java.awt.event.MouseWheelListener; import java.awt.image.BufferedImage; import java.io.File; -import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; +import java.io.Serial; +import java.util.Objects; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import javax.imageio.ImageIO; import javax.sound.sampled.UnsupportedAudioFileException; @@ -38,8 +36,6 @@ import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.SwingConstants; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import com.centerkey.utils.BareBonesBrowserLaunch; import com.mpcmaid.pgm.Profile; @@ -50,8 +46,14 @@ * * @author cyrille martraire */ +@SuppressWarnings("unused") public final class MainFrame extends BaseFrame { + private static final Logger logger = System.getLogger(MainFrame.class.getName()); + + @Serial + private static final long serialVersionUID = 8514219423131647433L; + private static final int FRAME_WIDTH = 900; private static final int FRAME_HEIGHT = 520; @@ -66,15 +68,15 @@ public final class MainFrame extends BaseFrame { private static final Font MEDIUM_FONT = new Font("Verdana", Font.PLAIN, 10); - protected int selectedPad = 0; + private final int selectedPad = 0; private final Program program; private File pgmFile; - protected ProgramPanel programEditor; + private ProgramPanel programEditor; - protected JPanel audioEditor; + private JPanel audioEditor; public MainFrame() { this(untitledProgram()); @@ -116,10 +118,9 @@ public Program getProgram() { return program; } - private final static Program untitledProgram() { + private static Program untitledProgram() { final InputStream resourceStream = Program.class.getResourceAsStream(UNTITLED_TEMPLATE); - final Program untitled = Program.open(resourceStream); - return untitled; + return Program.open(resourceStream); } protected void addMenus(JMenuBar mainMenuBar) { @@ -128,48 +129,22 @@ protected void addMenus(JMenuBar mainMenuBar) { final JMenuItem removeSamples = new JMenuItem("Remove all samples"); editMenu.add(removeSamples); - removeSamples.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - programEditor.removeAllSamples(); - } - - }); + removeSamples.addActionListener(e -> programEditor.removeAllSamples()); final JMenuItem setChromatic = new JMenuItem("Set Chromatic Note Layout"); editMenu.add(setChromatic); - setChromatic.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - programEditor.setChromatic(); - } - - }); + setChromatic.addActionListener(e -> programEditor.setChromatic()); final JMenuItem batchCreate = new JMenuItem("Batch Create Programs"); editMenu.add(batchCreate); - batchCreate.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - batchCreate(); - - } - - }); + batchCreate.addActionListener(e -> batchCreate()); final JMenuItem copyPadSettings = new JMenuItem("Copy Settings to All Pads"); editMenu.add(copyPadSettings); - copyPadSettings.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - copySettingsToAllPads(); - - } - - }); + copyPadSettings.addActionListener(e -> copySettingsToAllPads()); } @@ -179,32 +154,18 @@ protected void makeGUI() { public void newWindow() { final MainFrame newFrame = new MainFrame(); - newFrame.show(); + newFrame.setVisible(true); } public void open() { - final FileDialog openDialog = new FileDialog(this); - openDialog.setDirectory(Preferences.getInstance().getOpenPath()); - openDialog.setMode(FileDialog.LOAD); - openDialog.setFilenameFilter(new FilenameFilter() { - public boolean accept(File dir, String name) { - String[] supportedFiles = { "PGM", "pgm" }; - for (int i = 0; i < supportedFiles.length; i++) { - if (name.endsWith(supportedFiles[i])) { - return true; - } - } - return false; - } - }); - openDialog.setVisible(true); + final FileDialog openDialog = getDialog(Preferences.getInstance().getOpenPath(), FileDialog.LOAD); Preferences.getInstance().setOpenPath(openDialog.getDirectory()); if (openDialog.getDirectory() != null && openDialog.getFile() != null) { String filePath = openDialog.getDirectory() + openDialog.getFile(); - System.out.println(filePath); + logger.log(Level.INFO, filePath); final File pgmFile = new File(filePath); final MainFrame newFrame = new MainFrame(pgmFile); - newFrame.show(); + newFrame.setVisible(true); } } @@ -217,21 +178,7 @@ public void save() { } public void saveAs() { - final FileDialog saveDialog = new FileDialog(this); - saveDialog.setDirectory(Preferences.getInstance().getSavePath()); - saveDialog.setMode(FileDialog.SAVE); - saveDialog.setFilenameFilter(new FilenameFilter() { - public boolean accept(File dir, String name) { - String[] supportedFiles = { "PGM", "pgm" }; - for (int i = 0; i < supportedFiles.length; i++) { - if (name.endsWith(supportedFiles[i])) { - return true; - } - } - return false; - } - }); - saveDialog.setVisible(true); + final FileDialog saveDialog = getDialog(Preferences.getInstance().getSavePath(), FileDialog.SAVE); Preferences.getInstance().setSavePath(saveDialog.getDirectory()); String filename = saveDialog.getFile(); if (saveDialog.getDirectory() != null && filename != null) { @@ -239,13 +186,30 @@ public boolean accept(File dir, String name) { filename += ".PGM"; } String filePath = saveDialog.getDirectory() + filename; - System.out.println(filePath); + logger.log(Level.INFO, filePath); final File file = new File(filePath); setPgmFile(file); program.save(pgmFile); } } + private FileDialog getDialog(String SavePath, int save) { + final FileDialog saveDialog = new FileDialog(this); + saveDialog.setDirectory(SavePath); + saveDialog.setMode(save); + saveDialog.setFilenameFilter((dir, name) -> { + String[] supportedFiles = {"PGM", "pgm"}; + for (String supportedFile : supportedFiles) { + if (name.endsWith(supportedFile)) { + return true; + } + } + return false; + }); + saveDialog.setVisible(true); + return saveDialog; + } + public void export() { final JFileChooser saveDialog = new JFileChooser(Preferences.getInstance().getSavePath()); saveDialog.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); @@ -260,24 +224,22 @@ public void export() { return; } if (!dir.exists()) { - dir.mkdir(); + dir.mkdir(); //FIXME } Preferences.getInstance().setSavePath(dir.getAbsolutePath()); - if (dir != null) { - // save PGM file to the directory with the same name - final File pgmExportFile = new File(dir, dir.getName() + ".PGM"); - System.out.println(pgmExportFile); - setPgmFile(pgmExportFile); - program.save(pgmFile); + // save PGM file to the directory with the same name + final File pgmExportFile = new File(dir, dir.getName() + ".PGM"); + logger.log(Level.INFO, pgmExportFile); + setPgmFile(pgmExportFile); + program.save(pgmFile); - // save each sample - programEditor.exportSamples(dir); - } - } + // save each sample + programEditor.exportSamples(dir); + } - protected void batchCreate() { + private void batchCreate() { final JFileChooser batchDialog = new JFileChooser(Preferences.getInstance().getSavePath()); batchDialog.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); @@ -291,29 +253,19 @@ protected void batchCreate() { try { programEditor.batchCreate(dir); } catch (Exception e) { - e.printStackTrace();// error occurred + logger.log(Level.ERROR, e::getMessage, e);// error occurred } } } - protected void copySettingsToAllPads() { + private void copySettingsToAllPads() { programEditor.copySettingsToAllPads(); } - public boolean quit() { - return super.quit(); - } - - protected void checkOnClose() { - } - - public void help() { + public void help() { BareBonesBrowserLaunch.openURL(HELP_URL); } - public void loadFile(String path) { - } - public void makeAboutDialog() { // set up a simple about box aboutBox = new JDialog(this, "About MPCMaid"); @@ -323,7 +275,7 @@ public void makeAboutDialog() { try { final JLabel imageLabel = new JLabel(); - final BufferedImage currentImage = ImageIO.read(getClass().getResourceAsStream("mpcmaidlogo400_400.png")); + final BufferedImage currentImage = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("mpcmaidlogo400_400.png"))); //FIXME imageLabel.setHorizontalAlignment(SwingConstants.CENTER); imageLabel.setVerticalAlignment(SwingConstants.CENTER); imageLabel.setOpaque(true); @@ -335,11 +287,11 @@ public void makeAboutDialog() { aboutBox.getContentPane().add(imageLabel, BorderLayout.NORTH); } catch (IOException e) { - e.printStackTrace(); + logger.log(Level.ERROR, e::getMessage,e); } // aboutBox.getContentPane().add(new JLabel("MPCMaid", JLabel.CENTER)); - final JLabel notice = new JLabel("\u00A92009 Cyrille Martraire (cyrille.martraire.com)", JLabel.CENTER); + final JLabel notice = new JLabel("©2009 Cyrille Martraire (cyrille.martraire.com)", JLabel.CENTER); // notice.setPreferredSize(new Dimension(400, 25)); // aboutBox.getContentPane().add(notice, BorderLayout.CENTER); @@ -368,43 +320,35 @@ public void makePrefsDialog() { // profile selection final JLabel profileLabel = new JLabel("MPC Profile (not effective for current windows)", JLabel.RIGHT); - final JComboBox profileCombo = new JComboBox( - new String[] { Profile.MPC1000.getName(), Profile.MPC500.getName() }); + final JComboBox profileCombo = new JComboBox<>( + new String[] { Profile.MPC1000.name(), Profile.MPC500.name() }); profileCombo.setEditable(false); final Preferences preferences = Preferences.getInstance(); - final String currentProfile = preferences.getProfile().getName(); + final String currentProfile = preferences.getProfile().name(); profileCombo.setSelectedItem(currentProfile); profileCombo.setAlignmentX(RIGHT_ALIGNMENT); panel.add(profileLabel); panel.add(profileCombo); - profileCombo.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - final String profileName = (String) profileCombo.getSelectedItem(); - final Profile profile = Profile.getProfile(profileName); - preferences.setProfile(profile); - } - - }); + profileCombo.addActionListener(e -> { + final String profileName = (String) profileCombo.getSelectedItem(); + final Profile profile = Profile.getProfile(profileName); + preferences.setProfile(profile); + }); // audition mode final JLabel auditionLabel = new JLabel( "Audition mode(select which sample to play when pressing a pad)", JLabel.RIGHT); - final JComboBox auditionCombo = new JComboBox(ProgramSamples.AUDITION_MODES); + final JComboBox auditionCombo = new JComboBox<>(ProgramSamples.AUDITION_MODES); auditionCombo.setEditable(false); final int currentAudition = preferences.getAuditionSamples(); auditionCombo.setSelectedIndex(currentAudition); auditionCombo.setAlignmentX(RIGHT_ALIGNMENT); panel.add(auditionLabel); panel.add(auditionCombo); - auditionCombo.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - final int audition = auditionCombo.getSelectedIndex(); - preferences.setAuditionSamples(audition); - } - - }); + auditionCombo.addActionListener(e -> { + final int audition = auditionCombo.getSelectedIndex(); + preferences.setAuditionSamples(audition); + }); // contentPane.add(new JLabel("MPC Maid Preferences", JLabel.CENTER), // BorderLayout.NORTH); @@ -441,18 +385,14 @@ private void makeMain() { audioEditor.add(waveformePanel, BorderLayout.CENTER); final JSlider sensitivitySlider = new JSlider(JSlider.VERTICAL, 50, 200, 130); - sensitivitySlider.addChangeListener(new ChangeListener() { - - public void stateChanged(ChangeEvent e) { - final JSlider source = (JSlider) e.getSource(); - if (waveformePanel.isReady() && !source.getValueIsAdjusting()) { - final int sensitivity = source.getValue(); - waveformePanel.setSensitivity(sensitivity); - } - - } - - }); + sensitivitySlider.addChangeListener(e -> { + final JSlider source = (JSlider) e.getSource(); + if (waveformePanel.isReady() && !source.getValueIsAdjusting()) { + final int sensitivity = source.getValue(); + waveformePanel.setSensitivity(sensitivity); + } + + }); audioEditor.add(sensitivitySlider, BorderLayout.EAST); sensitivitySlider.setPreferredSize(new Dimension(25, 40)); sensitivitySlider.setPaintTicks(true); @@ -481,34 +421,33 @@ public void stateChanged(ChangeEvent e) { final JButton exportSlicesButton = new JButton("Export"); exportZone.add(exportSlicesButton); exportSlicesButton.setFocusable(false); - exportSlicesButton.enable(false); - exportSlicesButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - try { - if (waveformePanel.isReady()) { - waveformePanel.export(exportPrefix.getText()); - } - } catch (IOException io) { - JOptionPane.showMessageDialog(waveformePanel, io.getMessage(), "Error saving file", - JOptionPane.ERROR_MESSAGE); - } catch (Exception e1) { - e1.printStackTrace(); - } - } - - }); + exportSlicesButton.setEnabled(false); + exportSlicesButton.addActionListener(e -> { + try { + if (waveformePanel.isReady()) { + waveformePanel.export(exportPrefix.getText()); + } + } catch (IOException io) { + JOptionPane.showMessageDialog(waveformePanel, io.getMessage(), "Error saving file", + JOptionPane.ERROR_MESSAGE); + } catch (Exception e1) { + logger.log(Level.ERROR, e1::getMessage, e1); + } + }); audioEditor.add(bottom, BorderLayout.SOUTH); waveformePanel.setTransferHandler(new FileDragHandler() { + @Serial + private static final long serialVersionUID = -4822099780010064290L; + protected void process(File file) { try { waveformePanel.setAudioFile(file); final String name = file.getName(); exportPrefix.setText(WaveformPanel.prefixProposal(file.getName(), FILE_MAX_LENGTH - 2)); fileLabel.setText(waveformePanel.getFileDetails()); - exportSlicesButton.enable(waveformePanel.hasBeat()); + exportSlicesButton.setEnabled(waveformePanel.hasBeat()); audioEditor.repaint(); } catch (IllegalArgumentException e) { JOptionPane.showMessageDialog(waveformePanel, e.getMessage(), "Unsupported file", @@ -517,7 +456,7 @@ protected void process(File file) { JOptionPane.showMessageDialog(waveformePanel, "The file format is not supported by the MPC", "Unsupported file", JOptionPane.ERROR_MESSAGE); } catch (Exception e) { - e.printStackTrace(); + logger.log(Level.ERROR, e::getMessage, e); } } @@ -575,7 +514,7 @@ public void keyPressed(KeyEvent ke) { try { waveformePanel.getSelectedSlice().play(); } catch (Throwable e) { - e.printStackTrace(); + logger.log(Level.ERROR, e::getMessage, e); } break; } @@ -615,25 +554,24 @@ public void mousePressed(MouseEvent e) { }); // NUDGE WITH MOUSE WHEEL - waveformePanel.addMouseWheelListener(new MouseWheelListener() { - - public void mouseWheelMoved(MouseWheelEvent e) { - if (!waveformePanel.isReady()) { - return; - } - waveformePanel.nudgeMarker(-100 * e.getWheelRotation()); - final int location = waveformePanel.getSelectedMarkerLocation(); - currentMarkerLocation.setText("Marker location: " + location + " samples"); - } - - }); + waveformePanel.addMouseWheelListener(e -> { + if (!waveformePanel.isReady()) { + return; + } + waveformePanel.nudgeMarker(-100 * e.getWheelRotation()); + final int location = waveformePanel.getSelectedMarkerLocation(); + currentMarkerLocation.setText("Marker location: " + location + " samples"); + }); // SUPPORT DROP PGM FILES main.setTransferHandler(new FileDragHandler() { + @Serial + private static final long serialVersionUID = 712227010818715230L; + protected void process(File file) { final MainFrame newFrame = new MainFrame(file); - newFrame.show(); + newFrame.setVisible(true); } }); diff --git a/MpcMaid/src/com/mpcmaid/gui/PadListener.java b/MpcMaid/src/main/java/com/mpcmaid/gui/PadListener.java old mode 100755 new mode 100644 similarity index 83% rename from MpcMaid/src/com/mpcmaid/gui/PadListener.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/PadListener.java index 596ef94..00d033f --- a/MpcMaid/src/com/mpcmaid/gui/PadListener.java +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/PadListener.java @@ -4,6 +4,7 @@ import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; +import java.io.Serial; /** * The listener for each pad button @@ -12,6 +13,9 @@ */ public class PadListener extends FileDragHandler implements ActionListener, FocusListener { + @Serial + private static final long serialVersionUID = 8106993173333818375L; + public void actionPerformed(ActionEvent arg0) { } diff --git a/MpcMaid/src/com/mpcmaid/gui/Preferences.java b/MpcMaid/src/main/java/com/mpcmaid/gui/Preferences.java old mode 100755 new mode 100644 similarity index 79% rename from MpcMaid/src/com/mpcmaid/gui/Preferences.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/Preferences.java index 4aae6f8..e31939b --- a/MpcMaid/src/com/mpcmaid/gui/Preferences.java +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/Preferences.java @@ -1,11 +1,12 @@ package com.mpcmaid.gui; +import com.mpcmaid.pgm.Profile; + import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; +import java.nio.file.Files; import java.util.Properties; - -import com.mpcmaid.pgm.Profile; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; /** * Application-scope settings @@ -16,11 +17,13 @@ */ public final class Preferences { + private static final Logger logger = System.getLogger(Preferences.class.getName()); + private static final String MPCMAID_SETTINGS_DIR = "mpcmaid"; private final static Preferences INSTANCE = new Preferences(); - public final static Preferences getInstance() { + public static Preferences getInstance() { return INSTANCE; } @@ -77,7 +80,7 @@ public void setAuditionSamples(int auditionSamples) { save(); } - public static final boolean isMacOsX() { + public static boolean isMacOsX() { return System.getProperty("mrj.version") != null; } @@ -88,59 +91,59 @@ private static File getUserPreferencesDirectory() { return new File(System.getProperty("user.home")); } - private final static File getSettingsDirectory() { + private static File getSettingsDirectory() { final File home = getUserPreferencesDirectory(); final File settingsDirectory = new File(home, MPCMAID_SETTINGS_DIR); if (!settingsDirectory.exists()) { if (!settingsDirectory.mkdir()) { - throw new IllegalStateException("Could not create settings directory!\n" + settingsDirectory.toString()); + throw new IllegalStateException("Could not create settings directory: " + settingsDirectory); } } return settingsDirectory; } - private final static Properties getProperties() { + private static Properties getProperties() { Properties properties = new Properties(); final File home = getSettingsDirectory(); final File file = new File(home, "mpcmaid.properties"); try { file.createNewFile(); - properties.load(new FileInputStream(file)); + properties.load(Files.newInputStream(file.toPath())); } catch (Exception e) { - e.printStackTrace(); + logger.log(Level.ERROR, e::getMessage, e); //FIXME return null; } return properties; } - public final void load() { + public void load() { final Properties properties = getProperties(); if (properties == null) { return; } final String home = System.getProperty("user.home"); - this.profile = Profile.getProfile(properties.getProperty("profile", Profile.MPC1000.getName())); + this.profile = Profile.getProfile(properties.getProperty("profile", Profile.MPC1000.name())); this.openPath = properties.getProperty("lastOpenPath", home); this.savePath = properties.getProperty("lastSavePath", home); this.auditionSamples = Integer.parseInt(properties.getProperty("auditionSamples", "1")); } - public final void save() { + public void save() { try { final Properties properties = getProperties(); if (properties == null) { return; } - properties.setProperty("profile", profile.getName()); + properties.setProperty("profile", profile.name()); properties.setProperty("lastOpenPath", openPath); properties.setProperty("lastSavePath", savePath); properties.setProperty("auditionSamples", String.valueOf(auditionSamples)); final File home = getSettingsDirectory(); final File file = new File(home, "mpcmaid.properties"); - properties.store(new FileOutputStream(file), null); - } catch (Exception ignore) { - ignore.printStackTrace(); + properties.store(Files.newOutputStream(file.toPath()), null); + } catch (Exception e) { + logger.log(Level.ERROR, e::getMessage, e); } } } diff --git a/MpcMaid/src/com/mpcmaid/gui/ProgramPanel.java b/MpcMaid/src/main/java/com/mpcmaid/gui/ProgramPanel.java old mode 100755 new mode 100644 similarity index 77% rename from MpcMaid/src/com/mpcmaid/gui/ProgramPanel.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/ProgramPanel.java index 4d3378e..748a659 --- a/MpcMaid/src/com/mpcmaid/gui/ProgramPanel.java +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/ProgramPanel.java @@ -7,19 +7,15 @@ import java.awt.Font; import java.awt.GridLayout; import java.awt.LayoutManager; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.FocusEvent; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; +import java.awt.event.*; import java.io.File; +import java.io.Serial; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.Iterator; import java.util.List; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; import javax.swing.AbstractAction; import javax.swing.BoxLayout; @@ -52,8 +48,14 @@ * * @author cyrille martraire */ +@SuppressWarnings("unused") public class ProgramPanel extends JPanel implements BindingCapable { + private static final Logger logger = System.getLogger(ProgramPanel.class.getName()); + + @Serial + private static final long serialVersionUID = -2447341386033109052L; + private static final String[] ASSIGN_CHOICES2 = { "Cancel", "Sample", "Pad", "Multisample" }; private static final String[] ASSIGN_CHOICES1 = { "Cancel", "Sample", "Pad" }; @@ -66,9 +68,7 @@ public class ProgramPanel extends JPanel implements BindingCapable { protected final Profile profile; - private final File pgmFile; - - private final Program pgm; + private final Program pgm; private final JButton[] padButtons = new JButton[64]; @@ -83,9 +83,8 @@ public class ProgramPanel extends JPanel implements BindingCapable { public ProgramPanel(Program program, Profile profile, File pgmFile) { this.pgm = program; this.profile = profile; - this.pgmFile = pgmFile; - this.samples = new ProgramSamples(); + this.samples = new ProgramSamples(); this.samples.set(program, pgmFile == null ? null : pgmFile.getParentFile()); make(); } @@ -119,8 +118,8 @@ protected void make() { final JTabbedPane banks = new JTabbedPane(); banks.setPreferredSize(new Dimension(430, 410)); final int bankNumber = 4; - final int colNumber = profile.getColNumber(); - final int rowNumber = profile.getRowNumber(); + final int colNumber = profile.colNumber(); + final int rowNumber = profile.rowNumber(); final int bankSize = profile.getPadNumber(); for (int k = 0; k < bankNumber; k++) { final JPanel pads = new JPanel(new GridLayout(rowNumber, colNumber, 10, 10)); @@ -141,6 +140,9 @@ protected void make() { final PadListener listener = new PadListener() { + @Serial + private static final long serialVersionUID = 1865046902781631523L; + public void actionPerformed(ActionEvent arg0) { samples.play(selectedPad); } @@ -149,7 +151,7 @@ public void focusGained(FocusEvent e) { selectPad(selectedPad, padId, button); } - protected void process(List files) { + protected void process(List files) { selectPad(selectedPad, padId, button); assignSounds(selectedPad, files); load(); @@ -163,6 +165,9 @@ protected void process(List files) { final JPopupMenu popup = new JPopupMenu(); final JMenuItem copyActionItem = new JMenuItem(new AbstractAction("Copy pad parameters") { + @Serial + private static final long serialVersionUID = 1182625432047482131L; + public void actionPerformed(ActionEvent arg0) { selectPad(selectedPad, padId, button); copySettings(); @@ -171,10 +176,13 @@ public void actionPerformed(ActionEvent arg0) { }); copyActionItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_C, ActionEvent.CTRL_MASK)); + KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK)); popup.add(copyActionItem); final JMenuItem pasteActionItem = new JMenuItem(new AbstractAction("Paste pad parameters") { + @Serial + private static final long serialVersionUID = 7323561055754542910L; + public void actionPerformed(ActionEvent e) { selectPad(selectedPad, padId, button); pasteSettings(); @@ -182,7 +190,7 @@ public void actionPerformed(ActionEvent e) { }); pasteActionItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_V, ActionEvent.CTRL_MASK)); + KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK)); popup.add(pasteActionItem); button.addMouseListener(new MouseAdapter() { @@ -224,7 +232,7 @@ public void keyTyped(KeyEvent e) { } } final char ch = (char) ('A' + k); - banks.addTab(" " + String.valueOf(ch) + " ", pads); + banks.addTab(" " + ch + " ", pads); } final JButton lastSelected = padButtons[0]; lastSelected.setSelected(true); @@ -247,16 +255,15 @@ private void refreshPadButton(final Pad pad) { } } - public void assignSounds(Pad pad, List files) { + public void assignSounds(Pad pad, List files) { if (files.size() < 2) { doAssignSamples(pad, files, false); return; } - final String[] choices = ASSIGN_CHOICES2; - int response = JOptionPane.showOptionDialog(this, + int response = JOptionPane.showOptionDialog(this, "Each dropped file will be assigned to a pad or sample layer. ", "Assign samples to locations", - JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, choices, "Pad"); + JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, ASSIGN_CHOICES2, "Pad"); switch (response) { case 0: { return; @@ -284,9 +291,9 @@ public void assignSounds(Pad pad, List files) { } } - private void doMultisample(List files) { + private void doMultisample(List files) { final MultiSampleCommand command = new MultiSampleCommand(Sample.RENAMED, files, pgm); - final List impactedPads = (List) command.execute(samples); + final List impactedPads = (List) command.execute(samples); refreshImpactedPads(impactedPads); @@ -297,9 +304,9 @@ private void doMultisample(List files) { } - private void doAssignSamples(Pad pad, List files, final boolean perPad) { + private void doAssignSamples(Pad pad, List files, final boolean perPad) { final SimpleAssignCommand command = new SimpleAssignCommand(Sample.RENAMED, files, pad, perPad); - final Collection impactedPads = (Collection) command.execute(samples); + final Collection impactedPads = command.execute(samples); refreshImpactedPads(impactedPads); @@ -316,11 +323,10 @@ public void batchCreate(File path) { JOptionPane.showMessageDialog(this, msg); } - private void refreshImpactedPads(final Collection impactedPads) { - Iterator it = impactedPads.iterator(); - while (it.hasNext()) { - refreshPadButton((Pad) it.next()); - } + private void refreshImpactedPads(final Collection impactedPads) { + for (Pad impactedPad : impactedPads) { + refreshPadButton(impactedPad); + } } /** @@ -335,12 +341,12 @@ public void copySettings() { */ public void pasteSettings() { if (padToCopy != null) { - final HashSet ignoreParams = new HashSet(); + final HashSet ignoreParams = new HashSet<>(); ignoreParams.add(Pad.PAD_MIDI_NOTE_VALUE); ignoreParams.add(Layer.TUNING); currentlySelectedPad.copyFrom(padToCopy, ignoreParams); // copy samples within the sample matrix - for (int j = 0; j < padToCopy.getLayerNumber(); j++) { + for (int j = 0; j < Pad.LAYER_NUMBER; j++) { Layer layer = padToCopy.getLayer(j); samples.set(currentlySelectedPad.getLayer(j), samples.get(layer)); } @@ -359,19 +365,19 @@ public void copySettingsToAllPads() { return; } try { - final HashSet ignoreParams = new HashSet(); + final HashSet ignoreParams = new HashSet<>(); ignoreParams.add(Pad.PAD_MIDI_NOTE_VALUE); ignoreParams.add(Layer.SAMPLE_NAME); ignoreParams.add(Layer.TUNING); - final Collection impactedPads = new ArrayList(); + final Collection impactedPads = new ArrayList<>(); for (int i = 0; i < 4 * profile.getPadNumber(); i++) { final Pad pad = pgm.getPad(i); pad.copyFrom(currentlySelectedPad, ignoreParams); } refreshImpactedPads(impactedPads); } catch (Exception e) { - e.printStackTrace();// error occurred + logger.log(Level.ERROR, e::getMessage, e);// error occurred } } @@ -384,29 +390,28 @@ private void selectPad(final Pad selectedPad, final int padId, final JButton but currentlySelectedPad = selectedPad;// remember currently selected pad button.setSelected(true); - // System.out.println("Pad " + padId + " pressed!"); + logger.log(Level.TRACE,"Pad " + padId + " pressed!"); refreshParamsArea(); } private void refreshParamsArea() { final Component[] widgets = params.getComponents(); - for (int i = 0; i < widgets.length; i++) { - if (widgets[i] instanceof BindingCapable) { - BindingCapable component = (BindingCapable) widgets[i]; - component.load(); - } - } + for (Component widget : widgets) { + if (widget instanceof BindingCapable component) { + component.load(); + } + } } public void removeAllSamples() { - final Collection impactedPads = samples.removeAllSamples(pgm); + final Collection impactedPads = samples.removeAllSamples(pgm); refreshImpactedPads(impactedPads); // selectPad(selectedPad, padId, button); } public void setChromatic() { - final Collection impactedPads = new ArrayList(); + final Collection impactedPads = new ArrayList<>(); final int padNumber = pgm.getPadNumber(); for (int i = 0; i < padNumber; i++) { final Pad pad = pgm.getPad(i); @@ -425,9 +430,9 @@ public void exportSamples(File dir) { } } - private final static String htmlSamples(Pad padElement) { - final StringBuffer out = new StringBuffer(""); - for (int i = 0; i < padElement.getLayerNumber(); i++) { + private static String htmlSamples(Pad padElement) { + final StringBuilder out = new StringBuilder(""); + for (int i = 0; i < Pad.LAYER_NUMBER; i++) { final Layer sample = padElement.getLayer(i); final String sampleName = shorten(sample.getSampleName()); if (i > 0) { @@ -450,7 +455,7 @@ private JTabbedPane makeSlidersArea() { final JTabbedPane sliders = new JTabbedPane(); sliders.setFont(SMALL_FONT); sliders.setPreferredSize(new Dimension(200, 400)); - for (int i = 0; i < profile.getSliderNumber(); i++) { + for (int i = 0; i < profile.sliderNumber(); i++) { sliders.addTab("Slider" + (i + 1), makeSliderArea(pgm, i)); } return sliders; @@ -460,6 +465,9 @@ private Component makeSliderArea(Program pgm, int i) { final Slider slider = pgm.getSlider(i); final WidgetPanel area = new WidgetPanel(slider) { + @Serial + private static final long serialVersionUID = -5428368980591121800L; + public void make() { add(new JLabel("")); super.make(); @@ -484,14 +492,19 @@ protected void makeOffIntParameter(Parameter parameter) { /** * @return A Component that is also BindingCapable - * * When we select another pad, call the setElement() method to * update the view */ private Component makePadArea(Element element) { - final WidgetPanel area = new WidgetPanel(element) { + + //noinspection EmptyMethod + final WidgetPanel area = new WidgetPanel(element) { + + @Serial + private static final long serialVersionUID = -1482444822047248775L; public void make() { + // We may need this in the future, or the past :) // add(new JLabel("")); super.make(); } @@ -503,22 +516,23 @@ public void make() { /** * @return A Component that is also BindingCapable - * * Make the Widget panel and keep a reference to it in a collection * so that we can collectively call setElement(), load() and save() * on them - * + *

* When we select another pad, call the setElement() method to * update the view */ private Component makeSampleArea(final Pad pad) { - final int samplesNb = pad.getLayerNumber(); final SamplePanel layersArea = new SamplePanel(pad, new GridLayout(2, 2, 10, 10)); - for (int i = 0; i < samplesNb && i < 4; i++) { + for (int i = 0; i < Pad.LAYER_NUMBER; i++) { final Layer layer = pad.getLayer(i); final int layerIndex = i; final WidgetPanel area = new WidgetPanel(layer) { + @Serial + private static final long serialVersionUID = -5678698667326900109L; + public void make() { final String layerLabel = "Sample Layer " + (layerIndex + 1); final JLabel title = new JLabel(layerLabel, JLabel.CENTER); @@ -528,27 +542,23 @@ public void make() { super.makeParameters(); // play/remove buttons - final JPanel layerButtons = new JPanel(new FlowLayout(2, 0, 0)); + final JPanel layerButtons = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0)); final JButton playButton = new JButton("Play"); playButton.setFont(MEDIUM_FONT); layerButtons.add(playButton); final JButton removeButton = new JButton("Clear"); removeButton.setFont(MEDIUM_FONT); layerButtons.add(removeButton); - final ActionListener actionListener = new ActionListener() { - - public void actionPerformed(ActionEvent e) { - final Object source = e.getSource(); - if (source == playButton) { - samples.play(layer); - } else if (source == removeButton) { - samples.remove(layer); - refreshPadButton(pad); - load(); - } - } - - }; + final ActionListener actionListener = e -> { + final Object source = e.getSource(); + if (source == playButton) { + samples.play(layer); + } else if (source == removeButton) { + samples.remove(layer); + refreshPadButton(pad); + load(); + } + }; playButton.addActionListener(actionListener); removeButton.addActionListener(actionListener); add(layerButtons); @@ -570,26 +580,24 @@ public void makeDecimalParameter(Parameter parameter) { public void load() { final Component[] widgets = params.getComponents(); - for (int i = 0; i < widgets.length; i++) { - if (widgets[i] instanceof BindingCapable) { - BindingCapable component = (BindingCapable) widgets[i]; - component.load(); + for (Component widget : widgets) { + if (widget instanceof BindingCapable component) { + component.load(); - } - } + } + } } public void save() { final Component[] widgets = params.getComponents(); - for (int i = 0; i < widgets.length; i++) { - WidgetPanel component = (WidgetPanel) widgets[i]; - component.save(); - } + for (Component widget : widgets) { + WidgetPanel component = (WidgetPanel) widget; + component.save(); + } } /** * @return A Component that is also BindingCapable - * * When we select another pad, call the setElement() method to * update the view */ @@ -597,16 +605,16 @@ private Component makeFiltersArea(Pad pad) { final JTabbedPane sliders = new JTabbedPane(); sliders.setFont(SMALL_FONT); sliders.setPreferredSize(new Dimension(200, 400)); - for (int i = 0; i < profile.getFilterNumber(); i++) { + for (int i = 0; i < profile.filterNumber(); i++) { sliders.addTab("Filter" + (i + 1), makePadArea(pad.getFilter(i))); } return sliders; } - public final static String[] offPads(OffIntType type, int padNumber) { + public static String[] offPads(OffIntType type, int padNumber) { final Range range = type.getRange(); - final String[] values = new String[range.getHigh() - range.getLow() + 1]; + final String[] values = new String[range.high() - range.low() + 1]; for (int i = 0; i < values.length; i++) { int j = i - 1; values[i] = i == 0 ? "Off" : "Pad " + ((char) ('A' + (j / padNumber))) + ((j % padNumber) + 1); @@ -621,7 +629,7 @@ public String toString() { /** * Panel to contain the four widgets (one for each sample layer) for the * selected pad, which is why it is also BindingCapable - * + *

* When we select another pad, call the setElement() method to update the * view * @@ -629,27 +637,30 @@ public String toString() { */ protected static final class SamplePanel extends JPanel implements BindingCapable { - private Pad pad; + @Serial + private static final long serialVersionUID = 2008068001960565405L; - protected SamplePanel(Pad pad, LayoutManager arg0) { + private final Pad pad; + + private SamplePanel(Pad pad, LayoutManager arg0) { super(arg0); this.pad = pad; } public void load() { final Component[] widgets = getComponents(); - for (int i = 0; i < widgets.length; i++) { - BindingCapable component = (BindingCapable) widgets[i]; - component.load(); - } + for (Component widget : widgets) { + BindingCapable component = (BindingCapable) widget; + component.load(); + } } public void save() { final Component[] widgets = getComponents(); - for (int i = 0; i < widgets.length; i++) { - WidgetPanel component = (WidgetPanel) widgets[i]; - component.save(); - } + for (Component widget : widgets) { + WidgetPanel component = (WidgetPanel) widget; + component.save(); + } } public Element getElement() { diff --git a/MpcMaid/src/com/mpcmaid/gui/ProgramSamples.java b/MpcMaid/src/main/java/com/mpcmaid/gui/ProgramSamples.java old mode 100755 new mode 100644 similarity index 81% rename from MpcMaid/src/com/mpcmaid/gui/ProgramSamples.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/ProgramSamples.java index f2aed81..d2fc360 --- a/MpcMaid/src/com/mpcmaid/gui/ProgramSamples.java +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/ProgramSamples.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; import com.mpcmaid.pgm.Layer; import com.mpcmaid.pgm.Pad; @@ -18,6 +20,8 @@ */ public class ProgramSamples extends SampleMatrix { + private static final Logger logger = System.getLogger(ProgramSamples.class.getName()); + private File path; public final static String[] AUDITION_MODES = { "Play only first available sample", "Do not audition samples", @@ -51,7 +55,7 @@ public void set(final Program program, File programFile) { } public void set(final Pad pad) { - final int layerNumber = pad.getLayerNumber(); + final int layerNumber = Pad.LAYER_NUMBER; for (int i = 0; i < layerNumber; i++) { set(pad.getLayer(i)); } @@ -59,7 +63,7 @@ public void set(final Pad pad) { public void set(final Layer layer) { final String sampleName = layer.getSampleName(); - if (sampleName.trim().length() == 0) { + if (sampleName.trim().isEmpty()) { remove(layer); return; } @@ -80,14 +84,11 @@ public void play(Pad pad) { return;// do not audition } if (auditionSamples == 0) { - final int layerNumber = pad.getLayerNumber(); - for (int i = 0; i < layerNumber; i++) { + for (int i = 0; i < Pad.LAYER_NUMBER; i++) { final Layer layer = pad.getLayer(i); - if (get(layer) != null) { - play(layer); - if (auditionSamples == 0) { - return;// play only first available - } + if (this.get(layer) != null) { + this.play(layer); + return;// play only first available // 0 play each in sequence: cannot do yet } } @@ -106,7 +107,7 @@ public void play(final Layer layer) { } sample.play(); } catch (Exception e) { - e.printStackTrace(); + logger.log(Level.ERROR, e::getMessage, e); } } @@ -115,12 +116,12 @@ public void remove(final Layer layer) { set(layer, null); } - public Collection removeAllSamples(Program program) { - final List impactedPads = new ArrayList(); + public Collection removeAllSamples(Program program) { + final List impactedPads = new ArrayList<>(); final int n = program.getPadNumber(); for (int i = 0; i < n; i++) { final Pad pad = program.getPad(i); - final int m = pad.getLayerNumber(); + final int m = Pad.LAYER_NUMBER; for (int j = 0; j < m; j++) { final Layer layer = pad.getLayer(j); remove(layer); diff --git a/MpcMaid/src/main/java/com/mpcmaid/gui/Utils.java b/MpcMaid/src/main/java/com/mpcmaid/gui/Utils.java new file mode 100644 index 0000000..8833703 --- /dev/null +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/Utils.java @@ -0,0 +1,143 @@ +package com.mpcmaid.gui; + +import javax.sound.sampled.*; +import java.io.*; +import java.nio.file.Files; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; + +public class Utils { + + private static final Logger logger = System.getLogger(Utils.class.getName()); + + public static final String EXTENSION = ".WAV"; + + /** + * @return true if the given file has the expected extension + */ + public static boolean hasCorrectExtension(final File file) { + return file.getName().toUpperCase().endsWith(EXTENSION); + } + + public static String noExtension(final File file) { + return noExtension(file.getName()); + } + + /** + * @return The given name without its extension (the term after the last dot) + */ + public static String noExtension(final String name) { + final int indexOf = name.lastIndexOf('.'); + if (indexOf != -1) { + return name.substring(0, indexOf); + } + return name; + } + + /** + * Shorten the name if it is too long, then ensure its unicity thanks to a + * postfix incremental number + */ + public static String escapeName(final String name, final int length, final boolean brutal, final int renameCount) { + String escaped = escapeName(name, length, brutal); + if (renameCount != -1 && !escaped.equals(name)) { + if (renameCount > 0) { + final String postfix = String.valueOf(renameCount); + if (escaped.length() + postfix.length() <= length) { + escaped = escaped + postfix; + } else { + escaped = escaped.substring(0, length - postfix.length()) + postfix; + } + } + } + return escaped; + } + + /** + * Shorten the name if it is too long, either brutally, or with some trim so + * that it does not end on a space, underscore or dot + */ + public static String escapeName(final String name, final int length, final boolean brutal) { + String s = name; + if (s.length() <= length) { + return s; + } + s = s.substring(0, length).trim(); + if (brutal) { + return s; + } + String s2; + while (true) { + s2 = escapeEnding(s); + if (s.equals(s2)) { + return s.trim(); + } + s = s2; + } + } + + private static String escapeEnding(final String s) { + if (s.endsWith(".")) { + return s.substring(0, s.length() - 1); + } + if (s.endsWith(" ")) { + return s.substring(0, s.length() - 1); + } + if (s.endsWith("_")) { + return s.substring(0, s.length() - 1); + } + return s; + } + + // File utils + public static void copy(final File src, final File dst) throws IOException { + final InputStream in = Files.newInputStream(src.toPath()); + final OutputStream out = Files.newOutputStream(dst.toPath()); + + // Transfer bytes from in to out + final byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + in.close(); + out.close(); + } + + public String toString() { + return "Utils: "; + } + + /** + * Donwsamples a sample to fit the 16 bits, 44.1kHz requirements of the MPC. In + * Jave, this means 44100, pcm_s16le or pcm_u8 + * + * @param src the source file to convert + * @param dst the destination file to write + */ + public static void resample(final File src, final File dst) throws IOException { + try (FileInputStream in = new FileInputStream(src); BufferedInputStream bis = new BufferedInputStream(in)){ + AudioInputStream ais = AudioSystem.getAudioInputStream(bis); + AudioFormat oldFormat = ais.getFormat(); + AudioFormat mpcFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, oldFormat.getChannels(), 2*oldFormat.getChannels(), 44100, false); + if (isWrongFormat(ais)) { + logger.log(Level.INFO, "Need to convert sample "+src.getName()); + AudioInputStream converted = AudioSystem.getAudioInputStream(mpcFormat, ais); + AudioSystem.write(converted, AudioFileFormat.Type.WAVE, dst); + } else { + // no need to convert, we copy + Utils.copy(src, dst); + } + } catch (UnsupportedAudioFileException e) { + // by default, we copy on wrong format error + Utils.copy(src, dst); + throw new IOException("Got unsupported audio file, it was copied without modification !"); + } + } + + /** Returns true if the old format is "less or equal" than the good format, i.e. has lower or equal bit depth and lower or equal samplerate */ + private static boolean isWrongFormat(AudioInputStream stream) { + return stream.getFormat().getSampleRate() > 44100 || stream.getFormat().getSampleSizeInBits() > 16; + } + +} diff --git a/MpcMaid/src/com/mpcmaid/gui/WaveformPanel.java b/MpcMaid/src/main/java/com/mpcmaid/gui/WaveformPanel.java old mode 100755 new mode 100644 similarity index 92% rename from MpcMaid/src/com/mpcmaid/gui/WaveformPanel.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/WaveformPanel.java index 4710b32..0e26f97 --- a/MpcMaid/src/com/mpcmaid/gui/WaveformPanel.java +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/WaveformPanel.java @@ -4,6 +4,7 @@ import java.awt.Graphics; import java.awt.Polygon; import java.io.File; +import java.io.Serial; import java.util.Iterator; import java.util.List; @@ -25,6 +26,9 @@ */ public class WaveformPanel extends JPanel { + @Serial + private static final long serialVersionUID = -1728002082575891020L; + private static final int AVERAGE_ENERGY_WINDOW = 43; private static final int OVERLAP_RATIO = 1; @@ -95,7 +99,7 @@ public void paintComponent(Graphics g) { } private void printWaveform(int[] values, final int channel, Graphics g) { - final int width = (int) (getWidth() - 50); + final int width = getWidth() - 50; final int fullHeight = 180; final int height = fullHeight * 4 / 5; @@ -122,7 +126,7 @@ private void printWaveform(int[] values, final int channel, Graphics g) { int oldX = x0; int oldY = y0; g.setColor(Color.GRAY); - final int increment = (int) (n / (4 * width)); + final int increment = n / (4 * width); for (int t = 0; t < n; t += increment) { final int x = x0 + (int) Math.round(t * xScale); final int y = y0 + (int) Math.round(values[t] * yScale); @@ -131,11 +135,11 @@ private void printWaveform(int[] values, final int channel, Graphics g) { oldY = y; } - Iterator it = markers.getMarkers().iterator(); + Iterator it = markers.getMarkers().iterator(); final int selectedMarkerIndex = markers.getSelectedMarkerIndex(); int markerIndex = 0; while (it.hasNext()) { - Marker marker = (Marker) it.next(); + Marker marker = it.next(); final int location = marker.getLocation(); final int x = x0 + (int) Math.round(location * xScale); @@ -166,7 +170,7 @@ public void selectMarker(final int shift) { public void selectClosestMarker(final int mouseX) { // get the location (in samples) from the mouse position - final int width = (int) (getWidth() - 50); + final int width = getWidth() - 50; final int x0 = 20; final double minX = 0; final double maxX = slicer.getChannels()[0].length; @@ -237,7 +241,7 @@ public float getDuration() { return markers.getDuration(); } - public static final String shortName(String name) { + public static String shortName(String name) { final int indexOf = name.lastIndexOf('.'); if (indexOf != -1) { return name.substring(0, indexOf); @@ -245,7 +249,7 @@ public static final String shortName(String name) { return name; } - public static final String prefixProposal(String name, final int maxLen) { + public static String prefixProposal(String name, final int maxLen) { final int indexOf = name.indexOf('.'); String prefix = name; if (indexOf != -1) { @@ -258,14 +262,14 @@ public static final String prefixProposal(String name, final int maxLen) { public void export(String prefix) throws Exception { final String name = prefixProposal(prefix, 10); final File path = file.getParentFile(); - final List slices = slicer.exportSlices(path, name); + final List slices = slicer.exportSlices(path, name); final File midiFile = new File(path, name + ".mid"); markers.exportMidiSequence(midiFile, MIDI_PPQ); // final File file = new File("chromatic.pgm"); final Program pgm = Program.open(getClass().getResourceAsStream("chromatic.pgm")); for (int i = 0; i < slices.size() && i < 64; i++) { - final File slice = (File) slices.get(i); + final File slice = slices.get(i); final Pad pad = pgm.getPad(i); final String sampleName = shortName(slice.getName()); final com.mpcmaid.pgm.Layer layer0 = pad.getLayer(0); diff --git a/MpcMaid/src/com/mpcmaid/gui/Widget.java b/MpcMaid/src/main/java/com/mpcmaid/gui/Widget.java old mode 100755 new mode 100644 similarity index 76% rename from MpcMaid/src/com/mpcmaid/gui/Widget.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/Widget.java index d19341c..89d8e6b --- a/MpcMaid/src/com/mpcmaid/gui/Widget.java +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/Widget.java @@ -7,8 +7,11 @@ import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; +import java.io.Serial; import java.text.NumberFormat; import java.util.Locale; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import javax.swing.JComboBox; import javax.swing.JComponent; @@ -29,7 +32,12 @@ * * @author cyrille martraire */ -public abstract class Widget extends JPanel implements ActionListener, FocusListener, BindingCapable { +public abstract class Widget extends JPanel implements ActionListener, FocusListener, BindingCapable { + + @Serial + private static final long serialVersionUID = -532729841296280652L; + + private static final Logger logger = System.getLogger(Widget.class.getName()); private static final Font MEDIUM_FONT = new Font("Verdana", Font.PLAIN, 12); @@ -37,18 +45,16 @@ public abstract class Widget extends JPanel implements ActionListener, FocusList protected final Parameter parameter; - protected JComponent value; + protected T value; public Widget(Element element, Parameter parameter) { super(); this.element = element; this.parameter = parameter; - setupLabel(parameter); - - setupValue(); - - setupToolTip(parameter); + this.setupLabel(parameter); + this.setupValue(); + this.setupToolTip(parameter); } public void load() { @@ -99,14 +105,14 @@ public Type getType() { return parameter.getType(); } - public boolean validate(Object o) { - return getType().validate(o); + public boolean notValidate(Object o) { + return !getType().validate(o); } protected void check(final Object o) { - if (!validate(o)) { + if (notValidate(o)) { final String msg = "Invalid " + getLabel() + " value: " + o + "."; - System.err.println(msg); + logger.log(Level.ERROR,msg); // JOptionPane.showMessageDialog(null, msg, "Invalid value", // JOptionPane.ERROR_MESSAGE); onError(); @@ -122,7 +128,10 @@ public String toString() { return "Presentation: " + element + " " + parameter; } - public static class IntegerField extends Widget { + public static class IntegerField extends Widget { + + @Serial + private static final long serialVersionUID = 3709006660547691155L; public IntegerField(Element element, Parameter parameter) { super(element, parameter); @@ -141,7 +150,7 @@ protected void setupValue() { } private JTextField getTextField() { - return (JTextField) value; + return value; } public void load() { @@ -151,7 +160,7 @@ public void load() { public void save() { final String text = getTextField().getText(); - final Integer v = new Integer(text); + final Integer v = Integer.valueOf(text); check(v); element.set(parameter, v); } @@ -162,7 +171,10 @@ public String toString() { } - public static class StringField extends Widget { + public static class StringField extends Widget { + + @Serial + private static final long serialVersionUID = 3200524341632520173L; public StringField(Element element, Parameter parameter) { super(element, parameter); @@ -177,12 +189,12 @@ protected void setupValue() { getTextField().addActionListener(this); getTextField().addFocusListener(this); - getTextField().enable(false); + getTextField().setEnabled(false); load(); } private JTextField getTextField() { - return (JTextField) value; + return value; } public void load() { @@ -201,7 +213,10 @@ public String toString() { } } - public static class RangeField extends Widget { + public static class RangeField extends Widget { + + @Serial + private static final long serialVersionUID = 5633564907524431966L; private JTextField value2; @@ -230,17 +245,17 @@ protected void setupValue() { protected void check(final Object o) { final Range range = (Range) o; - if (!validate(new Integer(range.getLow()))) { - final String msg = "Invalid " + getLabel() + " value: " + range.getLow() + "."; - System.err.println(msg); + if (notValidate(range.low())) { + final String msg = "Invalid " + getLabel() + " value: " + range.low() + "."; + logger.log(Level.ERROR,msg); value.requestFocus(); Toolkit.getDefaultToolkit().beep(); return; } - if (!validate(new Integer(range.getHigh()))) { - final String msg = "Invalid " + getLabel() + " value: " + range.getHigh() + "."; - System.err.println(msg); + if (notValidate(range.high())) { + final String msg = "Invalid " + getLabel() + " value: " + range.high() + "."; + logger.log(Level.ERROR,msg); value2.requestFocus(); Toolkit.getDefaultToolkit().beep(); @@ -261,17 +276,17 @@ public void setupToolTip(Parameter parameter) { } private JTextField getTextField() { - return (JTextField) value; + return value; } private JTextField getTextField2() { - return (JTextField) value2; + return value2; } public void load() { final Range range = (Range) element.get(parameter); - getTextField().setText(String.valueOf(range.getLow())); - getTextField2().setText(String.valueOf(range.getHigh())); + getTextField().setText(String.valueOf(range.low())); + getTextField2().setText(String.valueOf(range.high())); } public void save() { @@ -284,7 +299,10 @@ public void save() { } - public static class ComboField extends Widget { + public static class ComboField extends Widget> { + + @Serial + private static final long serialVersionUID = 1116472605960451997L; public ComboField(Element element, Parameter parameter) { super(element, parameter); @@ -293,7 +311,7 @@ public ComboField(Element element, Parameter parameter) { protected void setupValue() { final EnumType type = (EnumType) parameter.getType(); - value = new JComboBox(type.getValues()); + value = new JComboBox<>(type.getValues()); value.setAlignmentX(LEFT_ALIGNMENT); value.setFont(MEDIUM_FONT); add(value); @@ -302,18 +320,17 @@ protected void setupValue() { load(); } - private JComboBox getComboBox() { - return (JComboBox) value; + private JComboBox getComboBox() { + return value; } public void load() { final Integer selection = (Integer) element.get(parameter); - getComboBox().setSelectedIndex(selection.intValue()); + getComboBox().setSelectedIndex(selection); } public void save() { - final int selection = getComboBox().getSelectedIndex(); - final Integer sel = new Integer(selection); + final Integer sel = getComboBox().getSelectedIndex(); check(sel); element.set(parameter, sel); } @@ -323,9 +340,12 @@ public String toString() { } } - public static class OffIntegerField extends Widget { + public static class OffIntegerField extends Widget> { - private String[] values; + @Serial + private static final long serialVersionUID = -454582028253676511L; + + private final String[] values; public OffIntegerField(Element element, Parameter parameter, String[] values) { super(element, parameter); @@ -339,7 +359,7 @@ protected void setupValue() { } protected void setupValuePost() { - value = new JComboBox(values); + value = new JComboBox<>(values); value.setAlignmentX(LEFT_ALIGNMENT); value.setFont(MEDIUM_FONT); add(value); @@ -349,18 +369,17 @@ protected void setupValuePost() { load(); } - private JComboBox getComboBox() { - return (JComboBox) value; + private JComboBox getComboBox() { + return value; } public void load() { final Integer selection = (Integer) element.get(parameter); - getComboBox().setSelectedIndex(selection.intValue()); + getComboBox().setSelectedIndex(selection); } public void save() { - final int selection = getComboBox().getSelectedIndex(); - final Integer sel = new Integer(selection); + final Integer sel = getComboBox().getSelectedIndex(); check(sel); element.set(parameter, sel); } @@ -370,7 +389,10 @@ public String toString() { } } - public static class TuningField extends Widget { + public static class TuningField extends Widget { + + @Serial + private static final long serialVersionUID = -1579155864749957680L; public TuningField(Layer element, Parameter parameter) { super(element, parameter); @@ -395,7 +417,7 @@ protected void setupValue() { } private JTextField getTextField() { - return (JTextField) value; + return value; } private Layer getSampleElement() { @@ -412,9 +434,9 @@ public void load() { public void save() { final String text = getTextField().getText(); - final Double v = new Double(text); + final Double v = Double.valueOf(text); - if (!parameter.getType().validate(v)) { + if (parameter.getType().validate(v)) { onError(); return; } diff --git a/MpcMaid/src/com/mpcmaid/gui/WidgetPanel.java b/MpcMaid/src/main/java/com/mpcmaid/gui/WidgetPanel.java old mode 100755 new mode 100644 similarity index 75% rename from MpcMaid/src/com/mpcmaid/gui/WidgetPanel.java rename to MpcMaid/src/main/java/com/mpcmaid/gui/WidgetPanel.java index 292f0ea..b135c48 --- a/MpcMaid/src/com/mpcmaid/gui/WidgetPanel.java +++ b/MpcMaid/src/main/java/com/mpcmaid/gui/WidgetPanel.java @@ -2,6 +2,9 @@ import java.awt.Component; import java.awt.GridLayout; +import java.io.Serial; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; import javax.swing.JLabel; import javax.swing.JPanel; @@ -24,6 +27,11 @@ */ public class WidgetPanel extends JPanel implements BindingCapable { + private static final Logger logger = System.getLogger(WidgetPanel.class.getName()); + + @Serial + private static final long serialVersionUID = -8139985486559953248L; + private final Element element; public WidgetPanel(Element element) { @@ -39,10 +47,9 @@ public void make() { protected void makeParameters() { final Parameter[] parameters = element.getParameters(); - for (int j = 0; j < parameters.length; j++) { - final Parameter parameter = parameters[j]; - makeParameter(parameter); - } + for (final Parameter parameter : parameters) { + makeParameter(parameter); + } } protected void makeParameter(final Parameter parameter) { @@ -61,7 +68,7 @@ protected void makeParameter(final Parameter parameter) { } } - protected void addWidget(final Widget widget) { + protected void addWidget(final Widget widget) { add(widget); } @@ -101,31 +108,29 @@ public void makeDecimalParameter(Parameter parameter) { public void load() { final Component[] widgets = getComponents(); - for (int i = 0; i < widgets.length; i++) { - if (widgets[i] instanceof BindingCapable) { - BindingCapable component = (BindingCapable) widgets[i]; - try { - component.load(); - } catch (Exception e) { - System.out.println("xception: " + component + " " + i); - e.printStackTrace(); - } - } - } + for (Component widget : widgets) { + if (widget instanceof BindingCapable component) { + try { + component.load(); + } catch (Exception e) { + logger.log(Level.ERROR, e::getMessage, e); + } + } + } } public void save() { final Component[] widgets = getComponents(); - for (int i = 0; i < widgets.length; i++) { - WidgetPanel component = (WidgetPanel) widgets[i]; - component.save(); - } + for (Component widget : widgets) { + WidgetPanel component = (WidgetPanel) widget; + component.save(); + } } - public final static String[] enumerate(Parameter parameter, String prefix) { + public static String[] enumerate(Parameter parameter, String prefix) { final OffIntType type = (OffIntType) parameter.getType(); final Range range = type.getRange(); - final String[] values = new String[range.getHigh() - range.getLow() + 1]; + final String[] values = new String[range.high() - range.low() + 1]; for (int i = 0; i < values.length; i++) { values[i] = i == 0 ? "Off" : prefix + i; } diff --git a/MpcMaid/src/com/mpcmaid/midi/MidiSequenceBuilder.java b/MpcMaid/src/main/java/com/mpcmaid/midi/MidiSequenceBuilder.java old mode 100755 new mode 100644 similarity index 82% rename from MpcMaid/src/com/mpcmaid/midi/MidiSequenceBuilder.java rename to MpcMaid/src/main/java/com/mpcmaid/midi/MidiSequenceBuilder.java index 08bbb1f..f884696 --- a/MpcMaid/src/com/mpcmaid/midi/MidiSequenceBuilder.java +++ b/MpcMaid/src/main/java/com/mpcmaid/midi/MidiSequenceBuilder.java @@ -1,14 +1,10 @@ package com.mpcmaid.midi; +import javax.sound.midi.*; import java.io.File; import java.io.IOException; - -import javax.sound.midi.InvalidMidiDataException; -import javax.sound.midi.MidiEvent; -import javax.sound.midi.MidiSystem; -import javax.sound.midi.Sequence; -import javax.sound.midi.ShortMessage; -import javax.sound.midi.Track; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; /** * A builder to create a MIDI sequence that can be played or exported to file. @@ -17,13 +13,15 @@ */ public final class MidiSequenceBuilder { + private static final Logger logger = System.getLogger(MidiSequenceBuilder.class.getName()); + private Sequence sequence; public MidiSequenceBuilder(final int ppq) { try { sequence = new Sequence(Sequence.PPQ, ppq); } catch (InvalidMidiDataException e) { - e.printStackTrace(); + logger.log(Level.ERROR, e::getMessage, e); } } @@ -52,7 +50,7 @@ public void addNote(Track track, int channel, int startTick, int tickLength, int track.add(new MidiEvent(on, startTick)); track.add(new MidiEvent(off, startTick + tickLength)); } catch (InvalidMidiDataException e) { - e.printStackTrace(); + logger.log(Level.ERROR, e::getMessage, e); } } diff --git a/MpcMaid/src/com/mpcmaid/pgm/BaseElement.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/BaseElement.java old mode 100755 new mode 100644 similarity index 89% rename from MpcMaid/src/com/mpcmaid/pgm/BaseElement.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/BaseElement.java index c6881f6..6e41790 --- a/MpcMaid/src/com/mpcmaid/pgm/BaseElement.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/BaseElement.java @@ -120,14 +120,13 @@ public void setRange(int index, Range value) { * Copies every parameter value of the given source element into this * element, except for the given set of parameters to ignore */ - public void copyFrom(BaseElement source, Set ignoreParams) { + public void copyFrom(BaseElement source, Set ignoreParams) { final Parameter[] ps = getParameters(); - for (int i = 0; i < ps.length; i++) { - final Parameter parameter = ps[i]; - if (ignoreParams == null || !ignoreParams.contains(parameter)) { - final Object value = source.get(parameter); - set(parameter, value); - } - } + for (final Parameter parameter : ps) { + if (ignoreParams == null || !ignoreParams.contains(parameter)) { + final Object value = source.get(parameter); + set(parameter, value); + } + } } } diff --git a/MpcMaid/src/main/java/com/mpcmaid/pgm/Buffer.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/Buffer.java new file mode 100644 index 0000000..9fc7eb4 --- /dev/null +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/Buffer.java @@ -0,0 +1,21 @@ +package com.mpcmaid.pgm; + +public interface Buffer { + + String getString(final int offset); + + void setString(final int offset, String string); + + short getShort(final int index); + + void setShort(final int index, final short value); + + byte getByte(final int index); + + void setByte(final int index, final int value); + + Range getRange(final int index); + + void setRange(final int index, final Range value); + +} \ No newline at end of file diff --git a/MpcMaid/src/com/mpcmaid/pgm/ByteBuffer.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/ByteBuffer.java old mode 100755 new mode 100644 similarity index 82% rename from MpcMaid/src/com/mpcmaid/pgm/ByteBuffer.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/ByteBuffer.java index 590e12d..2256eba --- a/MpcMaid/src/com/mpcmaid/pgm/ByteBuffer.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/ByteBuffer.java @@ -28,9 +28,7 @@ public ByteBuffer(byte[] bytes) { public ByteBuffer(ByteBuffer other) { this(other.bytes.length); - for (int i = 0; i < bytes.length; i++) { - bytes[i] = other.bytes[i]; - } + System.arraycopy(other.bytes, 0, bytes, 0, bytes.length); } public String getString(final int offset) { @@ -58,7 +56,7 @@ public void setString(final int offset, String string) { public int getInt(final int index) { return ((bytes[index + 3] & 0xff) << 24) | ((bytes[index + 2] & 0xff) << 16) | ((bytes[index + 1] & 0xff) << 8) - | ((bytes[index + 0] & 0xff)); + | ((bytes[index] & 0xff)); } public void setInt(final int index, final int value) { @@ -92,40 +90,22 @@ public Range getRange(int index) { } public void setRange(int index, Range range) { - setByte((index + LOW), range.getLow()); - setByte((index + HIGH), range.getHigh()); + setByte((index + LOW), range.low()); + setByte((index + HIGH), range.high()); } public static ByteBuffer open(final InputStream fis, final int length) throws IOException { final byte[] bytes = new byte[length]; - try { - fis.read(bytes); - fis.close(); - } catch (IOException e) { - throw e; - } finally { - try { - fis.close(); - } catch (IOException e) { - throw e; - } + try (fis) { + fis.read(bytes); //FIXME } return new ByteBuffer(bytes); } public void save(final OutputStream fos) throws IOException { - try { - fos.write(bytes); - fos.close(); - } catch (IOException e) { - throw e; - } finally { - try { - fos.close(); - } catch (IOException e) { - throw e; - } - } + try (fos) { + fos.write(bytes); + } } public String toString() { diff --git a/MpcMaid/src/com/mpcmaid/pgm/Element.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/Element.java old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/src/com/mpcmaid/pgm/Element.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/Element.java diff --git a/MpcMaid/src/com/mpcmaid/pgm/Layer.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/Layer.java old mode 100755 new mode 100644 similarity index 97% rename from MpcMaid/src/com/mpcmaid/pgm/Layer.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/Layer.java index 9ade9a6..6e8b296 --- a/MpcMaid/src/com/mpcmaid/pgm/Layer.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/Layer.java @@ -25,7 +25,7 @@ public final class Layer extends BaseElement { public final static Parameter[] PARAMETERS = { SAMPLE_NAME, LEVEL, TUNING, PLAY_MODE, RANGE }; - protected Layer(final Pad parent, int layerIndex) { + Layer(final Pad parent, int layerIndex) { super(parent, 0, layerIndex, SAMPLE_LENGTH); Program.assertIn(0, layerIndex, 3, "sample layer"); } diff --git a/MpcMaid/src/main/java/com/mpcmaid/pgm/MultisampleBuilder.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/MultisampleBuilder.java new file mode 100644 index 0000000..6069cd0 --- /dev/null +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/MultisampleBuilder.java @@ -0,0 +1,248 @@ +package com.mpcmaid.pgm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; + +/** + * Finds out a configuration of a multisample program from a mere set of sample + * files names. + *

+ * Uses the sample filenames to guess their pitch, then assigns each sample to + * one or several pads so that to rebuild a full chromatic scale (from note 35 + * to note 98). + * + * @author cyrille martraire + */ +public class MultisampleBuilder { + + private static final Logger logger = System.getLogger(MultisampleBuilder.class.getName()); + + private final int firstNote = 35; + + private final int padNumber = 64; + + private final Collection warnings = new ArrayList<>(); + + private static final String[] NOTES = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; + + private static final String[] NOTES_BIS = { "C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ", "G#", "A ", "A#", "B " }; + + /** + * @param samples + * A list of String of the sample names without extension + */ + public Slot[] assign(List samples) { + try { + return assignBare(samples); + } catch (Exception e) { + logger.log(Level.ERROR, e::getMessage, e); + return new Slot[64]; + } + } + + /** + * Converts a list of samples into a list of filenames without extension + */ + private static List sampleNames(List samples) { + final List list = new ArrayList<>(); + for (Sample sample : samples) { + final String sampleName = sample.getSampleName(); + logger.log(Level.INFO, sampleName); + list.add(sampleName); + } + return list; + } + + public Collection getWarnings() { + return warnings; + } + + private Slot[] assignBare(List samples) { + if (samples.size() < 2) { + return null; + } + + final List sampleNames = sampleNames(samples); + final int commonIndex = longestPrefix(sampleNames); + if (commonIndex == 0) { + return null; + } + + // build slots, returns a sorted list + final List slots = collectSlots(samples, commonIndex); + if (slots.size() <= 2) { + return null; + } + + // interpolate notes in between + final Slot[] multisample = new Slot[64]; + Slot last = null; + for (Slot slot : slots) { + final int note = slot.note(); + + // fill exact slot first, to be sure it wins + multisample[note - firstNote] = slot; + + // cross note is halfway between previous sample slot and this + // sample slot + int crossNote = last == null ? firstNote - 1 : ((note + last.note()) / 2); + + if (last != null) { + // fill from previous slot till cross note + for (int transposeUp = last.note() + 1; transposeUp <= crossNote; transposeUp++) { + final int index = transposeUp - firstNote; + if (multisample[index] == null) { + final Slot transposed = last.transpose(transposeUp); + if (Math.abs(transposed.tuning()) <= 36) { + multisample[index] = transposed; + } + } + } + } + + // fill from cross note till current slot + for (int transposeDown = crossNote + 1; transposeDown < note; transposeDown++) { + final int index = transposeDown - firstNote; + if (multisample[index] == null) { + final Slot transposed = slot.transpose(transposeDown); + if (Math.abs(transposed.tuning()) <= 36) { + multisample[index] = transposed; + } + } + } + + last = slot; + } + + // finish till the end of the scale + for (int transposeUp = last.note() + 1; transposeUp < firstNote + padNumber; transposeUp++) { + final int index = transposeUp - firstNote; + if (multisample[index] == null) { + final Slot transposed = last.transpose(transposeUp); + if (Math.abs(transposed.tuning()) <= 36) { + multisample[index] = transposed; + } + } + } + + return multisample; + } + + protected List collectSlots(final List samples, int commonIndex) { + final List slots = new ArrayList<>(); + for (Sample sample : samples) { + final String word = sample.getSampleName(); + final String variablePart = word.substring(commonIndex); + final int note = extractNote(variablePart); + + if (note >= firstNote && note <= firstNote + padNumber) { + slots.add(new Slot(sample, note, 0)); + } else { + warnings.add("File: " + word + + " is not consistently named, will be ignored when building the multisamples"); + } + } + Collections.sort(slots); + return slots; + } + + protected static int longestPrefix(final List words) { + int commonIndex = 16;// max + String last = null; + for (String word : words) { + if (last != null) { + final int index = longestPrefix(commonIndex, word, last); + if (index < commonIndex) { + commonIndex = index; + } + } + last = word; + } + return commonIndex; + } + + private static int longestPrefix(int index, String word, String last) { + for (int i = 0; i < index && i < word.length() && i < last.length(); i++) { + if (word.charAt(i) != last.charAt(i)) { + return i; + } + } + return index; + } + + public static String noteName(final int note) { + final int chromatic = (note - 24) % 12; + final int octave = (note - 24) / 12; + return NOTES[chromatic] + octave; + } + + public static int extractNote(final String noteName) { + for (int i = NOTES.length - 1; i >= 0; i--) { + String candidate = NOTES_BIS[i]; + int indexOf = noteName.lastIndexOf(candidate); + if (indexOf == -1) { + candidate = NOTES[i]; + indexOf = noteName.lastIndexOf(candidate); + } + if (indexOf != -1) { + final char octaveDigit = noteName.charAt(indexOf + candidate.length()); + int octave = 3; + if (Character.isDigit(octaveDigit)) { + octave = Integer.parseInt("" + octaveDigit); + } + return 24 + octave * 12 + i; + } + } + return -1; + } + + public String toString() { + return "MultisampleBuilder first note: " + noteName(firstNote) + ", " + padNumber + " pads"; + } + + /** + * Represents one sample used in a multisample program, including the + * chromatic note it is supposed to play and the tuning required to play + * this note + * + * @author cyrille martraire + */ + public record Slot(Object source, int note, double tuning) implements Comparable { + + public Slot transpose(final int anotherNote) { + final int requiredTuning = anotherNote - note; + return new Slot(source, anotherNote, requiredTuning); + } + + + public int compareTo(Slot o) { + return note - o.note; + } + + /** + * @return true if this Slot is equal to the given Slot + */ + public boolean equals(Object arg0) { + if (!(arg0 instanceof Slot other)) { + return false; + } + if (this == other) { + return true; + } + return note == other.note; + } + + public int hashCode() { + return note; + } + + public String toString() { + return "Slot " + note + " " + source + " tuning=" + tuning; + } + + } +} diff --git a/MpcMaid/src/com/mpcmaid/pgm/Pad.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/Pad.java old mode 100755 new mode 100644 similarity index 91% rename from MpcMaid/src/com/mpcmaid/pgm/Pad.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/Pad.java index 5eeb7e4..a48d3a8 --- a/MpcMaid/src/com/mpcmaid/pgm/Pad.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/Pad.java @@ -27,7 +27,9 @@ public final class Pad extends BaseElement { private static final int PAD_LENGTH = 0xA4;// length of pad section - protected Pad(final Program parent, int padIndex) { + public static final int LAYER_NUMBER = 4; + + Pad(final Program parent, int padIndex) { super(parent, PAD_SECTION, padIndex, PAD_LENGTH); Program.assertIn(0, padIndex, 63, "pad"); } @@ -50,7 +52,7 @@ public PadEnvelope getEnvelope() { } public BaseElement getFilter(int i) { - return (i == 0) ? (BaseElement) getFilter1() : (BaseElement) getFilter2(); + return (i == 0) ? getFilter1() : getFilter2(); } public PadFilter1 getFilter1() { @@ -97,7 +99,7 @@ public void setPadMidiNote(final int midiNote) { public Object get(Parameter parameter) { if (parameter.equals(PAD_MIDI_NOTE_VALUE)) { - return new Integer(getPadMidiNote() - 35); + return getPadMidiNote() - 35; } return super.get(parameter); } @@ -113,7 +115,7 @@ public void set(Parameter parameter, Object value) { /** * Copies every parameter from the given source element, ignoring parameters given in the Set ignoreParams */ - public void copyFrom(BaseElement source, Set ignoreParams) { + public void copyFrom(BaseElement source, Set ignoreParams) { final Pad sourcePad = (Pad) source; super.copyFrom(sourcePad, ignoreParams); @@ -124,18 +126,14 @@ public void copyFrom(BaseElement source, Set ignoreParams) { final BaseElement page = pages[j]; page.copyFrom(sourcePages[j], ignoreParams); } - for (int j = 0; j < getLayerNumber(); j++) { + for (int j = 0; j < LAYER_NUMBER; j++) { Layer layer = getLayer(j); final Layer sourceLayer = sourcePad.getLayer(j); layer.copyFrom(sourceLayer, ignoreParams); } } - public int getLayerNumber() { - return 4; - } - - private final static String[] notes() { + private static String[] notes() { final String[] noteNames = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; final String[] notes = new String[64]; for (int i = 0; i < notes.length; i++) { diff --git a/MpcMaid/src/com/mpcmaid/pgm/PadEnvelope.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/PadEnvelope.java old mode 100755 new mode 100644 similarity index 95% rename from MpcMaid/src/com/mpcmaid/pgm/PadEnvelope.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/PadEnvelope.java index d07d25b..49ff651 --- a/MpcMaid/src/com/mpcmaid/pgm/PadEnvelope.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/PadEnvelope.java @@ -18,7 +18,7 @@ public final class PadEnvelope extends BaseElement { public final static Parameter[] PARAMETERS = { ATTACK, DECAY, DECAY_MODE, VELOCITY_TO_LEVEL }; - protected PadEnvelope(final Pad parent) { + PadEnvelope(final Pad parent) { super(parent); } diff --git a/MpcMaid/src/com/mpcmaid/pgm/PadFilter1.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/PadFilter1.java old mode 100755 new mode 100644 similarity index 96% rename from MpcMaid/src/com/mpcmaid/pgm/PadFilter1.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/PadFilter1.java index b2983fd..cda3ebd --- a/MpcMaid/src/com/mpcmaid/pgm/PadFilter1.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/PadFilter1.java @@ -24,7 +24,7 @@ public final class PadFilter1 extends BaseElement { public final static Parameter[] PARAMETERS = { FILTER1_TYPE, FILTER1_FREQ, FILTER1_RES, FILTER1_VELOCITY_TO_FREQ, FILTER_ATTN }; - protected PadFilter1(final Pad parent) { + PadFilter1(final Pad parent) { super(parent); } diff --git a/MpcMaid/src/com/mpcmaid/pgm/PadFilter2.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/PadFilter2.java old mode 100755 new mode 100644 similarity index 95% rename from MpcMaid/src/com/mpcmaid/pgm/PadFilter2.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/PadFilter2.java index 7241fac..fa3be9a --- a/MpcMaid/src/com/mpcmaid/pgm/PadFilter2.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/PadFilter2.java @@ -19,7 +19,7 @@ public final class PadFilter2 extends BaseElement { public final static Parameter[] PARAMETERS = { FILTER2_TYPE, FILTER2_FREQ, FILTER2_RES, FILTER2_VELOCITY_TO_FREQ }; - protected PadFilter2(final Pad parent) { + PadFilter2(final Pad parent) { super(parent); } diff --git a/MpcMaid/src/com/mpcmaid/pgm/PadMixer.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/PadMixer.java old mode 100755 new mode 100644 similarity index 96% rename from MpcMaid/src/com/mpcmaid/pgm/PadMixer.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/PadMixer.java index 2fbba49..5650f70 --- a/MpcMaid/src/com/mpcmaid/pgm/PadMixer.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/PadMixer.java @@ -22,7 +22,7 @@ public final class PadMixer extends BaseElement { public final static Parameter[] PARAMETERS = { MIXER_LEVEL, MIXER_PAN, OUTPUT, FX_SEND, FX_SEND_LEVEL }; - protected PadMixer(final Pad parent) { + PadMixer(final Pad parent) { super(parent); } diff --git a/MpcMaid/src/com/mpcmaid/pgm/Parameter.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/Parameter.java old mode 100755 new mode 100644 similarity index 77% rename from MpcMaid/src/com/mpcmaid/pgm/Parameter.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/Parameter.java index 795c349..4e6bd28 --- a/MpcMaid/src/com/mpcmaid/pgm/Parameter.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/Parameter.java @@ -8,7 +8,7 @@ */ public class Parameter { - public static interface Type { + public interface Type { Object get(BaseElement element, Parameter parameter); @@ -21,19 +21,17 @@ public static interface Type { public static final class TextType implements Type { - public int getStringLength() { - return 16; - } + public static final int STRING_LENGTH = 16; public void validate(String string, String explanation) { - if (validate(string)) { + if (!validate(string)) { throw new IllegalArgumentException(explanation + ": " + string + " is too long (16 chars max)"); } } public boolean validate(Object o) { final String string = (String) o; - return string.length() > 16; + return string.length() <= STRING_LENGTH; } public Object get(BaseElement element, Parameter parameter) { @@ -80,18 +78,18 @@ public boolean validate(Object value) { public Object get(BaseElement element, Parameter parameter) { final byte b = element.getBuffer().getByte(parameter.getOffset()); - return new Integer(b); + return (int) b; } public void set(BaseElement element, Parameter parameter, Object value) { final Integer i = (Integer) value; - final int val = i.intValue(); + final int val = i; validate(i, parameter.getLabel()); element.getBuffer().setByte(parameter.getOffset(), val); } public String toolTip() { - return "Min = " + getRange().getLow() + ", max = " + getRange().getHigh(); + return "Min = " + getRange().low() + ", max = " + getRange().high(); } public String toString() { @@ -101,7 +99,7 @@ public String toString() { public static final class IntType extends NumberType { - protected IntType(Range range) { + private IntType(Range range) { super(range); } @@ -109,7 +107,7 @@ protected IntType(Range range) { public static final class OffIntType extends NumberType { - protected OffIntType(Range range) { + private OffIntType(Range range) { super(range); } @@ -117,7 +115,7 @@ protected OffIntType(Range range) { public static final class TuningType extends NumberType { - protected TuningType(Range range) { + private TuningType(Range range) { super(range); } @@ -130,7 +128,7 @@ public boolean validate(Object value) { public static final class RangeType extends NumberType { - protected RangeType(Range range) { + private RangeType(Range range) { super(range); } @@ -149,7 +147,7 @@ public static final class EnumType implements Type { private final String[] values; - protected EnumType(String[] values) { + private EnumType(String[] values) { this.values = values; } @@ -159,12 +157,12 @@ public String[] getValues() { public Object get(BaseElement element, Parameter parameter) { final byte b = element.getBuffer().getByte(parameter.getOffset()); - return new Integer(b); + return (int) b; } public void set(BaseElement element, Parameter parameter, Object value) { final Integer i = (Integer) value; - final int val = i.intValue(); + final int val = i; validate(i, parameter.getLabel()); element.getBuffer().setByte(parameter.getOffset(), val); } @@ -177,8 +175,7 @@ private void validate(Integer value, String explanation) { } public boolean validate(Object o) { - final Integer v = (Integer) o; - final int value = v.intValue(); + final int value = (Integer) o; return value >= 0 && value < values.length; } @@ -199,35 +196,35 @@ protected Parameter(final String label, final int index, Type type) { this.type = type; } - public static final Parameter range(final String label, final int index, final Range valueRange) { + public static Parameter range(final String label, final int index, final Range valueRange) { return new Parameter(label, index, new RangeType(valueRange)); } - public static final Parameter range(final String label, final int index, final int min, final int max) { + public static Parameter range(final String label, final int index, final int min, final int max) { return range(label, index, new Range(min, max)); } - public static final Parameter integer(final String label, final int index, final Range valueRange) { + public static Parameter integer(final String label, final int index, final Range valueRange) { return new Parameter(label, index, new IntType(valueRange)); } - public static final Parameter integer(final String label, final int index, final int min, final int max) { + public static Parameter integer(final String label, final int index, final int min, final int max) { return integer(label, index, new Range(min, max)); } - public static final Parameter intOrOff(final String label, final int index, final int min, final int max) { + public static Parameter intOrOff(final String label, final int index, final int min, final int max) { return new Parameter(label, index, new OffIntType(new Range(min, max))); } - public static final Parameter decimal(final String label, final int index, final Range valueRange) { + public static Parameter decimal(final String label, final int index, final Range valueRange) { return new Parameter(label, index, new TuningType(valueRange)); } - public static final Parameter string(final String label, final int index, final int stringLength) { + public static Parameter string(final String label, final int index, final int stringLength) { return new Parameter(label, index, new TextType()); } - public static final Parameter enumType(final String label, final int index, final String[] possibleValues) { + public static Parameter enumType(final String label, final int index, final String[] possibleValues) { return new Parameter(label, index, new EnumType(possibleValues)); } diff --git a/MpcMaid/src/main/java/com/mpcmaid/pgm/Profile.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/Profile.java new file mode 100644 index 0000000..5b43931 --- /dev/null +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/Profile.java @@ -0,0 +1,28 @@ +package com.mpcmaid.pgm; + +/** + * Represents the profile of an MPC + * + * @author cyrille martraire + */ +public record Profile(String name, int rowNumber, int colNumber, int sliderNumber, int filterNumber) { + + public final static Profile MPC500 = new Profile("MPC500", 4, 3, 1, 1); + + public final static Profile MPC1000 = new Profile("MPC1000", 4, 4, 2, 2); + + + public int getPadNumber() { + return rowNumber * colNumber; + } + + + public String toString() { + return "Profile " + name; + } + + public static Profile getProfile(String name) { + return "MPC1000".equalsIgnoreCase(name) ? MPC1000 : MPC500; + } + +} diff --git a/MpcMaid/src/com/mpcmaid/pgm/Program.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/Program.java old mode 100755 new mode 100644 similarity index 78% rename from MpcMaid/src/com/mpcmaid/pgm/Program.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/Program.java index 50a6ac4..7cee765 --- a/MpcMaid/src/com/mpcmaid/pgm/Program.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/Program.java @@ -1,21 +1,21 @@ package com.mpcmaid.pgm; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.InputStream; +import java.nio.file.Files; /** * Represents an MPC1000 Program (*.pgm file). Note that a program only declares * how to deal with samples, it does not contain any actual sound. - * + *

* The MPC1000 file format used was provided by Stephen Norum on his website: - * http://mybunnyhug.com/fileformats/pgm/ Many thanks for sharing this format + * ... Many thanks for sharing this format * Stephen! - * + * * @author cyrille martraire */ -public class Program extends BaseElement { +@SuppressWarnings("unused") + public class Program extends BaseElement { // ------------- HEADER ------ private static final short FILE_LENGTH = 0x2A04; @@ -50,7 +50,8 @@ public Parameter[] getParameters() { return new Parameter[] { MIDI_PROGRAM_CHANGE }; } - protected static final void assertIn(final int min, final int value, final int max, String param) { + @SuppressWarnings("SameParameterValue") + protected static void assertIn(final int min, final int value, final int max, String param) { if (value < min || value > max) { final String msg = "Invalid " + param + " value: " + value + "; must be in [" + min + ".." + max + "]"; throw new IllegalArgumentException(msg); @@ -61,7 +62,9 @@ public Pad getPad(final int pad) { return new Pad(this, pad); } - public int getPadNumber() { + @SuppressWarnings("SameReturnValue") + public int getPadNumber() { + // keep it a variable, MPC500 has only four banks of 12 pads => 48 return 64; } @@ -70,7 +73,9 @@ public Slider getSlider(final int slider) { return new Slider(this, slider); } - public int getSlideNumber() { + @SuppressWarnings("SameReturnValue") + public int getSlideNumber() { + // keep it a variable, MPC500 has only one slider return 2; } @@ -85,7 +90,7 @@ public void setMidiProgramChange(final short midiProgramChange) { public static Program open(final File file) { try { - final ByteBuffer buffer = ByteBuffer.open(new FileInputStream(file), FILE_LENGTH); + final ByteBuffer buffer = ByteBuffer.open(Files.newInputStream(file.toPath()), FILE_LENGTH); return new Program(buffer); } catch (Exception e) { throw new IllegalArgumentException("The file " + file.getName() + " is not a valid MPC1000 pgm file."); @@ -104,7 +109,7 @@ public static Program open(final InputStream is) { public void save(final File file) { try { final ByteBuffer byteBuffer = (ByteBuffer) getBuffer(); - byteBuffer.save(new FileOutputStream(file)); + byteBuffer.save(Files.newOutputStream(file.toPath())); } catch (Exception e) { throw new IllegalArgumentException("The file " + file.getName() + " is not a valid MPC1000 pgm file."); } diff --git a/MpcMaid/src/com/mpcmaid/pgm/Range.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/Range.java old mode 100755 new mode 100644 similarity index 53% rename from MpcMaid/src/com/mpcmaid/pgm/Range.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/Range.java index 151e37b..d5675b3 --- a/MpcMaid/src/com/mpcmaid/pgm/Range.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/Range.java @@ -1,27 +1,12 @@ package com.mpcmaid.pgm; /** - * Represents a range of values [low..high] - * + * Represents a range of values [low...high] + * * @author cyrille martraire */ -public final class Range { - private final int low; +public record Range(int low, int high) { - private final int high; - - public Range(int low, int high) { - this.low = low; - this.high = high; - } - - public int getLow() { - return low; - } - - public int getHigh() { - return high; - } public boolean isReversed() { return high < low; @@ -38,21 +23,16 @@ public boolean contains(final double value) { /** * @return true if this Range is equal to the given Range */ - public boolean equals(Object arg0) { - if (!(arg0 instanceof Range)) { + public boolean equals(Object arg0) { //FIXME probably useless in a record + if (!(arg0 instanceof Range other)) { return false; } - final Range other = (Range) arg0; if (this == other) { return true; } return other.low == low && other.high == high; } - public int hashCode() { - return low + 97 * high; - } - public String toString() { return low + ".." + high; } diff --git a/MpcMaid/src/com/mpcmaid/pgm/RelativeBuffer.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/RelativeBuffer.java old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/src/com/mpcmaid/pgm/RelativeBuffer.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/RelativeBuffer.java diff --git a/MpcMaid/src/com/mpcmaid/pgm/Sample.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/Sample.java old mode 100755 new mode 100644 similarity index 93% rename from MpcMaid/src/com/mpcmaid/pgm/Sample.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/Sample.java index 5540513..8304111 --- a/MpcMaid/src/com/mpcmaid/pgm/Sample.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/Sample.java @@ -70,7 +70,7 @@ public static Sample importFile(final File file, final int length, final Status * program) */ public static Sample findFile(String sampleName, File path) { - if (sampleName == null || sampleName.trim().length() == 0) { + if (sampleName == null || sampleName.trim().isEmpty()) { return null; } File file = new File(path, sampleName + ".wav"); @@ -150,7 +150,7 @@ public String getSampleName() { return name; } - public File getDestinationFile(File dir) throws IOException { + public File getDestinationFile(File dir) { final String dstName = getName(); if (actualFile == null || dstName == null) { return null; @@ -166,6 +166,14 @@ public void copyTo(File dir) throws IOException { Utils.copy(actualFile, dst); } + public void convertTo(File dir) throws IOException { + final File dst = getDestinationFile(dir); + if (dst == null) { + return; + } + Utils.resample(actualFile, dst); + } + public void play() { if (actualFile != null) { SamplePlayer.getInstance().play(actualFile); diff --git a/MpcMaid/src/com/mpcmaid/pgm/SampleCommand.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/SampleCommand.java old mode 100755 new mode 100644 similarity index 76% rename from MpcMaid/src/com/mpcmaid/pgm/SampleCommand.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/SampleCommand.java index 9ded309..134b7b5 --- a/MpcMaid/src/com/mpcmaid/pgm/SampleCommand.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/SampleCommand.java @@ -1,7 +1,7 @@ package com.mpcmaid.pgm; /** - * A closure to execute agaisnt this sample matrix + * A closure to execute against this sample matrix * * @pattern Command * diff --git a/MpcMaid/src/com/mpcmaid/pgm/SampleMatrix.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/SampleMatrix.java old mode 100755 new mode 100644 similarity index 54% rename from MpcMaid/src/com/mpcmaid/pgm/SampleMatrix.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/SampleMatrix.java index 155390f..437d127 --- a/MpcMaid/src/com/mpcmaid/pgm/SampleMatrix.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/SampleMatrix.java @@ -1,6 +1,7 @@ package com.mpcmaid.pgm; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -24,37 +25,31 @@ public Sample get(final Layer layer) { public int size() { int size = 0; - for (int i = 0; i < cells.length; i++) { - final Sample[] layers = cells[i]; - for (int j = 0; j < layers.length; j++) { - if (layers[j] != null) { - size++; - } - } - } + for (final Sample[] layers : cells) { + for (Sample layer : layers) { + if (layer != null) { + size++; + } + } + } return size; } public void clear() { - for (int i = 0; i < cells.length; i++) { - final Sample[] layers = cells[i]; - for (int j = 0; j < layers.length; j++) { - layers[j] = null; - } - } + for (final Sample[] layers : cells) { + Arrays.fill(layers, null); + } } - public List collectAll() { - final List list = new ArrayList(); - for (int i = 0; i < cells.length; i++) { - final Sample[] layers = cells[i]; - for (int j = 0; j < layers.length; j++) { - final Sample sample = layers[j]; - if (sample != null) { - list.add(sample); - } - } - } + public List collectAll() { + final List list = new ArrayList<>(); + for (final Sample[] layers : cells) { + for (final Sample sample : layers) { + if (sample != null) { + list.add(sample); + } + } + } return list; } diff --git a/MpcMaid/src/com/mpcmaid/pgm/Slider.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/Slider.java old mode 100755 new mode 100644 similarity index 97% rename from MpcMaid/src/com/mpcmaid/pgm/Slider.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/Slider.java index ff10302..56c64ed --- a/MpcMaid/src/com/mpcmaid/pgm/Slider.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/Slider.java @@ -37,7 +37,7 @@ public final class Slider extends BaseElement { // Tune range 0-100 public static final Parameter DECAY_RANGE = Parameter.range("Decay", 0x29E4, 0, 100); - protected Slider(final Program parent, int sliderIndex) { + Slider(final Program parent, int sliderIndex) { super(parent, 0, sliderIndex, SLIDER_LENGTH); Program.assertIn(0, sliderIndex, 1, "slider"); } diff --git a/MpcMaid/src/com/mpcmaid/pgm/command/ExportCommand.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/command/ExportCommand.java old mode 100755 new mode 100644 similarity index 66% rename from MpcMaid/src/com/mpcmaid/pgm/command/ExportCommand.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/command/ExportCommand.java index fb36f18..11e9201 --- a/MpcMaid/src/com/mpcmaid/pgm/command/ExportCommand.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/command/ExportCommand.java @@ -1,19 +1,23 @@ package com.mpcmaid.pgm.command; -import java.io.File; -import java.io.IOException; -import java.util.Iterator; - import com.mpcmaid.pgm.Sample; import com.mpcmaid.pgm.SampleCommand; import com.mpcmaid.pgm.SampleMatrix; +import java.io.File; +import java.io.IOException; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; + /** * Exports every sample file into the destination directory. * * @author cyrille martraire */ public final class ExportCommand implements SampleCommand { + + private static final Logger logger = System.getLogger(ExportCommand.class.getName()); + private final File dir; private int exported = 0; @@ -25,17 +29,15 @@ public ExportCommand(File dir) { } public Object execute(SampleMatrix matrix) { - final Iterator it = matrix.collectAll().iterator(); - while (it.hasNext()) { - Sample sample = (Sample) it.next(); - expected++; - try { - sample.copyTo(dir); - exported++; - } catch (IOException e) { - e.printStackTrace(); - } - } + for (Sample sample : matrix.collectAll()) { + expected++; + try { + sample.convertTo(dir); + exported++; + } catch (IOException e) { + logger.log(Level.ERROR, e::getMessage, e); + } + } return getReport(); } diff --git a/MpcMaid/src/com/mpcmaid/pgm/command/ImportCommand.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/command/ImportCommand.java old mode 100755 new mode 100644 similarity index 72% rename from MpcMaid/src/com/mpcmaid/pgm/command/ImportCommand.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/command/ImportCommand.java index bc5fed9..71b7c8b --- a/MpcMaid/src/com/mpcmaid/pgm/command/ImportCommand.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/command/ImportCommand.java @@ -1,7 +1,6 @@ package com.mpcmaid.pgm.command; import java.io.File; -import java.util.Iterator; import java.util.List; import com.mpcmaid.pgm.Sample; @@ -10,14 +9,14 @@ /** * Imports files and processes them into Sample objects for later use. - * + *

* Subclasses must call importFiles() to process the imported files before use. * * @author cyrille martraire */ public abstract class ImportCommand implements SampleCommand { - private final List files; + private final List files; private final Status errorPolicy; @@ -27,7 +26,7 @@ public abstract class ImportCommand implements SampleCommand { protected int rejectedCount; - public ImportCommand(Status errorPolicy, List files) { + public ImportCommand(Status errorPolicy, List files) { this.errorPolicy = errorPolicy; this.files = files; } @@ -61,21 +60,19 @@ public String getReport() { * an extension other than .wav, renaming file names too long) */ protected void importFiles() { - Iterator it = files.iterator(); - while (it.hasNext()) { - final File file = (File) it.next(); - importCount++; - final Sample sample = Sample.importFile(file, 16, errorPolicy, true, renameCount); - if (sample == null || sample.isRejected()) { - rejectedCount++; - } else { - // increments the rename count if needed - if (sample.isRenamed()) { - renameCount++; - } - addSample(sample); - } - } + for (File file : files) { + importCount++; + final Sample sample = Sample.importFile(file, 16, errorPolicy, true, renameCount); + if (sample == null || sample.isRejected()) { + rejectedCount++; + } else { + // increments the rename count if needed + if (sample.isRenamed()) { + renameCount++; + } + addSample(sample); + } + } } /** diff --git a/MpcMaid/src/com/mpcmaid/pgm/command/MultiSampleCommand.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/command/MultiSampleCommand.java old mode 100755 new mode 100644 similarity index 66% rename from MpcMaid/src/com/mpcmaid/pgm/command/MultiSampleCommand.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/command/MultiSampleCommand.java index 2bdbcaf..3b36c67 --- a/MpcMaid/src/com/mpcmaid/pgm/command/MultiSampleCommand.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/command/MultiSampleCommand.java @@ -1,8 +1,12 @@ package com.mpcmaid.pgm.command; +import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; + import com.mpcmaid.pgm.Layer; import com.mpcmaid.pgm.MultisampleBuilder; @@ -20,11 +24,13 @@ */ public class MultiSampleCommand extends ImportCommand { - private final List samples = new ArrayList(); + private static final Logger logger = System.getLogger(MultiSampleCommand.class.getName()); + + private final List samples = new ArrayList<>(); private final Program pgm; - public MultiSampleCommand(Status errorPolicy, List files, Program pgm) { + public MultiSampleCommand(Status errorPolicy, List files, Program pgm) { super(errorPolicy, files); this.pgm = pgm; } @@ -33,7 +39,7 @@ protected void addSample(Sample sample) { samples.add(sample); } - public Object execute(SampleMatrix matrix) { + public Collection execute(SampleMatrix matrix) { // process raw files (rename, reject etc) importFiles(); @@ -43,25 +49,24 @@ public Object execute(SampleMatrix matrix) { rejectedCount += builder.getWarnings().size(); // print - for (int i = 0; i < multisample.length; i++) { - Slot slot = multisample[i]; - System.out.println(slot); - } + for (Slot slot : multisample) { + logger.log(Level.INFO, slot); + } // assign - final Collection impactedPads = new ArrayList(); + final Collection impactedPads = new ArrayList<>(); for (int i = 0; i < multisample.length; i++) { Slot slot = multisample[i]; if (slot != null) { final Pad pad = pgm.getPad(i); final Layer layer = pad.getLayer(0); - final Sample sample = (Sample) slot.getSource(); + final Sample sample = (Sample) slot.source(); matrix.set(layer, sample); layer.setSampleName(sample.getSampleName()); - layer.setTuning(slot.getTuning()); - pad.setPadMidiNote(slot.getNote()); + layer.setTuning(slot.tuning()); + pad.setPadMidiNote(slot.note()); layer.setNoteOn(); impactedPads.add(pad); diff --git a/MpcMaid/src/com/mpcmaid/pgm/command/SimpleAssignCommand.java b/MpcMaid/src/main/java/com/mpcmaid/pgm/command/SimpleAssignCommand.java old mode 100755 new mode 100644 similarity index 78% rename from MpcMaid/src/com/mpcmaid/pgm/command/SimpleAssignCommand.java rename to MpcMaid/src/main/java/com/mpcmaid/pgm/command/SimpleAssignCommand.java index f5228f4..a6a2db9 --- a/MpcMaid/src/com/mpcmaid/pgm/command/SimpleAssignCommand.java +++ b/MpcMaid/src/main/java/com/mpcmaid/pgm/command/SimpleAssignCommand.java @@ -1,5 +1,6 @@ package com.mpcmaid.pgm.command; +import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -19,13 +20,13 @@ */ public class SimpleAssignCommand extends ImportCommand { - private final List samples = new ArrayList(); + private final List samples = new ArrayList<>(); private final Pad selectedPad; private final boolean perPad; - public SimpleAssignCommand(Status errorPolicy, List files, Pad selectedPad, boolean perPad) { + public SimpleAssignCommand(Status errorPolicy, List files, Pad selectedPad, boolean perPad) { super(errorPolicy, files); this.perPad = perPad; this.selectedPad = selectedPad; @@ -35,20 +36,20 @@ protected void addSample(Sample sample) { samples.add(sample); } - public Object execute(SampleMatrix matrix) { - final List impactedPads = new ArrayList(); + public List execute(SampleMatrix matrix) { + final List impactedPads = new ArrayList<>(); final Program program = (Program) selectedPad.getParent(); final int from = selectedPad.getElementIndex(); // fills internal list importFiles(); - Iterator it = samples.iterator(); + Iterator it = samples.iterator(); final int n = program.getPadNumber(); for (int i = from; i < n; i++) { final Pad pad = program.getPad(i); - final int m = pad.getLayerNumber(); + final int m = Pad.LAYER_NUMBER; for (int j = 0; j < m; j++) { final Layer layer = pad.getLayer(j); if (matrix.get(layer) == null) { @@ -57,7 +58,7 @@ public Object execute(SampleMatrix matrix) { if (!it.hasNext()) { return impactedPads; } - final Sample sample = (Sample) it.next(); + final Sample sample = it.next(); matrix.set(layer, sample); layer.setSampleName(sample.getSampleName()); diff --git a/MpcMaid/src/com/mpcmaid/gui/chromatic.pgm b/MpcMaid/src/main/resources/com/mpcmaid/gui/chromatic.pgm old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/src/com/mpcmaid/gui/chromatic.pgm rename to MpcMaid/src/main/resources/com/mpcmaid/gui/chromatic.pgm diff --git a/MpcMaid/src/com/mpcmaid/gui/default.pgm b/MpcMaid/src/main/resources/com/mpcmaid/gui/default.pgm old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/src/com/mpcmaid/gui/default.pgm rename to MpcMaid/src/main/resources/com/mpcmaid/gui/default.pgm diff --git a/MpcMaid/src/com/mpcmaid/gui/mpcmaidlogo400_400.png b/MpcMaid/src/main/resources/com/mpcmaid/gui/mpcmaidlogo400_400.png old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/src/com/mpcmaid/gui/mpcmaidlogo400_400.png rename to MpcMaid/src/main/resources/com/mpcmaid/gui/mpcmaidlogo400_400.png diff --git a/MpcMaid/src/com/mpcmaid/pgm/Untitled.pgm b/MpcMaid/src/main/resources/com/mpcmaid/pgm/Untitled.pgm old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/src/com/mpcmaid/pgm/Untitled.pgm rename to MpcMaid/src/main/resources/com/mpcmaid/pgm/Untitled.pgm diff --git a/MpcMaid/test/com/mpcmaid/audio/SlicerTest.java b/MpcMaid/src/test/java/com/mpcmaid/audio/SlicerTest.java old mode 100755 new mode 100644 similarity index 67% rename from MpcMaid/test/com/mpcmaid/audio/SlicerTest.java rename to MpcMaid/src/test/java/com/mpcmaid/audio/SlicerTest.java index 8a79891..687f604 --- a/MpcMaid/test/com/mpcmaid/audio/SlicerTest.java +++ b/MpcMaid/src/test/java/com/mpcmaid/audio/SlicerTest.java @@ -1,6 +1,8 @@ package com.mpcmaid.audio; import java.io.IOException; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; import javax.sound.midi.Sequence; import javax.sound.midi.Track; @@ -8,6 +10,9 @@ import junit.framework.TestCase; public class SlicerTest extends TestCase { + + private static final Logger logger = System.getLogger(SlicerTest.class.getName()); + private static final int AVERAGE_ENERGY_WINDOW = 43; private static final int OVERLAP_RATIO = 1; @@ -21,16 +26,16 @@ protected void setUp() throws Exception { slicer = new Slicer(sample, WINDOW_SIZE, OVERLAP_RATIO, AVERAGE_ENERGY_WINDOW); slicer.extractMarkers(); markers = slicer.getMarkers(); - System.out.println(slicer); + logger.log(Level.INFO, slicer.toString()); } private Slicer slicer; private Markers markers; - public void testMarkers() { + public void testMarkers() throws IOException { assertEquals("Slicer: 3.8424037s (169450 samples), 9 markers", slicer.toString()); - System.out.println(markers); + logger.log(Level.INFO, markers.toString()); assertEquals(9, markers.size()); @@ -38,19 +43,19 @@ public void testMarkers() { Marker marker = markers.getSelectedMarker(); assertEquals(0, marker.getLocation()); - System.out.println(marker); + logger.log(Level.INFO, marker.toString()); markers.selectMarker(4); assertEquals(4, markers.getSelectedMarkerIndex()); assertEquals(79872, markers.getSelectedMarkerLocation()); assertEquals(79872, markers.getSelectedMarker().getLocation()); - assertEquals(0, markers.getRangeFrom(0).getFrom()); + assertEquals(0, markers.getRangeFrom(0).from()); final LocationRange range3 = markers.getRangeFrom(3); - System.out.println(range3); + logger.log(Level.INFO, range3.toString()); final LocationRange range4 = markers.getRangeFrom(4); - System.out.println(range4); + logger.log(Level.INFO, range4.toString()); assertEquals(3.8424037, markers.getDuration(), 0.000001); assertEquals(124.92, markers.getTempo(), 0.01); @@ -61,26 +66,23 @@ public void testMarkers() { assertEquals(3, markers.getSelectedMarkerIndex()); final LocationRange range3bis = markers.getRangeFrom(3); - assertEquals(range3.getFrom(), range3bis.getFrom()); - assertEquals(range4.getTo(), range3bis.getTo()); + assertEquals(range3.from(), range3bis.from()); + assertEquals(range4.to(), range3bis.to()); // last range extends up to the Frame Length final LocationRange range7 = markers.getRangeFrom(7); - assertEquals(169450, range7.getTo()); - System.out.println(range7); + assertEquals(169450, range7.to()); + logger.log(Level.INFO, range7.toString()); final int[] midiTicks = { 0, 32, 97, 129, 190, 222, 288, 320, 381, 413, 478, 510, 575, 607, 673, 705, 705 }; - try { - final Sequence midiSequence = markers.exportMidiSequence(null, MIDI_PPQ); - final Track track = midiSequence.getTracks()[0]; - assertEquals(17, track.size()); - for (int i = 0; i < track.size(); i++) { - // System.out.println(track.get(i).getTick()); - assertEquals(midiTicks[i], track.get(i).getTick()); - } - } catch (IOException e) { - e.printStackTrace(); + final Sequence midiSequence = markers.exportMidiSequence(null, MIDI_PPQ); + final Track track = midiSequence.getTracks()[0]; + assertEquals(17, track.size()); + for (int i = 0; i < track.size(); i++) { + // logger.log(Level.INFO, track.get(i).getTick()); + assertEquals(midiTicks[i], track.get(i).getTick()); } + assertEquals(3, markers.getSelectedMarkerIndex()); markers.insertMarker(); assertEquals(4, markers.getSelectedMarkerIndex()); diff --git a/MpcMaid/src/test/java/com/mpcmaid/gui/UtilsTest.java b/MpcMaid/src/test/java/com/mpcmaid/gui/UtilsTest.java new file mode 100644 index 0000000..ed4e241 --- /dev/null +++ b/MpcMaid/src/test/java/com/mpcmaid/gui/UtilsTest.java @@ -0,0 +1,56 @@ +package com.mpcmaid.gui; + +import junit.framework.TestCase; + +public class UtilsTest extends TestCase { + + public static String escapeSampleName(final String name, int length) { + final String noExt = Utils.noExtension(name); + + return Utils.escapeName(noExt, length, false); + } + + public void testEscapeName() { + assertEquals("123456789123456", escapeSampleName("123456789123456", 16)); + + assertEquals("1", escapeSampleName("1", 16)); + + assertEquals("1234567890123456", escapeSampleName("1234567890123456.", 16)); + assertEquals("1234567890123456", escapeSampleName("1234567890123456.wav", 16)); + assertEquals("123456789012345", escapeSampleName("123456789012345.abcd.wav", 16)); + assertEquals("123456789012345", escapeSampleName("123456789012345", 16)); + assertEquals("123456789012345 ", escapeSampleName("123456789012345 ", 16)); + assertEquals("123456789012345", escapeSampleName("123456789012345.", 16)); + + assertEquals("1234567890123456", escapeSampleName("123456789012345678.wav", 16)); + assertEquals("123456789012345", escapeSampleName("123456789012345_78.wav", 16)); + } + + public void testPathToListing() { + assertEquals("12345678901234", escapeSampleName("1234567890123456", 14)); + + assertEquals("1", escapeSampleName("1", 14)); + + assertEquals("1234567890123", escapeSampleName("1234567890123.", 14)); + assertEquals("123456789012", escapeSampleName("123456789012", 13)); + assertEquals("123456789012 ", escapeSampleName("123456789012 ", 13)); + assertEquals("123456789012_", escapeSampleName("123456789012_", 13)); + assertEquals("123456789012", escapeSampleName("123456789012 4", 13)); + assertEquals("123456789012", escapeSampleName("123456789012.4", 13)); + + assertEquals("1234567890123", escapeSampleName("1234567890123.12345", 14)); + assertEquals("1234567890123", escapeSampleName("1234567890123_13245", 14)); + } + + public void testMultipleRenaming() { + final String[] names = { "TicTacShutUp_click_1_d.wav", "TicTacShutUp_click_1_off_click.wav", + "TicTacShutUp_light_1.wav" }; + for (int j = 0; j < 4; j++) { + for (String name : names) { + final String noExt = Utils.noExtension(name); + Utils.escapeName(noExt, 16, true); + } + } + } + +} diff --git a/MpcMaid/src/test/java/com/mpcmaid/pgm/MultisampleBuilderTest.java b/MpcMaid/src/test/java/com/mpcmaid/pgm/MultisampleBuilderTest.java new file mode 100644 index 0000000..b134e06 --- /dev/null +++ b/MpcMaid/src/test/java/com/mpcmaid/pgm/MultisampleBuilderTest.java @@ -0,0 +1,79 @@ +package com.mpcmaid.pgm; + +import java.io.File; +import java.lang.System.*; +import java.lang.System.Logger.*; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import com.mpcmaid.pgm.MultisampleBuilder.Slot; + +public class MultisampleBuilderTest extends TestCase { + + + public final static Logger logger = System.getLogger(MultisampleBuilderTest.class.getName()); + + public void testNoteName() { + final List filenames = collectFileNames(1); + + final int commonIndex = MultisampleBuilder.longestPrefix(filenames); + // logger.log(Level.INFO, commonIndex); + + int i = 35; + for (String word : filenames) { + final String variablePart = word.substring(commonIndex); + final int note = MultisampleBuilder.extractNote(variablePart); + // logger.log(Level.INFO, note); + assertEquals(i++, note); + } + } + + public void testExtractNote() { + final int note = MultisampleBuilder.extractNote("ROH 40 E 1"); + assertEquals(40, note); + } + + public void testAssignment() { + final List filenames = collectFileNames(4); + final List samples = toSamples(filenames); + + final MultisampleBuilder builder = new MultisampleBuilder(); + final Slot[] multisample = builder.assign(samples); + + for (Slot slot : multisample) { + logger.log(Level.INFO, slot); + } + } + + private static List collectFileNames(int step) { + final List list = new ArrayList<>(); + for (int i = 0; i < 64; i += step) { + final int k = 35 + i; + final String noteName = MultisampleBuilder.noteName(k); + + final String spacer = noteName.length() == 2 ? " " : ""; + final String fileName = "WLS C" + k + noteName + (spacer) + "#" + i; + // logger.log(Level.INFO, fileName); + list.add(fileName); + final int note = MultisampleBuilder.extractNote(fileName); + assertEquals(k, note); + } + return list; + } + + protected static List toSamples(final List fileNames) { + final List list = new ArrayList<>(); + for (String fileName : fileNames) { + final Sample sample = toSample(fileName); + logger.log(Level.INFO, sample); + list.add(sample); + } + return list; + } + + protected static Sample toSample(final String fileName) { + return Sample.importFile(new File(fileName + ".WAV"), 16, Sample.OK, false, 0); + } +} diff --git a/MpcMaid/test/com/mpcmaid/pgm/ProgramInOutTest.java b/MpcMaid/src/test/java/com/mpcmaid/pgm/ProgramInOutTest.java old mode 100755 new mode 100644 similarity index 76% rename from MpcMaid/test/com/mpcmaid/pgm/ProgramInOutTest.java rename to MpcMaid/src/test/java/com/mpcmaid/pgm/ProgramInOutTest.java index 4e67132..958a052 --- a/MpcMaid/test/com/mpcmaid/pgm/ProgramInOutTest.java +++ b/MpcMaid/src/test/java/com/mpcmaid/pgm/ProgramInOutTest.java @@ -1,6 +1,8 @@ package com.mpcmaid.pgm; import java.io.File; +import java.lang.System.*; +import java.lang.System.Logger.*; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -10,7 +12,8 @@ public class ProgramInOutTest extends TestCase { - public void testFileInOut() throws Exception { + public final static Logger logger = System.getLogger(ProgramInOutTest.class.getName()); + public void testFileInOut() { // final File testFile = new File(get // assertTrue(testFile.exists()); @@ -21,11 +24,11 @@ public void testFileInOut() throws Exception { final Layer layer = pad.getLayer(0); for (int i = 0; i < 4; i++) { pad.setElementIndex(i); - System.out.println(pad); + logger.log(Level.INFO, pad); for (int j = 0; j < 4; j++) { layer.setElementIndex(j); - System.out.println(layer); - System.out.println(layer.getSampleName()); + logger.log(Level.INFO, layer); + logger.log(Level.INFO, layer.getSampleName()); } } } @@ -33,19 +36,16 @@ public void testFileInOut() throws Exception { /** * Copies every parameter of the given source pad but those contained in the * Set ignoreParams, for every pad between fromPad and toPad. - * - * @return A Collection of every impacted pad */ - public Collection copyPadParameters(Program pgm, Pad sourcePad, final int fromPad, final int toPad, Set ignoreParams) { - final Collection impactedPads = new ArrayList(); + public void copyPadParameters(Program pgm, Pad sourcePad, final int fromPad, final int toPad, Set ignoreParams) { + final Collection impactedPads = new ArrayList<>(); for (int i = fromPad; i < toPad; i++) { final Pad pad = pgm.getPad(i); pad.copyFrom(sourcePad, ignoreParams); } - return impactedPads; } - public void testCopyFrom() throws Exception { + public void testCopyFrom() { Program pgm = Program.open(getClass().getResourceAsStream("test.pgm")); final Pad currentlySelectedPad = pgm.getPad(0); @@ -53,7 +53,7 @@ public void testCopyFrom() throws Exception { pgm.save(new File("copyFrom1.pgm")); - final HashSet ignoreParams = new HashSet(); + final HashSet ignoreParams = new HashSet<>(); ignoreParams.add(Pad.PAD_MIDI_NOTE_VALUE); pgm = Program.open(getClass().getResourceAsStream("test.pgm")); copyPadParameters(pgm, currentlySelectedPad, 3, 12, ignoreParams); diff --git a/MpcMaid/test/com/mpcmaid/pgm/ProgramTest.java b/MpcMaid/src/test/java/com/mpcmaid/pgm/ProgramTest.java old mode 100755 new mode 100644 similarity index 71% rename from MpcMaid/test/com/mpcmaid/pgm/ProgramTest.java rename to MpcMaid/src/test/java/com/mpcmaid/pgm/ProgramTest.java index e881a1d..2294a59 --- a/MpcMaid/test/com/mpcmaid/pgm/ProgramTest.java +++ b/MpcMaid/src/test/java/com/mpcmaid/pgm/ProgramTest.java @@ -1,19 +1,16 @@ package com.mpcmaid.pgm; -import java.io.File; - -import com.mpcmaid.pgm.Pad; -import com.mpcmaid.pgm.PadMixer; -import com.mpcmaid.pgm.Program; -import com.mpcmaid.pgm.Range; -import com.mpcmaid.pgm.Layer; -import com.mpcmaid.pgm.Slider; - import junit.framework.TestCase; +import java.io.File; +import java.lang.System.Logger.Level; +import java.lang.System.Logger; + public class ProgramTest extends TestCase { - public void testRead() throws Exception { + private static final Logger logger = System.getLogger(ProgramTest.class.getName()); + + public void testRead() { Program pgm = Program.open(getClass().getResourceAsStream("test.pgm")); // read sample name @@ -23,15 +20,15 @@ public void testRead() throws Exception { final int padNumber = pgm.getPadNumber(); for (int i = 0; i < padNumber; i++) { final Pad pad = pgm.getPad(i); - System.out.println(pad + " fxSendLevel=" + pad.getMixer().get(PadMixer.FX_SEND_LEVEL) + " note: " + logger.log(Level.INFO, pad + " fxSendLevel=" + pad.getMixer().get(PadMixer.FX_SEND_LEVEL) + " note: " + pad.getPadMidiNote()); - final int sampleNumber = pad.getLayerNumber(); + final int sampleNumber = Pad.LAYER_NUMBER; for (int j = 0; j < sampleNumber; j++) { final Layer sample = pad.getLayer(j); final String playModeLabel = (sample.isOneShot()) ? "One Shot" : "Note On"; - System.out.println(sample + ": " + sample.getSampleName() + " level=" + sample.getLevel() + logger.log(Level.INFO, sample + ": " + sample.getSampleName() + " level=" + sample.getLevel() + " playMode=" + playModeLabel + " tuning=" + sample.getTuning()); } @@ -43,7 +40,7 @@ public void testRead() throws Exception { final String sampleName = "tomlow"; padLayer.setSampleName(sampleName); final String sampleName2 = padLayer.getSampleName(); - System.out.println(sampleName + "--" + sampleName2 + "--"); + logger.log(Level.INFO, sampleName + "--" + sampleName2 + "--"); assertEquals(sampleName.trim(), sampleName2); assertEquals(-0.5, padLayer.getTuning(), 0); diff --git a/MpcMaid/test/com/mpcmaid/pgm/SampleTest.java b/MpcMaid/src/test/java/com/mpcmaid/pgm/SampleTest.java old mode 100755 new mode 100644 similarity index 86% rename from MpcMaid/test/com/mpcmaid/pgm/SampleTest.java rename to MpcMaid/src/test/java/com/mpcmaid/pgm/SampleTest.java index 01237f4..1b55e19 --- a/MpcMaid/test/com/mpcmaid/pgm/SampleTest.java +++ b/MpcMaid/src/test/java/com/mpcmaid/pgm/SampleTest.java @@ -4,16 +4,18 @@ import junit.framework.TestCase; +import static org.junit.Assert.assertNotEquals; + public class SampleTest extends TestCase { - public void test_importFile_invalidExtension() throws Exception { + public void test_importFile_invalidExtension() { // not a wave file! File invalidFile = new File("test.pgm"); Sample sample = Sample.importFile(invalidFile, 16, Sample.RENAMED, true, 0); assertNull(sample); } - public void test_importFile_ok() throws Exception { + public void test_importFile_ok() { final File dir = new File("dummydir"); // valid file @@ -32,7 +34,7 @@ public void test_importFile_ok() throws Exception { assertFalse(sample.getSampleName().endsWith(".wav")); } - public void test_importFile_fileTooLong() throws Exception { + public void test_importFile_fileTooLong() { final File dir = new File("dummydir"); // valid file, name too long before the extension + RENAME policy @@ -42,8 +44,8 @@ public void test_importFile_fileTooLong() throws Exception { assertEquals(fileTooLong, sample.getActualFile()); assertEquals(dir, sample.getDestinationFile(dir).getParentFile()); - assertFalse(sample.getName().equals(sample.getOriginalName())); - assertFalse(sample.getOriginalName().equals(sample.getSampleName())); + assertNotEquals(sample.getName(), sample.getOriginalName()); + assertNotEquals(sample.getOriginalName(), sample.getSampleName()); assertTrue(sample.isRenamed()); @@ -55,7 +57,7 @@ public void test_importFile_fileTooLong() throws Exception { assertTrue(sample.getSampleName().endsWith("12")); } - public void test_findFile_notFound() throws Exception { + public void test_findFile_notFound() { final File path = getPath(); final File dir = new File("dummydir"); @@ -77,11 +79,10 @@ public void test_findFile_notFound() throws Exception { private File getPath() { final File file = new File(getClass().getResource("chh.wav").getFile()); - final File path = file.getParentFile(); - return path; + return file.getParentFile(); } - public void test_findFile_ok() throws Exception { + public void test_findFile_ok() { final File path = getPath(); final File dir = new File("dummydir"); final File file = new File(getClass().getResource("chh.wav").getFile()); diff --git a/MpcMaid/test/com/mpcmaid/pgm/command/ImportCommandTest.java b/MpcMaid/src/test/java/com/mpcmaid/pgm/command/ImportCommandTest.java old mode 100755 new mode 100644 similarity index 72% rename from MpcMaid/test/com/mpcmaid/pgm/command/ImportCommandTest.java rename to MpcMaid/src/test/java/com/mpcmaid/pgm/command/ImportCommandTest.java index 1c31ee6..b80f1b4 --- a/MpcMaid/test/com/mpcmaid/pgm/command/ImportCommandTest.java +++ b/MpcMaid/src/test/java/com/mpcmaid/pgm/command/ImportCommandTest.java @@ -1,6 +1,8 @@ package com.mpcmaid.pgm.command; import java.io.File; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -13,10 +15,12 @@ public class ImportCommandTest extends TestCase { + public final static Logger logger = System.getLogger(ImportCommandTest.class.getName()); + public static final class SampleList extends ImportCommand { - private final List list = new ArrayList(); + private final List list = new ArrayList<>(); - public SampleList(Status errorPolicy, List files) { + public SampleList(Status errorPolicy, List files) { super(errorPolicy, files); importFiles(); } @@ -26,7 +30,7 @@ protected void addSample(Sample sample) { } public Sample[] getSamples() { - return (Sample[]) list.toArray(new Sample[list.size()]); + return list.toArray(new Sample[0]); } // unused @@ -38,47 +42,39 @@ public int size() { return list.size(); } - public String getReport() { - return super.getReport(); - } - - public boolean hasError() { - return super.hasError(); - } - } public void testSampleList_allOK() { File fileOk = new File("chh.wav"); - SampleList list = new SampleList(Sample.RENAMED, Arrays.asList(new File[] { fileOk })); + SampleList list = new SampleList(Sample.RENAMED, List.of(fileOk)); assertEquals(1, list.size()); assertTrue(list.getSamples()[0].isValid()); assertFalse(list.hasError()); - System.out.println(list.getReport()); + logger.log(Level.INFO, list.getReport()); } public void testSampleList_1renamed() { File fileOk = new File("chh.wav"); File fileTooLong = new File("chh45678901234567.wav"); - SampleList list = new SampleList(Sample.RENAMED, Arrays.asList(new File[] { fileTooLong, fileOk })); + SampleList list = new SampleList(Sample.RENAMED, Arrays.asList(fileTooLong, fileOk)); assertEquals(2, list.size()); assertTrue(list.getSamples()[1].isValid()); assertTrue(list.getSamples()[0].isRenamed()); assertTrue(list.hasError()); - System.out.println(list.getReport()); + logger.log(Level.INFO, list.getReport()); } public void testSampleList_1rejected() { File fileOk = new File("chh.wav"); File fileTooLong = new File("chh45678901234567.wav"); - SampleList list = new SampleList(Sample.REJECTED, Arrays.asList(new File[] { fileTooLong, fileOk })); + SampleList list = new SampleList(Sample.REJECTED, Arrays.asList(fileTooLong, fileOk)); assertEquals(1, list.size()); assertTrue(list.getSamples()[0].isValid()); assertTrue(list.hasError()); - System.out.println(list.getReport()); + logger.log(Level.INFO, list.getReport()); } } diff --git a/MpcMaid/test/com/mpcmaid/audio/myLoop.WAV b/MpcMaid/src/test/resources/com/mpcmaid/audio/myLoop.WAV old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/test/com/mpcmaid/audio/myLoop.WAV rename to MpcMaid/src/test/resources/com/mpcmaid/audio/myLoop.WAV diff --git a/MpcMaid/test/com/mpcmaid/pgm/chh.wav b/MpcMaid/src/test/resources/com/mpcmaid/pgm/chh.wav old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/test/com/mpcmaid/pgm/chh.wav rename to MpcMaid/src/test/resources/com/mpcmaid/pgm/chh.wav diff --git a/MpcMaid/test/com/mpcmaid/pgm/chh45678901234567.wav b/MpcMaid/src/test/resources/com/mpcmaid/pgm/chh45678901234567.wav old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/test/com/mpcmaid/pgm/chh45678901234567.wav rename to MpcMaid/src/test/resources/com/mpcmaid/pgm/chh45678901234567.wav diff --git a/MpcMaid/test/com/mpcmaid/pgm/chromatic.pgm b/MpcMaid/src/test/resources/com/mpcmaid/pgm/chromatic.pgm old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/test/com/mpcmaid/pgm/chromatic.pgm rename to MpcMaid/src/test/resources/com/mpcmaid/pgm/chromatic.pgm diff --git a/MpcMaid/test/com/mpcmaid/pgm/multisample.PGM b/MpcMaid/src/test/resources/com/mpcmaid/pgm/multisample.PGM old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/test/com/mpcmaid/pgm/multisample.PGM rename to MpcMaid/src/test/resources/com/mpcmaid/pgm/multisample.PGM diff --git a/MpcMaid/test/com/mpcmaid/pgm/test.pgm b/MpcMaid/src/test/resources/com/mpcmaid/pgm/test.pgm old mode 100755 new mode 100644 similarity index 100% rename from MpcMaid/test/com/mpcmaid/pgm/test.pgm rename to MpcMaid/src/test/resources/com/mpcmaid/pgm/test.pgm diff --git a/MpcMaid/test/com/mpcmaid/gui/UtilsTest.java b/MpcMaid/test/com/mpcmaid/gui/UtilsTest.java deleted file mode 100755 index fcd9b66..0000000 --- a/MpcMaid/test/com/mpcmaid/gui/UtilsTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.mpcmaid.gui; - -import junit.framework.TestCase; - -public class UtilsTest extends TestCase { - - public static String escapeSampleName(final String name, int length) { - final String noExt = Utils.noExtension(name); - final String escapeName = Utils.escapeName(noExt, length, false); - - return escapeName; - } - - public void testEscapeName() { - assertEquals(escapeSampleName("123456789123456", 16), "123456789123456"); - - assertEquals(escapeSampleName("1", 16), "1"); - - assertEquals(escapeSampleName("1234567890123456.", 16), "1234567890123456"); - assertEquals(escapeSampleName("1234567890123456.wav", 16), "1234567890123456"); - assertEquals(escapeSampleName("123456789012345.abcd.wav", 16), "123456789012345"); - assertEquals(escapeSampleName("123456789012345", 16), "123456789012345"); - assertEquals(escapeSampleName("123456789012345 ", 16), "123456789012345 "); - assertEquals(escapeSampleName("123456789012345.", 16), "123456789012345"); - - assertEquals(escapeSampleName("123456789012345678.wav", 16), "1234567890123456"); - assertEquals(escapeSampleName("123456789012345_78.wav", 16), "123456789012345"); - } - - public void testPathToListing() { - assertEquals(escapeSampleName("1234567890123456", 14), "12345678901234"); - - assertEquals(escapeSampleName("1", 14), "1"); - - assertEquals(escapeSampleName("1234567890123.", 14), "1234567890123"); - assertEquals(escapeSampleName("123456789012", 13), "123456789012"); - assertEquals(escapeSampleName("123456789012 ", 13), "123456789012 "); - assertEquals(escapeSampleName("123456789012_", 13), "123456789012_"); - assertEquals(escapeSampleName("123456789012 4", 13), "123456789012"); - assertEquals(escapeSampleName("123456789012.4", 13), "123456789012"); - - assertEquals(escapeSampleName("1234567890123.12345", 14), "1234567890123"); - assertEquals(escapeSampleName("1234567890123_13245", 14), "1234567890123"); - } - - public void testMultipleRenaming() throws Exception { - final String[] names = { "TicTacShutUp_click_1_d.wav", "TicTacShutUp_click_1_off_click.wav", - "TicTacShutUp_light_1.wav" }; - for (int j = 0; j < 4; j++) { - for (int i = 0; i < names.length; i++) { - String name = names[i]; - final String noExt = Utils.noExtension(name); - Utils.escapeName(noExt, 16, true); - } - } - } - -} diff --git a/MpcMaid/test/com/mpcmaid/pgm/MultisampleBuilderTest.java b/MpcMaid/test/com/mpcmaid/pgm/MultisampleBuilderTest.java deleted file mode 100755 index cff9763..0000000 --- a/MpcMaid/test/com/mpcmaid/pgm/MultisampleBuilderTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.mpcmaid.pgm; - -import java.io.File; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import junit.framework.TestCase; - -import com.mpcmaid.pgm.MultisampleBuilder.Slot; - -public class MultisampleBuilderTest extends TestCase { - - public void testNoteName() throws Exception { - final List filenames = collectFileNames(1); - - final int commonIndex = MultisampleBuilder.longuestPrefix(filenames); - // System.out.println(commonIndex); - - int i = 35; - Iterator it = filenames.iterator(); - while (it.hasNext()) { - String word = (String) it.next(); - final String variablePart = word.substring(commonIndex); - final int note = MultisampleBuilder.extractNote(variablePart); - // System.out.println(note); - assertEquals(i++, note); - } - } - - public void testExtractNote() throws Exception { - final int note = MultisampleBuilder.extractNote("ROH 40 E 1"); - assertEquals(40, note); - } - - public void testAssignment() throws Exception { - final List filenames = collectFileNames(4); - final List samples = toSamples(filenames); - - final MultisampleBuilder builder = new MultisampleBuilder(); - final Slot[] multisample = builder.assign(samples); - - for (int i = 0; i < multisample.length; i++) { - Slot slot = multisample[i]; - System.out.println(slot); - } - } - - private static List collectFileNames(int step) { - final List list = new ArrayList(); - for (int i = 0; i < 64; i += step) { - final int k = 35 + i; - final String noteName = MultisampleBuilder.noteName(k); - - final String spacer = noteName.length() == 2 ? " " : ""; - final String fileName = "WLS C" + k + noteName + (spacer) + "#" + i; - // System.out.println(fileName); - list.add(fileName); - final int note = MultisampleBuilder.extractNote(fileName); - assertEquals(k, note); - } - return list; - } - - protected final static List toSamples(final List fileNames) { - final List list = new ArrayList(); - final Iterator it = fileNames.iterator(); - while (it.hasNext()) { - final String fileName = (String) it.next(); - final Sample sample = toSample(fileName); - System.out.println(sample); - list.add(sample); - } - return list; - } - - protected final static Sample toSample(final String fileName) { - return Sample.importFile(new File(fileName + ".WAV"), 16, Sample.OK, false, 0); - } -} diff --git a/README.md b/README.md index fdabf67..3483679 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ ![](https://github.com/cyriux/mpcmaid/blob/master/MpcMaid/packaging/icon128.png) +![Java CI with Maven](https://github.com/malkav30/mpcmaid/workflows/Java%20CI%20with%20Maven/badge.svg) + MPC Maid is a software editor for the Akai MPC 1000, MPC 2500, and MPC 500, for Mac, PC, and other platforms (Java) - Switch between the MPC 500 12-pads layout or the MPC 1000 16-pads layout (also takes care of the correct number of filters and sliders thanks to the built-in machine profiles). @@ -19,7 +21,7 @@ MPC Maid is a software editor for the Akai MPC 1000, MPC 2500, and MPC 500, for # Installation -Download the unique .jar directly from [Github](https://github.com/cyriux/mpcmaid/blob/master/MpcMaid/mpcmaid_beta.jar) +Download the unique .jar directly from [GitHub](https://github.com/cyriux/mpcmaid/blob/master/MpcMaid/mpcmaid_beta.jar) Double-click on it, MPC Maid must show.