//=============================================================================================== //CDDA.EXE //Copyright (c), Firelight Technologies Pty, Ltd, 1999-2004. // //Use FMOD stream API to do digital CD playback. Also demonstrates how to use FMOD to //generate a CDDB query. //=============================================================================================== /** * I've ported the C++ FMOD example to use it with NativeFmod * * @author J�r�me JOUVIE (Jouvieje) * * WANT TO CONTACT ME ? * E-mail : * jerome.jouvie@gmail.com * My web sites : * http://jerome.jouvie.free.fr/ */ package org.jouvieje.Fmod.Examples; import java.nio.ByteBuffer; import javax.swing.JPanel; import org.jouvieje.Fmod.Fmod; import org.jouvieje.Fmod.Init; import org.jouvieje.Fmod.Defines.FSOUND_MISC_VALUES; import org.jouvieje.Fmod.Defines.FSOUND_MODES; import org.jouvieje.Fmod.Defines.VERSIONS; import org.jouvieje.Fmod.Examples.Util.ConsoleGUI; import org.jouvieje.Fmod.Examples.Util.FmodExampleFrame; import org.jouvieje.Fmod.Exceptions.InitException; import org.jouvieje.Fmod.Misc.BufferUtils; import org.jouvieje.Fmod.Misc.Pointer; import org.jouvieje.Fmod.Misc.PointerUtils; import org.jouvieje.Fmod.Structures.FSOUND_STREAM; import org.jouvieje.Fmod.Structures.FSOUND_TOC_TAG; import org.jouvieje.libloader.LibLoader; public class CDDA extends ConsoleGUI implements FSOUND_MODES, FSOUND_MISC_VALUES, VERSIONS { private static final long serialVersionUID = 1L; public static void main(String[] args) { new FmodExampleFrame(new CDDA()); } public CDDA() { super(); initFmod(); initialize(); } public JPanel getPanel() { return this; } public String getTitle() { return "FMOD CDDA example."; } private boolean init = false; private boolean deinit = false; private FSOUND_STREAM stream; private int channel = -1; private int last_openstate = -1; private boolean firsttime = true; private int track = 0; public void initFmod() { /* * NativeFmod Init */ try { Init.loadLibraries(); } catch(InitException e) { printExit("NativeFmod error! " + e.getMessage() + "\n"); return; } /* * Checking NativeFmodEx version */ if(NATIVEFMOD_LIBRARY_VERSION != NATIVEFMOD_JAR_VERSION) { printExit("Error! NativeFmod library version (" + NATIVEFMOD_LIBRARY_VERSION + ") is different to jar version (" + NATIVEFMOD_JAR_VERSION + ")\n"); return; } /*==================================================*/ /* * Checking Fmod version */ if(Fmod.FSOUND_GetVersion() < FMOD_VERSION) { printExit("Error : You are using the wrong DLL version! You should be using FMOD "+FMOD_VERSION+"\n"); return; } init = true; } public void run() { if(!init) { return; } print("-------------------------------------------------------------\n"); print("FMOD CDDA example.\n"); print("Copyright (c) Firelight Technologies Pty, Ltd, 2001-2004.\n"); print("-------------------------------------------------------------\n"); setInput("'E' (windows) or '/dev/cdrom1' (linux/mac)"); String drive = readInput("Audio CD Drive: "); switch (LibLoader.getPlatform()) { case LibLoader.PLATFORM_WINDOWS: if(!((drive.charAt(0) >= 'a' && drive.charAt(0) <= 'z') || (drive.charAt(0) >= 'A' && drive.charAt(0) <= 'Z'))) { printExit("ERROR: Invalid drive"); return; } drive += ":*j"; break; case LibLoader.PLATFORM_LINUX: case LibLoader.PLATFORM_MACOSX: if(!drive.startsWith("/")) { printExit("ERROR: Invalid drive"); return; } break; } if(!Fmod.FSOUND_Init(44100, 32, 0)) { String error = Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError()); print("Shutdown FMOD\n"); Fmod.FSOUND_Close(); printExit(error); return; } Fmod.FSOUND_Stream_SetBufferSize(2000); stream = Fmod.FSOUND_Stream_Open(new String(drive), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0); if(stream == null) { String error = Fmod.FMOD_ErrorString(Fmod.FSOUND_GetError()); print("Shutdown FMOD\n"); Fmod.FSOUND_Close(); printExit(error); return; } Fmod.FSOUND_Stream_SetSubStream(stream, 0); print("\n"); print("=========================================================================\n"); print("Press f Skip forward 2 seconds\n"); print(" b Skip back 2 seconds\n"); print(" n Next track\n"); print(" SPACE Pause/Unpause\n"); print(" e Quit\n"); print("=========================================================================\n"); boolean exit = false; do { if((stream != null) && (channel < 0)) { int this_openstate = Fmod.FSOUND_Stream_GetOpenState(stream); if(this_openstate == -3) { Pointer cd_error = new Pointer(); int[] length = new int[1]; if(Fmod.FSOUND_Stream_FindTagField(stream, 0, "CD_ERROR", cd_error, length)) { ByteBuffer buff = PointerUtils.toBuffer(cd_error, length[0]); print(BufferUtils.toString(buff) + "\n"); } else { print("ERROR: Couldn't open CDDA stream\n"); } Fmod.FSOUND_Stream_Close(stream); print("Shutdown FMOD\n"); Fmod.FSOUND_Close(); return; } if((last_openstate != 0) && (this_openstate == 0)) { if(firsttime) { FSOUND_TOC_TAG toc = new FSOUND_TOC_TAG(); if(Fmod.FSOUND_Stream_FindTagField(stream, 0, "CD_TOC", toc, (int[])null)) { dump_cddb_query(toc); } Pointer cd_device_info = new Pointer(); if(!Fmod.FSOUND_Stream_GetTagField(stream, 0, (int[])null, null, cd_device_info, (int[])null)) { Fmod.FSOUND_Stream_Close(stream); print("Shutdown FMOD\n"); Fmod.FSOUND_Close(); printExit("ERROR: Couldn't get CD_DEVICE_INFO tag"); return; } print(PointerUtils.toString(cd_device_info)+"\n"); print("\n=========================================================================\n"); firsttime = false; Pointer cd_error = new Pointer(); if(Fmod.FSOUND_Stream_FindTagField(stream, 0, "CD_ERROR", cd_error, (int[])null)) { Fmod.FSOUND_Stream_Close(stream); print("Shutdown FMOD\n"); Fmod.FSOUND_Close(); printExit(PointerUtils.toString(cd_error)+"\n"); return; } } channel = Fmod.FSOUND_Stream_PlayEx(FSOUND_FREE, stream, null, true); Fmod.FSOUND_SetPaused(channel, false); } last_openstate = this_openstate; } if(channel != -1) { switch(getKey()) { case ' ': Fmod.FSOUND_SetPaused(channel, !Fmod.FSOUND_GetPaused(channel)); break; case 'f': Fmod.FSOUND_Stream_SetTime(stream, Fmod.FSOUND_Stream_GetTime(stream) + 2000); break; case 'b': Fmod.FSOUND_Stream_SetTime(stream, Fmod.FSOUND_Stream_GetTime(stream) - 2000); break; case 'n': track++; if(track >= Fmod.FSOUND_Stream_GetNumSubStreams(stream)) { track = 0; } Fmod.FSOUND_Stream_SetSubStream(stream, track); channel = -1; last_openstate = -1; break; case 'e': case 'E': exit = true; break; } } //stream is open and ready if(Fmod.FSOUND_Stream_GetOpenState(stream) == 0) { /* * Print informations on the track (number, time, cpu usage) */ printr("Track "+(track+1)+"/"+Fmod.FSOUND_Stream_GetNumSubStreams(stream)+" " + (Fmod.FSOUND_Stream_GetTime(stream)/1000/60)+":"+(Fmod.FSOUND_Stream_GetTime(stream)/1000%60)+"/" + (Fmod.FSOUND_Stream_GetLengthMs(stream)/1000/60)+":"+(Fmod.FSOUND_Stream_GetLengthMs(stream)/1000%60)+" " + "cpu "+Fmod.FSOUND_GetCPUUsage()); } Fmod.FSOUND_Update(); try { Thread.sleep(100); } catch(Exception e){} } while(!exit && !deinit); stop(); } public void stop() { if(!init || deinit) { return; } deinit = true; print("\n"); if(stream != null && !stream.isNull()) Fmod.FSOUND_Stream_Close(stream); print("Shutdown FMOD\n"); Fmod.FSOUND_Close(); } private int cddb_sum(int n) { int ret = 0; while(n > 0) { ret += (n % 10); n /= 10; } return ret; } private long cddb_discid(FSOUND_TOC_TAG toc) { int i, t, n = 0; for(i = 0; i < toc.getNumtracks(); i++) { n += cddb_sum((toc.getMin()[i] * 60) + toc.getSec()[i]); } t = ((toc.getMin()[toc.getNumtracks()] * 60) + toc.getSec()[toc.getNumtracks()]) - ((toc.getMin()[0] * 60) + toc.getSec()[0]); return ((n % 0xff) << 24 | t << 8 | toc.getNumtracks()); } private void dump_cddb_query(FSOUND_TOC_TAG toc) { print("cddb query " + Integer.toHexString((int)cddb_discid(toc)) + " " + toc.getNumtracks()); for(int i = 0; i < toc.getNumtracks(); i++) { print(" " + ((toc.getMin()[i] * (60 * 75)) + (toc.getSec()[i] * 75) + toc.getFrame()[i])); } print(" "+((toc.getMin()[toc.getNumtracks()] * 60) + toc.getSec()[toc.getNumtracks()])+"\n"); } }