mas01mj@669: // mas01mj@669: // AppController.m mas01mj@669: // iAudioDB mas01mj@669: // mas01mj@669: // Created by Mike Jewell on 27/01/2010. mas01mj@669: // Copyright 2010 __MyCompanyName__. All rights reserved. mas01mj@669: // mas01mj@669: mas01mj@669: #import "AppController.h" mas01mj@669: mas01mj@669: mas01mj@669: @implementation AppController mas01mj@669: mas01mj@669: -(id)init mas01mj@669: { mas01mj@669: [super init]; mas01mj@669: mas01mj@669: // A max of 100 results. mas01mj@669: results = [[NSMutableArray alloc] initWithCapacity: 100]; mas01mj@669: mas01mj@669: mas01mj@669: return self; mas01mj@669: } mas01mj@669: mas01mj@669: mas01mj@669: /** mas01mj@669: * Create a new database, given the selected filename. mas01mj@669: */ mas01mj@669: -(IBAction)newDatabase:(id)sender mas01mj@669: { mas01mj@669: NSSavePanel* panel = [NSSavePanel savePanel]; mas01mj@669: NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@""]; mas01mj@669: mas01mj@669: [results removeAllObjects]; mas01mj@669: [tracksView reloadData]; mas01mj@669: mas01mj@669: if(response == NSFileHandlingPanelOKButton) mas01mj@669: { mas01mj@669: // TODO: Refactor this into a 'tidy' method. mas01mj@669: // Tidy any existing references up. mas01mj@669: if(db) mas01mj@669: { mas01mj@669: audiodb_close(db); mas01mj@669: } mas01mj@669: mas01mj@669: if(dbFilename) mas01mj@669: { mas01mj@669: [dbFilename release]; mas01mj@669: [dbName release]; mas01mj@669: [plistFilename release]; mas01mj@669: } mas01mj@669: mas01mj@669: // Create new db, and set flags. mas01mj@669: db = audiodb_create([[panel filename] cStringUsingEncoding:NSUTF8StringEncoding], 0, 0, 0); mas01mj@669: audiodb_l2norm(db); mas01mj@669: audiodb_power(db); mas01mj@669: mas01mj@669: // Store useful paths. mas01mj@669: dbName = [[[panel URL] relativePath] retain]; mas01mj@669: dbFilename = [[panel filename] retain]; mas01mj@669: plistFilename = [[NSString stringWithFormat:@"%@.plist", [dbFilename stringByDeletingPathExtension]] retain]; mas01mj@669: mas01mj@669: // Create the plist file (contains mapping from filename to key). mas01mj@669: trackMap = [[NSMutableDictionary alloc] init]; mas01mj@669: [trackMap writeToFile:plistFilename atomically:YES]; mas01mj@669: mas01mj@669: [queryKey setStringValue:@"None Selected"]; mas01mj@669: [self updateStatus]; mas01mj@669: } mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Open an existing adb (which must have a plist) mas01mj@669: */ mas01mj@669: -(IBAction)openDatabase:(id)sender mas01mj@669: { mas01mj@669: NSArray *fileTypes = [NSArray arrayWithObject:@"adb"]; mas01mj@669: NSOpenPanel* panel = [NSOpenPanel openPanel]; mas01mj@669: NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@"" types:fileTypes]; mas01mj@669: if(response == NSFileHandlingPanelOKButton) mas01mj@669: { mas01mj@669: // Tidy any existing references up. mas01mj@669: if(db) mas01mj@669: { mas01mj@669: audiodb_close(db); mas01mj@669: } mas01mj@669: mas01mj@669: if(dbFilename) mas01mj@669: { mas01mj@669: [dbFilename release]; mas01mj@669: [dbName release]; mas01mj@669: [plistFilename release]; mas01mj@669: } mas01mj@669: mas01mj@669: // Store useful paths. mas01mj@669: db = audiodb_open([[panel filename] cStringUsingEncoding:NSUTF8StringEncoding], O_RDWR); mas01mj@669: dbName = [[[panel URL] relativePath] retain]; mas01mj@669: dbFilename = [[panel filename] retain]; mas01mj@669: mas01mj@669: // TODO: Verify this exists! mas01mj@669: plistFilename = [[NSString stringWithFormat:@"%@.plist", [dbFilename stringByDeletingPathExtension]] retain]; mas01mj@669: mas01mj@669: // Clear out any old results. mas01mj@669: [results removeAllObjects]; mas01mj@669: [tracksView reloadData]; mas01mj@669: mas01mj@669: [queryKey setStringValue:@"None Selected"]; mas01mj@669: [self updateStatus]; mas01mj@669: mas01mj@669: adb_liszt_results_t* liszt_results = audiodb_liszt(db); mas01mj@669: mas01mj@669: for(int k=0; knresults; k++) mas01mj@669: { mas01mj@669: NSMutableString *trackVal = [[NSMutableString alloc] init]; mas01mj@669: [trackVal appendFormat:@"%s", liszt_results->entries[k].key]; mas01mj@669: } mas01mj@669: mas01mj@669: audiodb_liszt_free_results(db, liszt_results); mas01mj@669: trackMap = [[[NSMutableDictionary alloc] initWithContentsOfFile:plistFilename] retain]; mas01mj@669: NSLog(@"Size: %d", [trackMap count]); mas01mj@669: } mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Update button states and status field based on current state. mas01mj@669: */ mas01mj@669: -(void)updateStatus mas01mj@669: { mas01mj@669: if(db) mas01mj@669: { mas01mj@669: adb_status_ptr status = (adb_status_ptr)malloc(sizeof(struct adbstatus)); mas01mj@669: int flags; mas01mj@669: flags = audiodb_status(db, status); mas01mj@669: [statusField setStringValue: [NSString stringWithFormat:@"Database: %@ Dimensions: %d Files: %d", dbName, status->dim, status->numFiles]]; mas01mj@669: [chooseButton setEnabled:YES]; mas01mj@669: } mas01mj@669: else mas01mj@669: { mas01mj@669: [chooseButton setEnabled:NO]; mas01mj@669: [playBothButton setEnabled:FALSE]; mas01mj@669: [playResultButton setEnabled:FALSE]; mas01mj@669: } mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Get user's import choices. mas01mj@669: */ mas01mj@669: -(IBAction)importAudio:(id)sender mas01mj@669: { mas01mj@669: [NSApp beginSheet:importSheet modalForWindow:mainWindow modalDelegate:self didEndSelector:NULL contextInfo:nil]; mas01mj@669: session = [NSApp beginModalSessionForWindow: importSheet]; mas01mj@669: [NSApp runModalSession:session]; mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Cancel the import (at configuration time). mas01mj@669: */ mas01mj@669: -(IBAction)cancelImport:(id)sender; mas01mj@669: { mas01mj@669: [NSApp endModalSession:session]; mas01mj@669: [importSheet orderOut:nil]; mas01mj@669: [NSApp endSheet:importSheet]; mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Choose the file(s) to be imported. mas01mj@669: * TODO: Currently handles the import process too - split this off. mas01mj@669: */ mas01mj@669: -(IBAction)selectFiles:(id)sender mas01mj@669: { mas01mj@669: [tracksView reloadData]; mas01mj@669: mas01mj@669: NSArray *fileTypes = [NSArray arrayWithObject:@"wav"]; mas01mj@669: NSOpenPanel* panel = [NSOpenPanel openPanel]; mas01mj@669: [panel setAllowsMultipleSelection:TRUE]; mas01mj@669: NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@"" types:fileTypes]; mas01mj@669: if(response == NSFileHandlingPanelOKButton) mas01mj@669: { mas01mj@669: NSRect newFrame; mas01mj@669: mas01mj@669: [extractingBox setHidden:FALSE]; mas01mj@669: newFrame.origin.x = [importSheet frame].origin.x; mas01mj@669: newFrame.origin.y = [importSheet frame].origin.y - [extractingBox frame].size.height; mas01mj@669: newFrame.size.width = [importSheet frame].size.width; mas01mj@669: newFrame.size.height = [importSheet frame].size.height + [extractingBox frame].size.height; mas01mj@669: mas01mj@669: [indicator startAnimation:self]; mas01mj@669: [importSheet setFrame:newFrame display:YES animate:YES]; mas01mj@669: mas01mj@669: NSArray *filesToOpen = [panel filenames]; mas01mj@669: mas01mj@669: NSLog(@"Begin import"); mas01mj@669: mas01mj@669: // Work out which extractor to use mas01mj@669: NSString* extractor = @"chromagram"; mas01mj@669: switch([extractorOptions selectedTag]) mas01mj@669: { mas01mj@669: case 0: mas01mj@669: extractor = @"mfcc"; mas01mj@669: break; mas01mj@669: case 1: mas01mj@669: extractor = @"chromagram"; mas01mj@669: break; mas01mj@669: } mas01mj@669: mas01mj@669: for(int i=0; i<[filesToOpen count]; i++) mas01mj@669: { mas01mj@669: // First extract powers mas01mj@669: mas01mj@669: NSString *tempFileTemplate = [NSTemporaryDirectory() stringByAppendingPathComponent:@"powers.XXXXXX"]; mas01mj@669: const char *tempFileTemplateCString = [tempFileTemplate fileSystemRepresentation]; mas01mj@669: char *tempFileNameCString = (char *)malloc(strlen(tempFileTemplateCString) + 1); mas01mj@669: strcpy(tempFileNameCString, tempFileTemplateCString); mas01mj@669: mktemp(tempFileNameCString); mas01mj@669: mas01mj@669: NSString* powersFileName = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:tempFileNameCString length:strlen(tempFileNameCString)]; mas01mj@669: free(tempFileNameCString); mas01mj@669: mas01mj@669: NSTask *task = [[NSTask alloc] init]; mas01mj@669: [task setLaunchPath:@"/usr/local/bin/fftExtract2"]; mas01mj@669: NSArray *args = [NSArray arrayWithObjects:@"-P", @"-h", @"11025", @"-w", @"16384", @"-n", @"32768", @"-i", @"1000", [filesToOpen objectAtIndex:i], powersFileName, nil]; mas01mj@669: [task setArguments:args]; mas01mj@669: [task launch]; mas01mj@669: [task waitUntilExit]; mas01mj@669: [task release]; mas01mj@669: mas01mj@669: // Then features mas01mj@669: mas01mj@669: tempFileTemplate = [NSTemporaryDirectory() stringByAppendingPathComponent:@"features.XXXXXX"]; mas01mj@669: tempFileTemplateCString = [tempFileTemplate fileSystemRepresentation]; mas01mj@669: tempFileNameCString = (char *)malloc(strlen(tempFileTemplateCString) + 1); mas01mj@669: strcpy(tempFileNameCString, tempFileTemplateCString); mas01mj@669: mktemp(tempFileNameCString); mas01mj@669: mas01mj@669: NSString* featuresFileName = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:tempFileNameCString length:strlen(tempFileNameCString)]; mas01mj@669: free(tempFileNameCString); mas01mj@669: mas01mj@669: task = [[NSTask alloc] init]; mas01mj@669: mas01mj@669: [task setLaunchPath:@"/usr/local/bin/fftExtract2"]; mas01mj@669: mas01mj@669: NSArray *args2; mas01mj@669: mas01mj@669: // Choose the args (TODO: This should use sonic annotator eventually) mas01mj@669: if([extractor isEqualToString:@"chromagram"]) mas01mj@669: { mas01mj@669: args2 = [NSArray arrayWithObjects:@"-p",@"/Users/moj/planfile",@"-c", @"36", @"-h", @"11025", @"-w", @"16384", @"-n", @"32768", @"-i", @"1000", [filesToOpen objectAtIndex:i], featuresFileName, nil]; mas01mj@669: } mas01mj@669: else mas01mj@669: { mas01mj@669: args2 = [NSArray arrayWithObjects:@"-p",@"/Users/moj/planfile",@"-m", @"13", @"-h", @"11025", @"-w", @"16384", @"-n ", @"32768", @"-i", @"1000", [filesToOpen objectAtIndex:i], featuresFileName, nil]; mas01mj@669: } mas01mj@669: [task setArguments:args2]; mas01mj@669: [task launch]; mas01mj@669: [task waitUntilExit]; mas01mj@669: [task release]; mas01mj@669: mas01mj@669: NSString* val = [[filesToOpen objectAtIndex:i] retain]; mas01mj@669: NSString* key = [[[filesToOpen objectAtIndex:i] lastPathComponent] retain]; mas01mj@669: mas01mj@669: adb_insert_t insert; mas01mj@669: insert.features = [featuresFileName cStringUsingEncoding:NSUTF8StringEncoding]; mas01mj@669: insert.power = [powersFileName cStringUsingEncoding:NSUTF8StringEncoding]; mas01mj@669: insert.times = NULL; mas01mj@669: insert.key = [key cStringUsingEncoding:NSUTF8StringEncoding]; mas01mj@669: mas01mj@669: // Insert into db. mas01mj@669: if(audiodb_insert(db, &insert)) mas01mj@669: { mas01mj@669: // TODO: Show an error message. mas01mj@669: NSLog(@"Weep: %@ %@ %@", featuresFileName, powersFileName, key); mas01mj@669: continue; mas01mj@669: } mas01mj@669: mas01mj@669: // Update the plist store. mas01mj@669: [trackMap setValue:val forKey:key]; mas01mj@669: [trackMap writeToFile:plistFilename atomically: YES]; mas01mj@669: mas01mj@669: [self updateStatus]; mas01mj@669: } mas01mj@669: mas01mj@669: newFrame.origin.x = [importSheet frame].origin.x; mas01mj@669: newFrame.origin.y = [importSheet frame].origin.y + [extractingBox frame].size.height; mas01mj@669: newFrame.size.width = [importSheet frame].size.width; mas01mj@669: newFrame.size.height = [importSheet frame].size.height - [extractingBox frame].size.height; mas01mj@669: mas01mj@669: [importSheet setFrame:newFrame display:YES animate:YES]; mas01mj@669: mas01mj@669: [NSApp endModalSession:session]; mas01mj@669: [importSheet orderOut:nil]; mas01mj@669: [NSApp endSheet:importSheet]; mas01mj@669: [indicator stopAnimation:self]; mas01mj@669: [extractingBox setHidden:TRUE]; mas01mj@669: } mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Required table methods begin here. mas01mj@669: */ mas01mj@669: -(int)numberOfRowsInTableView:(NSTableView *)v mas01mj@669: { mas01mj@669: return [results count]; mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Return appropriate values - or the distance indicator if it's the meter column. mas01mj@669: */ mas01mj@669: -(id)tableView:(NSTableView *)v objectValueForTableColumn:(NSTableColumn *)tc row:(NSInteger)row mas01mj@669: { mas01mj@669: id result = [results objectAtIndex:row]; mas01mj@669: id value = [result objectForKey:[tc identifier]]; mas01mj@669: mas01mj@669: if([[tc identifier] isEqualToString:@"meter"]) mas01mj@669: { mas01mj@669: NSLevelIndicatorCell *distance = [[NSLevelIndicatorCell alloc] initWithLevelIndicatorStyle:NSRelevancyLevelIndicatorStyle]; mas01mj@669: [distance setFloatValue:10-[(NSNumber*)value floatValue]*100]; mas01mj@669: return distance; mas01mj@669: } mas01mj@669: else mas01mj@669: { mas01mj@669: return value; mas01mj@669: } mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Handle column sorting. mas01mj@669: */ mas01mj@669: - (void)tableView:(NSTableView *)v sortDescriptorsDidChange:(NSArray *)oldDescriptors mas01mj@669: { mas01mj@669: [results sortUsingDescriptors:[v sortDescriptors]]; mas01mj@669: [v reloadData]; mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Only enable the import menu option if a database is loaded. mas01mj@669: */ mas01mj@669: - (BOOL)validateUserInterfaceItem:(id )anItem mas01mj@669: { mas01mj@669: SEL theAction = [anItem action]; mas01mj@669: if (theAction == @selector(importAudio:)) mas01mj@669: { mas01mj@669: if(!db) mas01mj@669: { mas01mj@669: return NO; mas01mj@669: } mas01mj@669: } mas01mj@669: return YES; mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Ensure play buttons are only enabled if a track is selected. mas01mj@669: */ mas01mj@669: -(IBAction)selectedChanged:(id)sender mas01mj@669: { mas01mj@669: if([tracksView numberOfSelectedRows] == 0) mas01mj@669: { mas01mj@669: [playBothButton setEnabled:FALSE]; mas01mj@669: [playResultButton setEnabled:FALSE]; mas01mj@669: } mas01mj@669: else mas01mj@669: { mas01mj@669: [playBothButton setEnabled:TRUE]; mas01mj@669: [playResultButton setEnabled:TRUE]; mas01mj@669: } mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Play just the result track. mas01mj@669: */ mas01mj@669: -(IBAction)playResult:(id)sender mas01mj@669: { mas01mj@669: mas01mj@669: NSDictionary* selectedRow = [results objectAtIndex:[tracksView selectedRow]]; mas01mj@669: NSString* value = [selectedRow objectForKey:@"key"]; mas01mj@669: float ipos = [[selectedRow objectForKey:@"ipos"] floatValue]; mas01mj@669: NSString* filename = [trackMap objectForKey:value]; mas01mj@669: NSLog(@"Key: %@ Value: %@", value, filename); mas01mj@669: mas01mj@669: if(queryTrack) mas01mj@669: { mas01mj@669: if([queryTrack isPlaying]) mas01mj@669: { mas01mj@669: [queryTrack setDelegate:Nil]; mas01mj@669: [queryTrack stop]; mas01mj@669: } mas01mj@669: [queryTrack release]; mas01mj@669: } mas01mj@669: mas01mj@669: if(resultTrack) mas01mj@669: { mas01mj@669: if([resultTrack isPlaying]) mas01mj@669: { mas01mj@669: [resultTrack setDelegate:Nil]; mas01mj@669: [resultTrack stop]; mas01mj@669: } mas01mj@669: [resultTrack release]; mas01mj@669: } mas01mj@669: mas01mj@669: resultTrack = [[[NSSound alloc] initWithContentsOfFile:filename byReference:YES] retain]; mas01mj@669: [resultTrack setCurrentTime:ipos]; mas01mj@669: [resultTrack setDelegate:self]; mas01mj@669: [resultTrack play]; mas01mj@669: mas01mj@669: [stopButton setEnabled:YES]; mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Play the result and query simultaneously. mas01mj@669: */ mas01mj@669: -(IBAction)playBoth:(id)sender mas01mj@669: { mas01mj@669: mas01mj@669: NSDictionary* selectedRow = [results objectAtIndex:[tracksView selectedRow]]; mas01mj@669: NSString* value = [selectedRow objectForKey:@"key"]; mas01mj@669: float ipos = [[selectedRow objectForKey:@"ipos"] floatValue]; mas01mj@669: float qpos = [[selectedRow objectForKey:@"qpos"] floatValue]; mas01mj@669: NSString* filename = [trackMap objectForKey:value]; mas01mj@669: NSLog(@"Key: %@ Value: %@", value, filename); mas01mj@669: mas01mj@669: if(queryTrack) mas01mj@669: { mas01mj@669: mas01mj@669: if([queryTrack isPlaying]) mas01mj@669: { mas01mj@669: [queryTrack setDelegate:Nil]; mas01mj@669: [queryTrack stop]; mas01mj@669: } mas01mj@669: [queryTrack release]; mas01mj@669: } mas01mj@669: if(resultTrack) mas01mj@669: { mas01mj@669: if([resultTrack isPlaying]) mas01mj@669: { mas01mj@669: [resultTrack setDelegate:Nil]; mas01mj@669: [resultTrack stop]; mas01mj@669: } mas01mj@669: [resultTrack release]; mas01mj@669: } mas01mj@669: mas01mj@669: // Get query track and shift to start point mas01mj@669: queryTrack = [[[NSSound alloc] initWithContentsOfFile:selectedFilename byReference:YES] retain]; mas01mj@669: [queryTrack setCurrentTime:qpos]; mas01mj@669: [queryTrack setDelegate:self]; mas01mj@669: mas01mj@669: [queryTrack play]; mas01mj@669: mas01mj@669: resultTrack = [[[NSSound alloc] initWithContentsOfFile:filename byReference:YES] retain]; mas01mj@669: [resultTrack setCurrentTime:ipos]; mas01mj@669: [resultTrack setDelegate:self]; mas01mj@669: [resultTrack play]; mas01mj@669: mas01mj@669: [stopButton setEnabled:YES]; mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Disable the stop button after playback of both tracks. mas01mj@669: */ mas01mj@669: - (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)playbackSuccessful mas01mj@669: { mas01mj@669: mas01mj@669: if((queryTrack && [queryTrack isPlaying]) || (resultTrack && [resultTrack isPlaying])) mas01mj@669: { mas01mj@669: return; mas01mj@669: } mas01mj@669: else mas01mj@669: { mas01mj@669: [stopButton setEnabled:NO]; mas01mj@669: } mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Stop playback. mas01mj@669: */ mas01mj@669: -(IBAction)stopPlay:(id)sender mas01mj@669: { mas01mj@669: if(queryTrack) mas01mj@669: { mas01mj@669: [queryTrack stop]; mas01mj@669: } mas01mj@669: if(resultTrack) mas01mj@669: { mas01mj@669: [resultTrack stop]; mas01mj@669: } mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Select an audio file, determine the key, and fire off a query. mas01mj@669: */ mas01mj@669: -(IBAction)chooseQuery:(id)sender mas01mj@669: { mas01mj@669: NSArray* fileTypes = [NSArray arrayWithObject:@"wav"]; mas01mj@669: NSOpenPanel* panel = [NSOpenPanel openPanel]; mas01mj@669: NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@"" types:fileTypes]; mas01mj@669: if(response == NSFileHandlingPanelOKButton) mas01mj@669: { mas01mj@669: NSLog(@"%@", [panel filename]); mas01mj@669: // Grab key mas01mj@669: NSArray* opts = [trackMap allKeysForObject:[panel filename]]; mas01mj@669: if([opts count] != 1) mas01mj@669: { mas01mj@669: NSAlert *alert = [[[NSAlert alloc] init] autorelease]; mas01mj@669: [alert addButtonWithTitle:@"OK"]; mas01mj@669: [alert setMessageText:@"Track not found"]; mas01mj@669: [alert setInformativeText:@"Make sure you have specified a valid track identifier."]; mas01mj@669: [alert setAlertStyle:NSWarningAlertStyle]; mas01mj@669: [alert beginSheetModalForWindow:mainWindow modalDelegate:self didEndSelector:NULL contextInfo:nil]; mas01mj@669: } mas01mj@669: else mas01mj@669: { mas01mj@669: selectedKey = [opts objectAtIndex:0]; mas01mj@669: [queryKey setStringValue:selectedKey]; mas01mj@669: selectedFilename = [[panel filename] retain]; mas01mj@669: [self performQuery]; mas01mj@669: } mas01mj@669: } mas01mj@669: } mas01mj@669: mas01mj@669: /** mas01mj@669: * Actually perform the query. TODO: Monolithic. mas01mj@669: */ mas01mj@669: -(void)performQuery mas01mj@669: { mas01mj@669: NSLog(@"Perform query! %@, %@", selectedKey, selectedFilename); mas01mj@669: mas01mj@669: adb_query_spec_t *spec = (adb_query_spec_t *)malloc(sizeof(adb_query_spec_t)); mas01mj@669: spec->qid.datum = (adb_datum_t *)malloc(sizeof(adb_datum_t)); mas01mj@669: mas01mj@669: spec->qid.sequence_length = 20; mas01mj@669: spec->qid.sequence_start = 0; mas01mj@669: spec->qid.flags = 0; mas01mj@669: mas01mj@669: // spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_EXHAUSTIVE; mas01mj@669: spec->params.accumulation = ADB_ACCUMULATION_PER_TRACK; mas01mj@669: spec->params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED; mas01mj@669: mas01mj@669: spec->params.npoints = 1; mas01mj@669: spec->params.ntracks = 100; mas01mj@669: //spec->refine.radius = 5.0; mas01mj@669: spec->refine.hopsize = 1; mas01mj@669: // spec->refine.absolute_threshold = -6; mas01mj@669: // spec->refine.relative_threshold = 10; mas01mj@669: // spec->refine.duration_ratio = 0; mas01mj@669: mas01mj@669: spec->refine.flags = 0; mas01mj@669: // spec->refine.flags |= ADB_REFINE_ABSOLUTE_THRESHOLD; mas01mj@669: // spec->refine.flags |= ADB_REFINE_RELATIVE_THRESHOLD; mas01mj@669: spec->refine.flags |= ADB_REFINE_HOP_SIZE; mas01mj@669: //spec->refine.flags |= ADB_REFINE_RADIUS; mas01mj@669: mas01mj@669: adb_query_results_t *result = (adb_query_results_t *)malloc(sizeof(adb_query_results_t)); mas01mj@669: spec->qid.datum->data = NULL; mas01mj@669: spec->qid.datum->power = NULL; mas01mj@669: spec->qid.datum->times = NULL; mas01mj@669: mas01mj@669: [results removeAllObjects]; mas01mj@669: mas01mj@669: int ok = audiodb_retrieve_datum(db, [selectedKey cStringUsingEncoding:NSUTF8StringEncoding], spec->qid.datum); mas01mj@669: if(ok == 0) mas01mj@669: { mas01mj@669: NSLog(@"Got a datum"); mas01mj@669: result = audiodb_query_spec(db, spec); mas01mj@669: if(result == NULL) mas01mj@669: { mas01mj@669: mas01mj@669: NSLog(@"No results"); mas01mj@669: } mas01mj@669: else mas01mj@669: { mas01mj@669: for(int i=0; inresults; i++) mas01mj@669: { mas01mj@669: NSMutableDictionary* dict = [[NSMutableDictionary alloc] initWithCapacity:4]; mas01mj@669: [dict setValue:[NSString stringWithFormat:@"%s", result->results[i].key] forKey:@"key"]; mas01mj@669: [dict setValue:[NSNumber numberWithFloat:result->results[i].dist] forKey:@"distance"]; mas01mj@669: [dict setValue:[NSNumber numberWithFloat:result->results[i].dist] forKey:@"meter"]; mas01mj@669: [dict setValue:[NSNumber numberWithFloat:result->results[i].qpos/4] forKey:@"qpos"]; mas01mj@669: [dict setValue:[NSNumber numberWithFloat:result->results[i].ipos/4] forKey:@"ipos"]; mas01mj@669: NSLog(@"%s qpos %d ipos %d", result->results[i].key, result->results[i].qpos/4, result->results[i].ipos/4); mas01mj@669: [results addObject: dict]; mas01mj@669: } mas01mj@669: } mas01mj@669: mas01mj@669: NSSortDescriptor *distSort = [[NSSortDescriptor alloc]initWithKey:@"meter" ascending:YES]; mas01mj@669: NSArray *distDescs = [NSArray arrayWithObject:distSort]; mas01mj@669: mas01mj@669: [results sortUsingDescriptors:distDescs]; mas01mj@669: [tracksView setSortDescriptors:distDescs]; mas01mj@669: [tracksView reloadData]; mas01mj@669: mas01mj@669: } mas01mj@669: else mas01mj@669: { mas01mj@669: NSAlert *alert = [[[NSAlert alloc] init] autorelease]; mas01mj@669: [alert addButtonWithTitle:@"OK"]; mas01mj@669: [alert setMessageText:@"Track not found"]; mas01mj@669: [alert setInformativeText:@"Make sure you have specified a valid track identifier."]; mas01mj@669: [alert setAlertStyle:NSWarningAlertStyle]; mas01mj@669: [alert beginSheetModalForWindow:mainWindow modalDelegate:self didEndSelector:NULL contextInfo:nil]; mas01mj@669: } mas01mj@669: // audiodb_query_free_results(db, spec, result); mas01mj@669: } mas01mj@669: mas01mj@669: @end