Initial code commit - POC for .dci file writing/metadata extraction

This commit is contained in:
kacarmichael 2025-06-08 02:25:13 -05:00
parent 573fe97f61
commit 8f3da69661
16 changed files with 456 additions and 0 deletions

15
.idea/git_toolbox_prj.xml generated Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageIssueKeyValidationOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
<option name="commitMessageValidationEnabledOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
</component>
</project>

View File

@ -0,0 +1,100 @@
// === MEMBERS ===
CREATE (:Member {name: "Onye"});
CREATE (:Member {name: "Eric Westerhold"});
CREATE (:Member {name: "Andrew Manzaneres"});
// === CORPS ===
CREATE (:Corps {name: "Bluecoats"});
CREATE (:Corps {name: "Blue Devils"});
// === SHOWS ===
CREATE (:Show {title: "To Look For America", year: 2017});
CREATE (:Show {title: "Kinetic Noise", year: 2015});
CREATE (:Show {title: "Re:Write of Spring", year: 2013});
// === COMPOSERS ===
MERGE (ps:Composer {name: "Paul Simon"})
MERGE (rw:Composer {name: "Rufus Wainwright"})
MERGE (de:Composer {name: "Duke Ellington"})
MERGE (is:Composer {name: "Igor Stravinsky"})
MERGE (sb:Composer {name: "Steven Bryant"})
MERGE (lc:Composer {name: "Leonard Cohen"})
MERGE (sr:Composer {name: "Steve Reich"})
MERGE (ja:Composer {name: "John Adams"})
MERGE (jan:Composer {name: "John Anderson"})
MERGE (bi:Composer {name: "Bon Iver"})
MERGE (mg:Composer {name: "Michael Gordon"})
MERGE (tb:Composer {name: "The Books"})
MERGE (uz:Composer {name: "Univers Zero"})
// === PIECES ===
MERGE (a:Piece {title: "America"})-[:COMPOSED_BY]->(ps)
MERGE (ag:Piece {title: "Agnus Dei"})-[:COMPOSED_BY]->(rw)
MERGE (sp:Piece {title: "Spring"})-[:COMPOSED_BY]->(de)
MERGE (eb:Piece {title: "Ebony Concerto"})-[:COMPOSED_BY]->(is)
MERGE (cc:Piece {title: "Concerto"})-[:COMPOSED_BY]->(sb)
MERGE (hl:Piece {title: "Hallelujah"})-[:COMPOSED_BY]->(lc)
MERGE (cl:Piece {title: "City Life"})-[:COMPOSED_BY]->(sr)
MERGE (rs:Piece {title: "The Rite of Spring"})-[:COMPOSED_BY]->(is)
MERGE (sl:Piece {title: "Shaker Loops"})-[:COMPOSED_BY]->(ja)
MERGE (sl)-[:COMPOSED_BY]->(jan)
MERGE (ec:Piece {title: "Electric Counterpoint"})-[:COMPOSED_BY]->(sr)
MERGE (wd:Piece {title: "Woods"})-[:COMPOSED_BY]->(bi)
MERGE (gt:Piece {title: "Gene Takes A Drink"})-[:COMPOSED_BY]->(mg)
MERGE (ad:Piece {title: "An Animated Description Of Mr Maps"})-[:COMPOSED_BY]->(tb)
MERGE (ds:Piece {title: "Dense"})-[:COMPOSED_BY]->(uz);
// === RELATIONSHIPS: Shows → Corps ===
MATCH (s1:Show {title: "To Look For America"}), (c1:Corps {name: "Bluecoats"})
CREATE (s1)-[:FIELD_BY]->(c1);
MATCH (s2:Show {title: "Kinetic Noise"}), (c2:Corps {name: "Bluecoats"})
CREATE (s2)-[:FIELD_BY]->(c2);
MATCH (s3:Show {title: "Re:Write of Spring"}), (c3:Corps {name: "Blue Devils"})
CREATE (s3)-[:FIELD_BY]->(c3);
// === RELATIONSHIPS: Members → Shows ===
MATCH (m1:Member {name: "Onye"}), (s1:Show {title: "To Look For America"})
CREATE (m1)-[:PERFORMED_IN]->(s1);
MATCH (m2:Member {name: "Eric Westerhold"}), (s2:Show {title: "Kinetic Noise"})
CREATE (m2)-[:PERFORMED_IN]->(s2);
MATCH (m3:Member {name: "Andrew Manzaneres"}), (s3:Show {title: "Re:Write of Spring"})
CREATE (m3)-[:PERFORMED_IN]->(s3);
// === RELATIONSHIPS: Shows → Pieces ===
MATCH (s:Show {title: "To Look For America"}),
(a:Piece {title: "America"}),
(ag:Piece {title: "Agnus Dei"}),
(sp:Piece {title: "Spring"}),
(eb:Piece {title: "Ebony Concerto"}),
(cc:Piece {title: "Concerto"}),
(hl:Piece {title: "Hallelujah"}),
(cl:Piece {title: "City Life"})
CREATE (s)-[:FEATURED]->(a),
(s)-[:FEATURED]->(ag),
(s)-[:FEATURED]->(sp),
(s)-[:FEATURED]->(eb),
(s)-[:FEATURED]->(cc),
(s)-[:FEATURED]->(hl),
(s)-[:FEATURED]->(cl);
MATCH (s:Show {title: "Re:Write of Spring"}),
(rs:Piece {title: "The Rite of Spring"})
CREATE (s)-[:FEATURED]->(rs);
MATCH (s:Show {title: "Kinetic Noise"}),
(sl:Piece {title: "Shaker Loops"}),
(ec:Piece {title: "Electric Counterpoint"}),
(wd:Piece {title: "Woods"}),
(gt:Piece {title: "Gene Takes A Drink"}),
(ad:Piece {title: "An Animated Description Of Mr Maps"}),
(ds:Piece {title: "Dense"})
CREATE (s)-[:FEATURED]->(sl),
(s)-[:FEATURED]->(ec),
(s)-[:FEATURED]->(wd),
(s)-[:FEATURED]->(gt),
(s)-[:FEATURED]->(ad),
(s)-[:FEATURED]->(ds);

