Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import java.util.Locale;

public class MusicBrainzArtist {
public class MusicBrainzArtist extends MusicBrainzDataObject {
private String name;
private String dateOrganized; // May only be present for groups
private String birthDate; // May only be present for people
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

package com.CDPrintable.MusicBrainzResources;

public class MusicBrainzCDStub {
public class MusicBrainzCDStub extends MusicBrainzDataObject {
private String id;
private String title;
private String[] artists;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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 is an abstract data class for MusicBrainz data objects.
*/

package com.CDPrintable.MusicBrainzResources;

public abstract class MusicBrainzDataObject {
private String id;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package com.CDPrintable.MusicBrainzResources;

import com.CDPrintable.Constants;
import com.CDPrintable.ProgramWindow;
import com.google.gson.*;

import java.util.ArrayList;
Expand All @@ -27,7 +28,7 @@ public class MusicBrainzJSONReader {

/*
* Creates a MusicBrainzJSONReader from a JSON string.
* @param json The JSON string.
* @param JSON The JSON string.
* @throws IllegalArgumentException If the JSON is invalid.
*/
public MusicBrainzJSONReader(String json) throws IllegalArgumentException {
Expand Down Expand Up @@ -240,6 +241,49 @@ public MusicBrainzArtist[] getArtists() {
}, new MusicBrainzArtist[0]);
}

/**
* Gets track listing from the JSON from a discID.
*/
public MusicBrainzTrack[] getTracks() {
return parseJsonArray("tracks", jsonObject -> {
String title = jsonHasAndIsNotNull(jsonObject, "title") ? jsonObject.get("title").getAsString() : null;
String artist = jsonHasAndIsNotNull(jsonObject, "artist") ? jsonObject.get("artist").getAsString() : null;
int length = jsonHasAndIsNotNull(jsonObject, "length") ? jsonObject.get("length").getAsInt() : -1;

return new MusicBrainzTrack(title, artist, length);
}, new MusicBrainzTrack[0]);
}

/**
* Gets track listing from a release.
* @return An array of MusicBrainzTrack objects.
*/
public MusicBrainzTrack[] getReleaseTracks() {
List<MusicBrainzTrack> trackList = new ArrayList<>();

JsonArray mediaArray = json.getAsJsonArray("media");
for (JsonElement mediaElement : mediaArray) {
JsonObject mediaObject = mediaElement.getAsJsonObject(); // Cast each element to JsonObject
JsonArray trackArray = mediaObject.getAsJsonArray("tracks");
for (JsonElement trackElement : trackArray) {
JsonObject trackObject = trackElement.getAsJsonObject();
String title = jsonHasAndIsNotNull(trackObject, "title") ? trackObject.get("title").getAsString() : null;
int length = jsonHasAndIsNotNull(trackObject, "length") ? trackObject.get("length").getAsInt() : -1;
int trackNumber = -1;

if (trackObject.has("number")) {
trackNumber = trackObject.get("number").getAsInt();
} else if (trackObject.has("position")) {
trackNumber = trackObject.get("position").getAsInt();
}

trackList.add(new MusicBrainzTrack(title, null, length, trackNumber));
}
}

return trackList.toArray(new MusicBrainzTrack[0]);
}

/**
* Creates a table model from an array of items.
* @param items The array of items. Usually a MusicBrainzRelease, MusicBrainzCDStub, etc.
Expand All @@ -266,15 +310,15 @@ private DefaultTableModel createTableModel(Object[] items, String[] columnNames,
* @return The table model.
*/
public DefaultTableModel getReleasesAsTableModel(MusicBrainzRelease[] releaseArray) {
String[] columnNames = {"Release Name", "Artist", "Track Count", "Date", ""};
String[] columnNames = {"Release Name", "Artist", "Track Count", "Date"};
return createTableModel(releaseArray, columnNames, item -> {
MusicBrainzRelease release = (MusicBrainzRelease) item;
ProgramWindow.addId(getOrDefault(release.getId()));
return new String[]{
getOrDefault(release.getTitle()),
getOrDefault(release.getArtistsAsString()),
getOrDefault(release.getTrackCount() != -1 ? String.valueOf(release.getTrackCount()) : null),
getOrDefault(release.getDate()),
""
getOrDefault(release.getDate())
};
});
}
Expand All @@ -285,14 +329,14 @@ public DefaultTableModel getReleasesAsTableModel(MusicBrainzRelease[] releaseArr
* @return The table model.
*/
public DefaultTableModel getCDStubsAsTableModel(MusicBrainzCDStub[] cdStubArray) {
String[] columnNames = {"Disc Name", "Artist", "Track Count", ""};
String[] columnNames = {"Disc Name", "Artist", "Track Count"};
return createTableModel(cdStubArray, columnNames, item -> {
MusicBrainzCDStub cdStub = (MusicBrainzCDStub) item;
ProgramWindow.addId(getOrDefault(cdStub.getId()));
return new String[]{
getOrDefault(cdStub.getTitle()),
getOrDefault(cdStub.getArtistsAsString()),
getOrDefault(String.valueOf(cdStub.getTrackCount())),
""
getOrDefault(String.valueOf(cdStub.getTrackCount()))
};
});
}
Expand All @@ -303,9 +347,10 @@ public DefaultTableModel getCDStubsAsTableModel(MusicBrainzCDStub[] cdStubArray)
* @return The table model.
*/
public DefaultTableModel getArtistsAsTableModel(MusicBrainzArtist[] artistArray) {
String[] columnNames = {"Name", "Date Organised", "Birthdate", "Sort Name", "Gender", "Type", "Disambiguation", "Life Span", "Country", ""};
String[] columnNames = {"Artist Name", "Date Organised", "Birthdate", "Sort Name", "Gender", "Type", "Disambiguation", "Life Span", "Country"};
return createTableModel(artistArray, columnNames, item -> {
MusicBrainzArtist artist = (MusicBrainzArtist) item;
ProgramWindow.addId(getOrDefault(artist.getId()));
return new String[] {
getOrDefault(artist.getName()),
getOrDefault(artist.getDateOrganized()),
Expand All @@ -315,12 +360,28 @@ public DefaultTableModel getArtistsAsTableModel(MusicBrainzArtist[] artistArray)
getOrDefault(artist.getType()),
getOrDefault(artist.getDisambiguation()),
getOrDefault(artist.getLifeSpan()),
getOrDefault(artist.getCountry()),
""
getOrDefault(artist.getCountry())
};
});
}

/**
* Gets the tracks as a table model.
* @param trackArray The array of tracks.
*/
public DefaultTableModel getTracksAsTableModel(MusicBrainzTrack[] trackArray) {
String[] columnNames = {"#", "Track Name", "Artist", "Length"};
return createTableModel(trackArray, columnNames, item -> {
MusicBrainzTrack track = (MusicBrainzTrack) item;
return new String[]{
getOrDefault(Integer.toString(track.getTrackNumber())),
getOrDefault(track.getTitle()),
getOrDefault(track.getArtist()),
getOrDefault(track.getLength())
};
});
}

/**
* Functional interface for extracting data from an item.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

package com.CDPrintable.MusicBrainzResources;

public class MusicBrainzRelease {
public class MusicBrainzRelease extends MusicBrainzDataObject {
private String title;
private String[] artists;
private String date;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,7 @@ public MusicBrainzRequest(String queryType, String query, String otherParams) {
this.otherParams = otherParams;
}

/**
* Builds the request URL for the Musicbrainz API.
* @return The request URL.
*/
public String buildRequestURL() {
private StringBuilder startRequestBuild() {
StringBuilder url = new StringBuilder("https://musicbrainz.org/ws/2/");

switch (queryType) {
Expand All @@ -64,17 +60,51 @@ public String buildRequestURL() {
default:
throw new IllegalArgumentException("Invalid query type: " + queryType);
}
url.append("?query=").append(query);
url.append("&fmt=json");

return url;
}

private String endRequestBuild(StringBuilder url) {
if (!url.toString().contains("?")) {
url.append("?fmt=json");
} else {
url.append("&fmt=json");
}

if (otherParams != null) {
url.append(otherParams);
}

return url.toString()
.replace(" ", "%20")
return replaceAllIllegalChars(url.toString());
}

private String replaceAllIllegalChars(String str) {
return str.replace(" ", "%20")
.replace("\"", "%22");
}

/**
* Builds the request URL for the Musicbrainz API.
* @return The request URL.
*/
public String buildRequestURL() {
StringBuilder url = startRequestBuild();
url.append("?query=").append(query);

return endRequestBuild(url);
}

/**
* Builds the request URL for the Musicbrainz API to get a track list.
* @return The request URL.
*/
public String buildTrackListURL() {
StringBuilder url = startRequestBuild();
url.append("/").append(query).append("?inc=recordings");

return endRequestBuild(url);
}

/**
* Gets the query string.
* @return The query string.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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 holds data for a track from the MusicBrainz API.
*/

package com.CDPrintable.MusicBrainzResources;

public class MusicBrainzTrack extends MusicBrainzDataObject {
private String title;
private String artist;
private int length;
private int trackNumber;

public MusicBrainzTrack(String title, String artist, int length) {
this.title = title;
this.artist = artist;
this.length = length;
this.trackNumber = 0;
}

public MusicBrainzTrack(String title, String artist, int length, int trackNumber) {
this.title = title;
this.artist = artist;
this.length = length;
this.trackNumber = trackNumber;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getArtist() {
return artist;
}

public void setArtist(String artist) {
this.artist = artist;
}

public String getLength() {
int seconds = length / 1000;
int minutes = (seconds % 3600) / 60;
seconds = seconds % 60;

return String.format("%02d:%02d", minutes, seconds);
}

public void setLength(int length) {
this.length = length;
}

public int getTrackNumber() {
return trackNumber;
}

public void setTrackNumber(int trackNumber) {
this.trackNumber = trackNumber;
}
}
Loading