I've been extremely successful in making a 2D RPG using some of Bucky's Java Game Development tutorials from TheNewBoston, and generally just pushing my own envelope. Now I've run into a problem I CANNOT solve. I've tried for days now, and when you see what the problem is, you will understand my frustration on the matter.

I've tried to implement a simple MIDIPlayer (class-code supplied at the bottom). The thing works great, until I export to .jar, then no sound plays, but the game keeps chugging away. So, I read up on it, and apparently there's some problem with soundbanks, so I installed Java's deluxe soundbank, to no avail.

NOW, finally I've made it work...but ONLY if the MIDI-files are in the same folder as the .jar file, or a folder in that directory. So I read up on THAT, and it seems you're not supposed to use the standard filepath-method when loading streams (mainly audio) from a .jar file. ONLY if you're referencing an actual file in the folder of the .jar, as per example:getSequence("SomeMIDIfile.mid");

or in a dedicated folder next to it, as per example:getSequence("music/SomeMIDIfile.mid");

In fact, you're supposed to reference it using the URL class, and possibly converting that to a URI, and then use the path you can get from there. So I tried that in MANY different forms, and the weirdest thing happens!

The first couple of tries, I got a nullpointer exception, because I was trying to find the correct path-syntax, and when I finally got it, it gave me an error, stating: "Java cannot find the file at the specified location: " and then proceeds to write the correct path, just to mock me

SO, I'm not getting a nullpointer, because it does find the file...but it doesn't find the file...The file has been imported into my project on the path: src/snm/music/midis/SomeMIDI.midThese are the methods I've tried to use to get a usable path (tried ALL of them with every single combination of directories in the path above), and they all end up giving me that terrible error-message when I hit the right "spot".

As I said, I've also tried to convert the URL to a URI to circumvent the %20's which appear in place of spaces when getting a file-path. I've ALSO tried to rewrite the MIDIPlayer so getSequence doesn't work with File(), but with FileInputStream() instead, still to no avail. It is the same thing with wav-files. Haven't tried MP3s, but logically it should be the same.

I'm at wit's end...and I have exhausted Google. They called me and told me to stop searching for JAVA +MIDI +ARGH over and over again...something about their revenues.

// load 2 pieces of music// This commented out one doesn't give a nullpointer exception, because the path IS right,// but it doesn't play anything...The two underneath it, play the MIDI happily when// executing the .jar file, but only if the .mid is in the same folder.

/** This method is called by the sound system when a meta event occurs. In this case, when the end-of-track meta event is received, the sequence is restarted if looping is on. */publicvoidmeta(MetaMessageevent) {if (event.getType() == END_OF_TRACK_MESSAGE) {if (sequencer != null && sequencer.isOpen() && loop) {sequencer.start(); } } }

Are your .mid files making it into your jar? If so, getClass().getResource("/snm/music/midis/SomeMIDIfile.mid") should do what you want. Don't bother constructing URL by hand, since it's not aware of the scheme you need to access it, whereas getResource() is.

If you see it in the jar and you know you have the right resource path, I think your best bet is to step through it in a debugger. Could be the library you're using is doing something stupid through no fault of your own.

Thanks for your reply! I checked, and the .mid's are in the right place in the .jar, and tried almost exactly what you wrote.

Thing is, the MidiSystem.getSequence() takes a String, so I have to add .getPath() to get the path out of the URL returned by getClass().getResource(). Maybe that's what's destroying the "real" path? I checked what getClass().getResource() returns.

This is it:file:/D:/Egne%20Projekter/SwordsAndMagic%20v9%20test4.jar!/snm/music/midis/SomeMIDI.mid

Looks right...but it's still not working. I'd think it was because of a missing soundbank in the .jar, but as I mentioned, when I reference a MIDI outside the .jar, it plays perfectly.

Hi. Thanks for your reply! Sorry, that was a typo, or a brainfart or whatever. I wanted to say, that the implemented MidiPlayer-class wants a String as a location-reference. The MidiSystem.getResource used in it, wants a File. My problem, I think, is referencing to the file-path correctly, for MidiSystem to understand it. Am I right when I say that one cannot instantiate a File() using a normal String-reference when trying to access something in a .jar?

The use of new File() in 'my' MidiPlayer class should probably be exchanged for an InputStream. I tried that, but to no avail. I will try again, though. It was pretty late the last time ^^

// This commented out one doesn't give a nullpointer exception, because the path IS right,// but it doesn't play anything...The two underneath it, play the MIDI happily when// executing the .jar file, but only if the .mid is in the same folder.

THANK YOU! This was exactly what I needed. I wonder why nothing like this came up during my searches. I am sort of a noob at Java, but I feel like I'm getting a good grip on things. None of my teachers could tell me this, and I'm in 3rd semester of computer science! That's so embarrassing.

Thank you SO much, H3rnst and ra4king. This solved everything! It runs in both the IDE and from the .jar now.I just read your great replies in the List-thread. Very interesting thoughts!

@sproingie:I really wanted to go around that whole File-thing, and just put the stream right into that baby, and now it does. You we're all right

You should not use getClass() for resource loading as this will break when the class is sub classed. Use MidiPlayer.class.getResource() to have a fixed starting point.Also make sure that the resources are in the same JAR as the class you use as a base reference otherwise you could get issues depending on how the class loaders are setup.

You should not use getClass() for resource loading as this will break when the class is sub classed. Use MidiPlayer.class.getResource() to have a fixed starting point.Also make sure that the resources are in the same JAR as the class you use as a base reference otherwise you could get issues depending on how the class loaders are setup.

It will only "break" for relative paths and subclasses in a different package, in that it will be relative to the subclass in the new subclass, but you could also call that proper behavior. You should always be using absolute resource paths anyway unless you specifically want some resource co-located with the class.

Separate jars are not a problem -- you only get separate classloaders if you're writing web apps or OSGi or if you grabbed the boot classloader for some crazy reason (like calling getClassLoader on any java.lang.* class)

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org