package it.univpm.deit.semedia.musicuri.utils.misc; import it.univpm.deit.semedia.musicuri.core.MusicURIDatabase; import it.univpm.deit.semedia.musicuri.core.MusicURIQuery; import it.univpm.deit.semedia.musicuri.core.MusicURIReference; import it.univpm.deit.semedia.musicuri.core.MusicURISearch; import it.univpm.deit.semedia.musicuri.core.Result; import it.univpm.deit.semedia.musicuri.core.ResultRankingList; import it.univpm.deit.semedia.musicuri.core.Toolset; import it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearchServiceLocator; import it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearchSoapBindingStub; import java.io.File; import java.net.URL; import java.net.HttpURLConnection; import java.net.MalformedURLException; import jargs.gnu.CmdLineParser; /** * @author Dimitrios Kourtesis */ public class MusicURILibraryDemo { /** * * This application intends to practically demonstrate the basic * funcionality that MusicURI offers, which is to enable the mapping between * a piece of music and a unique URI. * * The demo application currently offers the following operations: * * a) Query a MusicURI local database with a music item, and retrieve a URI * b) Add a reference music item to a local MusicURI database * c) List all reference music items inside a local MusicURI database * * The main method in this class enables a user to: * * a) Query the local MusicURI database file at the specified path, with the * given audio file, to retrieve a URI. The -q switch is accompanied by the * path to the local database, and the -f flag (optional) signals if the * filename should be utilized as a reliable hint within search. Format: * java -jar MusicURI.jar [<audiofile>] [<-q> <DBfile>] [<-f>] example: * "c:\test.wav" -q "C:\WINDOWS\system32\MusicURIReferences.db" -f * * b) Add, to the local MusicURI database file at the specified path, the * given audio file. The -a switch is accompanied by the path to the local * database, into which the music item will be indexed. Format: java -jar * MusicURI.jar [<audiofile>] [<-a> <DBfile>] example: "c:\test.wav" -a * "C:\WINDOWS\system32\MusicURIReferences.db" * * c) List the URIs of all music items indexed in the local MusicURI * database file, at the specified path. Format: java -jar MusicURI.jar [<-l> * <databasefile>] Example: -l "C:\WINDOWS\system32\MusicURIReferences.db" * * Before proceeding with any of the aforementioned operations, the * application verifies that any files that have been specified exist, and * are valid. * * For query operations, the user has to specify Where, What and How to * identify. I.e. the user must specify the URL where the MusicURI data * source resides, the audio file containing the unknown piece of music, and * whether the system should utilize the provided filename as a reliable * hint within the search, or not (default is false). * * The filename should be taken into consideration only if the user is * absolutely confident that it does not contain any misleading information * about the artist and title of the respective piece of music. For example, * this option could be safely used for a filename of the form <ARTIST> * <SEPARATOR> <TITLE>.<EXTENSION> * * Where: The URL specifying the location of the MusicURI data source * What : The audio file containing the piece of music to use as a query * How : A flag determining whether to utilize the filename in search */ static MusicURIWebSearchSoapBindingStub stub; public static void main(String[] args) { if (args.length == 0) printUsage(); else { /****************** ARGUMENT SETTING **************/ // A command line parser to handle all options and arguments. CmdLineParser parser = new CmdLineParser(); // The -f option is a flag determining whether to use or not use the filename // within the search. No value follows, the flag is either present, or not. CmdLineParser.Option usefilename = parser.addBooleanOption('f', "usefilename"); // The -q option is followed by a String value specifying the path // of the database file to be queried. CmdLineParser.Option queryOption = parser.addStringOption('q', "query"); // The -a switch is followed by a String value specifying the path to the // local database, into which a given audio file will be indexed. CmdLineParser.Option addReferenceOption = parser.addStringOption('a', "addReference"); // The -l switch is followed by a String value specifying the path to the // local database, the contents of which will be listed. CmdLineParser.Option listReferencesOption = parser.addStringOption('l', "listReferences"); /****************** ARGUMENT PARSING **************/ // Parse the user-provided command line arguments, and catch any errors try { parser.parse(args); } catch (CmdLineParser.OptionException e) { System.err.println(e.getMessage()); printUsage(); System.exit(1); } // The location of the MusicURI data source defaults to the loopback address. //String queryValue = (String) parser.getOptionValue(queryWS, "http://localhost:8080/axis/MusicURIWebSearch.jws?wsdl"); String queryValue = (String) parser.getOptionValue(queryOption); String addReferenceValue = (String) parser.getOptionValue(addReferenceOption); String listReferencesValue = (String) parser.getOptionValue(listReferencesOption); /****************** PERFORM OPERATION **************/ String audiofileValue = null; // At any time only one option value should be selected, and therefore be non-null, // while the rest must be null. If any two option values are found to be non-null, // at the same time, print usage and abort. if ( ((queryValue != null) && (addReferenceValue != null)) || ((queryValue != null) && (listReferencesValue != null)) || ((addReferenceValue != null) && (listReferencesValue != null)) ) { printUsage(); System.exit(1); } else { /****************** QUERY OPERATION **************/ // The requested operation was a query to a Web Service or local database file if (queryValue != null) { // The flag determining whether to use the filename within search, defaults to false. Boolean usefilenameValue = (Boolean) parser.getOptionValue(usefilename, Boolean.FALSE); // There should remain only one free argument (not preceeded by a switch); // the one specifying the filename of the audio file. if (parser.getRemainingArgs().length == 1) { audiofileValue = parser.getRemainingArgs()[0]; } if (!isValidAudioFile(audiofileValue)) { printUsage(); System.exit(1); } boolean done = false; String musicURIDataSource = queryValue; // if the given MusicURI data source is a valid web service URL, query it. if (isValidWebServiceURL(musicURIDataSource)) { // Set the done flag, to signal that the MusicURI data source // has been identified as a Web Service done = true; try { queryWS(new URL(musicURIDataSource), new File(audiofileValue), usefilenameValue); } catch (MalformedURLException e) { //impossible to reach here, the URL has already been checked } } // if the given MusicURI data source is a valid local database file, query it. if (!done && isValidDatabaseFile(musicURIDataSource)) { // Set the done flag, to signal that the MusicURI data source // has been identified as a local database file done = true; queryDB(new File (musicURIDataSource), new File(audiofileValue), usefilenameValue); } // if the given MusicURI data source is non of the above, abort. if (!done) { printUsage(); System.exit(1); } } /****************** ADDITION OPERATION **************/ // The requested operation was a MusicURI reference addition to a // Web Service or local database file if (addReferenceValue != null) { // There should remain only one free argument (not preceded by a switch); // the one specifying the filename of the audio file. if (parser.getRemainingArgs().length == 1) { audiofileValue = parser.getRemainingArgs()[0]; } if (!isValidAudioFile(audiofileValue)) { printUsage(); System.exit(1); } boolean done = false; String musicURIDataSource = addReferenceValue; // if the given MusicURI data source is a valid web service URL, query it. if (isValidWebServiceURL(musicURIDataSource)) { // Set the done flag, to signal that the MusicURI data source // has been identified as a Web Service done = true; try { addReferenceToWS(new URL(musicURIDataSource), new File(audiofileValue)); } catch (MalformedURLException e) { //impossible to reach here, the URL has already been checked } } // if the given MusicURI data source is a valid local database file, query it. if (!done && isValidDatabaseFile(musicURIDataSource)) { // Set the done flag, to signal that the MusicURI data source // has been identified as a local database file done = true; addReferenceToDB(new File (musicURIDataSource), new File(audiofileValue)); } // if the given MusicURI data source is non of the above, abort. if (!done) { printUsage(); System.exit(1); } } /****************** LIST OPERATION **************/ // The requested operation was a listing of all the MusicURI references // that reside on a Web Service or local database file if (listReferencesValue != null) { boolean done = false; String musicURIDataSource = listReferencesValue; // if the given MusicURI data source is a valid web service URL, query it. if (isValidWebServiceURL(musicURIDataSource)) { // Set the done flag, to signal that the MusicURI data source // has been identified as a Web Service done = true; try { listWSReferences(new URL(musicURIDataSource)); } catch (MalformedURLException e) { //impossible to reach here, the URL has already been checked } } // if the given MusicURI data source is a valid local database file, query it. if (!done && isValidDatabaseFile(musicURIDataSource)) { // Set the done flag, to signal that the MusicURI data source // has been identified as a local database file done = true; listDBReferences(new File (musicURIDataSource)); } // if the given MusicURI data source is non of the above, abort. if (!done) { printUsage(); System.exit(1); } } } } }// end main method private static void printUsage() { System.out.println("USAGE: This MusicURI demo currently supports the following operations: "); System.out.println(""); System.out.println("1) To query a MusicURI local database with a music item, and retrieve a URI:"); System.out.println(" The -f flag signals if the filename should be considered as a hint in search."); System.out.println(" The -q switch is followed by the local database file's path"); System.out.println(""); System.out.println(" - java -jar MusicURI.jar [audiofile] [-f] [-q localDB]"); System.out.println(" "); System.out.println("2) To add a reference music item into a local MusicURI database file "); System.out.println(" The -a switch is followed by the local database file's path]"); System.out.println(" "); System.out.println(" - java -jar MusicURI.jar [audiofile] [-a localDB]"); System.out.println(" "); System.out.println("3) To list all reference music items indexed inside a local MusicURI database"); System.out.println(" The -l switch is followed by the local database file's path]"); System.out.println(" "); System.out.println(" - java -jar MusicURI.jar [-l localDB]"); } private static void queryWS(URL webServiceURL, File audioFile, Boolean usefilenameValue) { System.out.println("Starting MusicURI Demo: Query a MusicURI Web Service Data Source"); String response = null; try { //the object that will be our proxy stub = new MusicURIWebSearchSoapBindingStub(webServiceURL, new MusicURIWebSearchServiceLocator()); if (audioFile.exists()) { System.out.println("Creating query for : " + audioFile.getName()); String xmlAudioSignature = Toolset.createMPEG7Description(audioFile); String filename = audioFile.getName(); System.out.println("Waiting for Web Service to return results..."); // If the useFileName flag has been set to true, the filename should be provided // and used within the search. If not, don't the provide the filename at all. if (usefilenameValue.booleanValue()) { response = stub.performSearch(xmlAudioSignature, filename); } else { response = stub.performSearch(xmlAudioSignature, null); } System.out.println("Web Service response: "); System.out.println(response); } } catch (Exception e) { System.err.println("An error occured while querying the Web Service"); e.printStackTrace(); } } private static void addReferenceToWS(URL webServiceURL, File audioFile) { System.out.println("Starting MusicURI Demo: Add a MusicURI reference to a MusicURI Web Service Data Source"); System.out.println("Not implemented yet"); } private static void listWSReferences(URL webServiceURL) { System.out.println("Starting MusicURI Demo: List the MusicURI references of a MusicURI Web Service Data Source"); String response = null; try { //the object that will be our proxy stub = new MusicURIWebSearchSoapBindingStub(webServiceURL, new MusicURIWebSearchServiceLocator()); System.out.println("Waiting for Web Service to return results..."); response = stub.getMusicURIReferenceList(); System.out.println("Web Service response: "); System.out.println(response); } catch (Exception ex) { ex.printStackTrace(); response = "An error occured while querying the Web Service"; } } private static void queryDB(File databaseFile, File audioFile, Boolean usefilenameValue) { System.out.println("Starting MusicURI Demo: Query a local MusicURI Data Source"); String databasePath = databaseFile.getParent() + "\\"; String databaseFileName = databaseFile.getName(); MusicURIDatabase db = new MusicURIDatabase (databasePath, databaseFileName); MusicURISearch engine = new MusicURISearch (db); try { ResultRankingList finalDistanceRankingList = engine.identify(new MusicURIQuery(audioFile), usefilenameValue.booleanValue(), usefilenameValue.booleanValue(), 0.9f, //90% acceptable similarity rating usefilenameValue.booleanValue()); if (finalDistanceRankingList.getSize() >= 1) { Result theBestResult = finalDistanceRankingList.getResultAtIndex(0); double bestMatchDistance = theBestResult.distance; System.out.println("Matched with : " + (db.getMusicURIReference(theBestResult.md5)).getLabel()); System.out.println("Score : " + (float) (100 - (100*(theBestResult.distance))) + "%"); } } catch (Exception e) { e.printStackTrace(); } } private static void addReferenceToDB(File databaseFile, File audioFile) { System.out.println("Starting MusicURI Demo: Add a MusicURI reference to a local MusicURI Data Source"); String databasePath = databaseFile.getParent() + "\\"; String databaseFileName = databaseFile.getName(); MusicURIDatabase db = new MusicURIDatabase (databasePath, databaseFileName); boolean success = false; MusicURIReference newref = null; try { newref = new MusicURIReference(audioFile); success = db.addMusicURIReference(newref); } catch (Exception e) { e.printStackTrace(); } if (success) { System.out.println("The MusicURI reference was added successfully."); System.out.println("The local MusicURI Data Source now holds " + db.getDbSize() + " references."); } else System.out.println("The MusicURI reference could not be added"); } private static void listDBReferences(File databaseFile) { System.out.println("Starting MusicURI Demo: List the MusicURI references of a local MusicURI Data Source"); String databasePath = databaseFile.getParent() + "\\"; String databaseFileName = databaseFile.getName(); MusicURIDatabase db = new MusicURIDatabase (databasePath, databaseFileName); String list = db.textFormattedSetOfMusicURIReferences(); System.out.println(list); } public static boolean isValidAudioFile(String audiofileValue) { if (audiofileValue != null) { // Verify that the specified file exists, and it is not a directory File audioFile = new File(audiofileValue); if (!audioFile.exists()) { System.err.println("The specified file does not exist"); return false; } if (!audioFile.isFile()) { System.err.println("The specified file is a directory"); return false; } // Verify that the specified file is of a supported type if (!Toolset.isSupportedAudioFile(audioFile)) { System.err.println("The specified file is not a supported audio file"); return false; } return true; } else { System.out.println("Unspecified audiofileValue"); return false; } } public static boolean isValidWebServiceURL(String queryValue) { if (queryValue != null) { // Verify that the URL is well-formed and valid (both host and // resource exist) URL webServiceURL = null; try { webServiceURL = new URL(queryValue); HttpURLConnection urlConn = (HttpURLConnection) webServiceURL .openConnection(); // Try to connect. If the URL is malformed throw a // MalformedURLException. urlConn.connect(); // To take care of the chance of having an invalid, although // well-formed URL, check the HTTP Status Code. If it's not // 200 (HTTP_OK), throw an Exception. if (urlConn.getResponseCode() != 200) throw new Exception(); } catch (MalformedURLException e) { return false; } catch (Exception e) { return false; } return true; } else return false; } public static boolean isValidDatabaseFile(String musicURIDataSource) { if (musicURIDataSource != null) { // Verify that the specified file exists, and it is not a directory File databaseFile = new File(musicURIDataSource); if (!databaseFile.exists() || !databaseFile.isFile()) { return false; } // Verify that the specified file is a valid MusicURI Hashmap flatfile // (ends with .db, and can be deserialized into a Java Hashmap object) if (!isDBFile(databaseFile)) { System.err.println("The specified file is not a valid MusicURI database file"); return false; } // else // System.out.println("file ends with .db"); // try // { // HashMap object = new HashMap(); // ObjectInputStream in = new ObjectInputStream(new FileInputStream(musicURIDataSource)); // object = (HashMap) in.readObject(); // System.out.println("file can be deserialized"); // } // catch (Exception e) // { // e.toString(); // System.out.println("Can't load database file (" + musicURIDataSource + ")"); // return false; // } return true; } else { System.out.println("Unspecified musicURIDataSource"); return false; } } /** * Reports if the filename of the given file ends with ".db" * @param file the file to check * @return true if the filename ends with a ".db" extension, false otherwise */ public static boolean isDBFile(File file) { String fname = file.getName(); String extension = fname.substring(fname.lastIndexOf('.') + 1); if (extension.equalsIgnoreCase("db")) return true; else return false; } }