View File

@ -0,0 +1,29 @@
import com.dci.aaronic.player.io.DCIFileMetadataContainer;
import com.dci.aaronic.player.io.DCIFileWriter;
import java.io.File;
import java.io.IOException;
public class Scratch {
public static void main(String[] args) {
File test_file = new File("C:\\Users\\kacar\\Desktop\\Data Projects\\DCIPlayer\\player.api\\player.api\\assets\\Bluecoats_2015_Kinetic_Noise.mp4");
DCIFileMetadataContainer metadata = null;
try {
metadata = DCIFileMetadataContainer.extract(test_file.getName());
System.out.println(metadata);
}
catch (IOException e) {
e.printStackTrace();
}
try {
File testOut = new File("C:\\Users\\kacar\\Desktop\\Data Projects\\DCIPlayer\\player.api\\player.api\\assets\\Bluecoats_2015_Kinetic_Noise.dci");
DCIFileWriter writer = new DCIFileWriter();
writer.write(test_file, metadata, testOut);
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,13 @@
package com.dci.aaronic.player.api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,91 @@
package com.dci.aaronic.player.io;
import com.dci.aaronic.player.models.Corps;
import com.dci.aaronic.player.utils.Utils;
import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DCIFileMetadataContainer {
public int year;
public String title;
public String corps;
public DCIFileMetadataContainer() {}
public DCIFileMetadataContainer(int year, String title, String corps) {
this.year = year;
this.title = title;
this.corps = corps;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getCorps() {
return corps;
}
public void setCorps(String corps) {
this.corps = corps;
}
public static DCIFileMetadataContainer extract(String fileName) throws IOException {
Pattern yearPattern = Pattern.compile("\\d{4}");
Matcher yearMatcher = yearPattern.matcher(fileName);
String year = null;
if (yearMatcher.find()) {
year = yearMatcher.group();
}
String foundCorps = null;
for (Corps corps: Utils.ALL_CORPS) {
if (fileName.contains(corps.getName())) {
foundCorps = corps.getName();
break;
}
}
String fileExtension = fileName.substring(fileName.lastIndexOf("."));
String title = fileName;
if (foundCorps != null) {
title = title.replace(foundCorps, "");
}
if (year != null) {
title = title.replace(year, "");
}
if (fileExtension != null) {
title = title.replace(fileExtension, "");
}
title = title.replace("_", " ");
title = title.trim();
return new DCIFileMetadataContainer(Integer.parseInt(year), title, foundCorps);
}
public String toString() {
return "DCIFileMetadataContainer{" +
"year=" + year +
", title='" + title + '\'' +
", corps='" + corps + '\'' +
'}';
}
}

View File

@ -0,0 +1,28 @@
package com.dci.aaronic.player.io;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class DCIFileMetadataSerializer {
private static final ObjectMapper objectMapper = new ObjectMapper();
public static byte[] serialize(DCIFileMetadataContainer metadata) throws IOException {
try {
return objectMapper.writeValueAsBytes(metadata);
}
catch (IOException e) {
throw new IOException("Error serializing metadata: " + e);
}
}
public static DCIFileMetadataContainer deserialize(byte[] bytes) throws IOException {
try {
return objectMapper.readValue(bytes, DCIFileMetadataContainer.class);
}
catch (IOException e) {
throw new IOException("Error deserializing metadata: " + e);
}
}
}

View File

@ -0,0 +1,36 @@
package com.dci.aaronic.player.io;
import java.io.*;
import java.util.Arrays;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
public class DCIFileReader {
private static final byte[] MAGIC = ".DCI".getBytes();
private final ObjectMapper objectMapper = new ObjectMapper();
public void read(File file) throws IOException{
try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
byte[] magic = new byte[MAGIC.length];
in.readFully(magic);
if (!Arrays.equals(magic, MAGIC)) {
throw new IOException("Header mismatch - not a valid .DCI file");
}
int version = in.readInt();
if (version != 1) {
throw new IOException("Unsupported version: " + version);
}
int metaLength = in.readInt();
byte[] meta = new byte[metaLength];
in.readFully(meta);
Map<String, Object> metaMap = objectMapper.readValue(meta, Map.class); // <1>
System.out.println(metaMap);
byte[] content = in.readAllBytes();
}
}
}

View File

@ -0,0 +1,28 @@
package com.dci.aaronic.player.io;
import jdk.jshell.spi.ExecutionControl;
import java.io.*;
import java.nio.file.Files;
//Convert MP4 to DCI
public class DCIFileWriter {
private static final byte[] MAGIC = ".DCI".getBytes();
public void write(File file, DCIFileMetadataContainer metadata, File outputFile) throws IOException {
byte[] content = Files.readAllBytes(file.toPath());
try (DataOutputStream out = new DataOutputStream(new FileOutputStream(outputFile))) {
out.write(MAGIC);
out.writeInt(1);
byte[] meta = DCIFileMetadataSerializer.serialize(metadata);
out.writeInt(meta.length);
out.write(meta);
out.write(content);
}
catch (IOException e) {
System.out.println("Error creating DCI file: " + e);
}
}
}

View File

@ -0,0 +1,22 @@
package com.dci.aaronic.player.models;
public class Corps {
public String name;
public int foundingYear;
public String homeCity;
public String homeState;
public String[] aliases;
public Corps(String name, int foundingYear, String homeCity, String homeState, String[] aliases) {
this.name = name;
this.foundingYear = foundingYear;
this.homeCity = homeCity;
this.homeState = homeState;
this.aliases = aliases;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,8 @@
package com.dci.aaronic.player.models;
public class CorpsProgram {
private Corps _corps;
private MusicSelection[] _reportoires;
private int _year;
}

View File

@ -0,0 +1,10 @@
package com.dci.aaronic.player.models;
public class CorpsStaff {
public Member President;
public Member BrassCaptionHead;
public Member PercussionCaptionHead;
public Member VisualCaptionHead;
}

View File

@ -0,0 +1,4 @@
package com.dci.aaronic.player.models;
public class Member {
}

View File

@ -0,0 +1,9 @@
package com.dci.aaronic.player.models;
public class MusicSelection {
public String title;
public String subtitle;
public String composer;
}

View File

@ -0,0 +1,31 @@
package com.dci.aaronic.player.models;
public enum Section {
BRASS,
PERCUSSION,
COLORGUARD;
public enum Subsection {
TRUMPETS(BRASS),
MELLOPHONES(BRASS),
BARITONES(BRASS),
CONTRAS(BRASS),
SNARES(PERCUSSION),
TENORS(PERCUSSION),
BASSES(PERCUSSION),
CYMBALS(PERCUSSION),
FRONTENSEMBLE(PERCUSSION),
FLAGS(COLORGUARD),
RIFLESANDSABRES(COLORGUARD);
private final Section _section;
Subsection(Section section) {
_section = section;
}
public Section getSection() {
return _section;
}
}
}

View File

@ -0,0 +1,19 @@
package com.dci.aaronic.player.utils;
import com.dci.aaronic.player.models.Corps;
import java.util.List;
public class Utils {
private Utils() {}
public static List<Corps> ALL_CORPS = List.of(
new Corps("Bluecoats", 1974, "Canton", "Ohio",
new String[]{
"Bluecoats",
"Bloo"
})
);
}

View File

@ -0,0 +1,13 @@
package com.dci.aaronic.player.api;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() {
}
}