From 508e654ba5a80fd110fda6b1d93ea8546aba1a6e Mon Sep 17 00:00:00 2001 From: alex_mclean <116386669+EatSleepProgramRepeat@users.noreply.github.com> Date: Sun, 13 Apr 2025 19:59:44 -0400 Subject: [PATCH 1/5] somewhat made ThreadManager --- .../java/com/CDPrintable/ThreadManager.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/com/CDPrintable/ThreadManager.java diff --git a/src/main/java/com/CDPrintable/ThreadManager.java b/src/main/java/com/CDPrintable/ThreadManager.java new file mode 100644 index 0000000..0acbf79 --- /dev/null +++ b/src/main/java/com/CDPrintable/ThreadManager.java @@ -0,0 +1,32 @@ +/* + * CDPrintable: A program that prints labels with track listings for your CD cases. + * Copyright (C) 2025 Alexander McLean + * + * This source code is licensed under the GNU General Public License v3.0 + * found in the LICENSE file in the root directory of this source tree. + * + * This class manages threads. + */ + +package com.CDPrintable; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class ThreadManager { + private final ExecutorService executorService; + + public ThreadManager() { + executorService = Executors.newFixedThreadPool(Constants.MAX_THREADS); + } + + public Future submit(Callable task) { + return executorService.submit(task); + } + + public void submit(Runnable task) { + executorService.submit(task); + } +} From b435493ec1bf7bc3a5a3660baeea0e5fcba9a3f6 Mon Sep 17 00:00:00 2001 From: alex_mclean <116386669+EatSleepProgramRepeat@users.noreply.github.com> Date: Sun, 13 Apr 2025 22:14:11 -0400 Subject: [PATCH 2/5] search status; multithreading --- .../java/com/CDPrintable/ProgramWindow.java | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/CDPrintable/ProgramWindow.java b/src/main/java/com/CDPrintable/ProgramWindow.java index cc6bee0..fbb8f7c 100644 --- a/src/main/java/com/CDPrintable/ProgramWindow.java +++ b/src/main/java/com/CDPrintable/ProgramWindow.java @@ -23,6 +23,8 @@ public class ProgramWindow { private final UserAgent userAgent; private JLabel fullUserAgentLabel = new JLabel(); + private final JPanel cdSearchPanel = new JPanel(); + private final JLabel searchStatusLabel = new JLabel("Status: Nothing's going on."); /** * Creates a new ProgramWindow and sets up the GUI. @@ -76,20 +78,20 @@ private JPanel searchPanel() { JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); - // Track List panel set up + // Track List panel set-up JPanel trackListPanel = new JPanel(new BorderLayout()); trackListPanel.setBorder(BorderFactory.createTitledBorder("Search Results")); // Search table set up JTable searchTable = new JTable(getCDStubModel()); JScrollPane trackListScrollPane = new JScrollPane(searchTable); + trackListPanel.add(searchStatusLabel, BorderLayout.NORTH); trackListPanel.add(trackListScrollPane, BorderLayout.CENTER); // Add the Track List panel to the main panel panel.add(trackListPanel, BorderLayout.CENTER); // CD Search Panel set up - JPanel cdSearchPanel = new JPanel(); cdSearchPanel.setBorder(BorderFactory.createTitledBorder("Search")); JTextField searchField = new JTextField(15); @@ -102,26 +104,36 @@ private JPanel searchPanel() { if (searchTypeComboBox.getSelectedItem() == null) { return; } + setSearchStatus("Preforming search...", "blue"); if (searchTypeComboBox.getSelectedItem().equals("CDStub")) { - MusicBrainzJSONReader reader = sendRequest("cdstub", searchField.getText()); - - // Get CDStubs and set the table model - MusicBrainzCDStub[] cdStubs = reader.getCDStubs(); - searchTable.setModel(reader.getCDStubsAsTableModel(cdStubs)); + Constants.THREAD_MANAGER.submit(() -> { + MusicBrainzJSONReader reader = sendRequest("cdstub", searchField.getText()); + + // Get CDStubs and set the table model + MusicBrainzCDStub[] cdStubs = reader.getCDStubs(); + searchTable.setModel(reader.getCDStubsAsTableModel(cdStubs)); + setSearchStatus("All done!", "green"); + }); } else if (searchTypeComboBox.getSelectedItem().equals("Artist")) { - MusicBrainzJSONReader reader = sendRequest("artist", searchField.getText()); - - // Get Artists and set the table model - MusicBrainzArtist[] artists = reader.getArtists(); - searchTable.setModel(reader.getArtistsAsTableModel(artists)); + Constants.THREAD_MANAGER.submit(() -> { + MusicBrainzJSONReader reader = sendRequest("artist", searchField.getText()); + + // Get Artists and set the table model + MusicBrainzArtist[] artists = reader.getArtists(); + searchTable.setModel(reader.getArtistsAsTableModel(artists)); + setSearchStatus("All done!", "green"); + }); } else if (searchTypeComboBox.getSelectedItem().equals("Release")) { - MusicBrainzJSONReader reader = sendRequest("release", searchField.getText()); - - // Get Releases and set the table model - MusicBrainzRelease[] releases = reader.getReleases(); - searchTable.setModel(reader.getReleasesAsTableModel(releases)); + Constants.THREAD_MANAGER.submit(() -> { + MusicBrainzJSONReader reader = sendRequest("release", searchField.getText()); + + // Get Releases and set the table model + MusicBrainzRelease[] releases = reader.getReleases(); + searchTable.setModel(reader.getReleasesAsTableModel(releases)); + setSearchStatus("All done!", "green"); + }); } else { - // how does this even happen + // how does this even happen? JOptionPane.showMessageDialog(panel, "Please select a search type."); } resizeColumnWidths(searchTable); @@ -286,7 +298,7 @@ public void changedUpdate(DocumentEvent e) {} // Not used userAgentPanel.add(fullAgentPanel, BorderLayout.NORTH); userAgentPanel.add(userAgentInputPanel, BorderLayout.CENTER); - // Add sub panels to main panel + // Add subpanels to the main panel panel.add(userAgentPanel); panel.add(fontPanel); @@ -294,7 +306,7 @@ public void changedUpdate(DocumentEvent e) {} // Not used } /** - * Helper method to resize a tables columns to fit the largest element. + * Helper method to resize a table column to fit the largest element. * @param table The table to resize. */ private void resizeColumnWidths(JTable table) { @@ -313,4 +325,8 @@ private void resizeColumnWidths(JTable table) { tableColumn.setPreferredWidth(preferredWidth + 2); // Add padding } } + + public void setSearchStatus(String status, String color) { + searchStatusLabel.setText("Status: " + status + ""); + } } \ No newline at end of file From 85fee4e14e2a9ac12cb0ff524f68138118091117 Mon Sep 17 00:00:00 2001 From: alex_mclean <116386669+EatSleepProgramRepeat@users.noreply.github.com> Date: Sun, 13 Apr 2025 22:14:40 -0400 Subject: [PATCH 3/5] set up multithreading --- src/main/java/com/CDPrintable/Constants.java | 5 +- .../MusicBrainzJSONReader.java | 68 +++++++++++++++---- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/CDPrintable/Constants.java b/src/main/java/com/CDPrintable/Constants.java index 7714e80..49c923a 100644 --- a/src/main/java/com/CDPrintable/Constants.java +++ b/src/main/java/com/CDPrintable/Constants.java @@ -15,4 +15,7 @@ public class Constants { public static final String VERSION = "1.6.4"; public static final boolean USER_AGENT_EMAIL_CHANGED = false; -} + + public static final int MAX_THREADS = 4; + public static final ThreadManager THREAD_MANAGER = new ThreadManager(); +} \ No newline at end of file diff --git a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java index 403c85d..e283cc6 100644 --- a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java +++ b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java @@ -10,12 +10,16 @@ package com.CDPrintable.MusicBrainzResources; +import com.CDPrintable.Constants; import com.google.gson.*; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; import javax.swing.table.DefaultTableModel; import java.lang.reflect.Array; +import java.util.concurrent.Future; public class MusicBrainzJSONReader { private final JsonObject json; @@ -36,6 +40,28 @@ public MusicBrainzJSONReader(String json) throws IllegalArgumentException { this.json = tempJsonObject; } + /** + * This method splits a JSON array into smaller chunks for multithreading. + * @param jsonArray The JSON array to split. + */ + public JsonArray[] splitJsonArray(JsonArray jsonArray) { + int chunkSize = Constants.MAX_THREADS; + int arraySize = jsonArray.size(); + int numChunks = (int) Math.ceil((double) arraySize / chunkSize); + JsonArray[] chunks = new JsonArray[numChunks]; + + for (int i = 0; i < numChunks; i++) { + int start = i * chunkSize; + int end = Math.min(start + chunkSize, arraySize); + JsonArray chunk = new JsonArray(); + for (int j = start; j < end; j++) { + chunk.add(jsonArray.get(j)); + } + chunks[i] = chunk; + } + return chunks; + } + /** * Parses a JSON array and creates a new array of the same type as the provided array. * @@ -49,22 +75,40 @@ public MusicBrainzJSONReader(String json) throws IllegalArgumentException { */ @SuppressWarnings("unchecked") private T[] parseJsonArray(String key, JsonArrayProcessor processor, T[] array) { - // Make sure the key exists in the JSON object - if (!json.has(key)) { - // Return an empty array if the JSON object does not have the key - array = (T[]) Array.newInstance(array.getClass().getComponentType(), 0); - return array; + if(!json.has(key)) { + // Return an empty array if the key does not exist + return (T[]) Array.newInstance(array.getClass().getComponentType(), 0); } - // Make a JSON array using the provided key + JsonArray jsonArray = json.getAsJsonArray(key); - array = (T[]) Array.newInstance(array.getClass().getComponentType(), jsonArray.size()); + JsonArray[] chunks = splitJsonArray(jsonArray); - // Process each JSON object in the array - for (int i = 0; i < jsonArray.size(); i++) { - JsonObject jsonObject = jsonArray.get(i).getAsJsonObject(); - array[i] = processor.process(jsonObject); // Uses provided processor to process the JSON object + // Use multithreading to process the JSON array + // This is a list of promises that promise to return a list + // of whatever type T is, e.g., MusicBrainzRelease. + List>> futures = new ArrayList<>(); + for (JsonArray chunk : chunks) { + // Submit a task to the thread manager + futures.add(Constants.THREAD_MANAGER.submit(() -> { + List result = new ArrayList<>(); + for (JsonElement element : chunk) { + JsonObject jsonObject = element.getAsJsonObject(); + result.add(processor.process(jsonObject)); + } + return result; + })); } - return array; + + List resultList = new ArrayList<>(); + try { + for (Future> future : futures) { + resultList.addAll(future.get()); + } + } catch (Exception e) { + e.printStackTrace(); + } + + return resultList.toArray((T[]) Array.newInstance(array.getClass().getComponentType(), resultList.size())); } /** From 3e13199623464514fb6ff4950d4382751c97335e Mon Sep 17 00:00:00 2001 From: alex_mclean <116386669+EatSleepProgramRepeat@users.noreply.github.com> Date: Sun, 13 Apr 2025 22:17:02 -0400 Subject: [PATCH 4/5] better error thingamabob? --- .../CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java index e283cc6..23e202e 100644 --- a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java +++ b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java @@ -105,7 +105,7 @@ private T[] parseJsonArray(String key, JsonArrayProcessor processor, T[] resultList.addAll(future.get()); } } catch (Exception e) { - e.printStackTrace(); + JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } return resultList.toArray((T[]) Array.newInstance(array.getClass().getComponentType(), resultList.size())); From 8ed161e6dd18734311926e024e58df23030b1b39 Mon Sep 17 00:00:00 2001 From: alex_mclean <116386669+EatSleepProgramRepeat@users.noreply.github.com> Date: Sun, 13 Apr 2025 22:17:29 -0400 Subject: [PATCH 5/5] import swing --- .../CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java index 23e202e..f19bc71 100644 --- a/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java +++ b/src/main/java/com/CDPrintable/MusicBrainzResources/MusicBrainzJSONReader.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Locale; +import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.lang.reflect.Array; import java.util.concurrent.Future;