annotate examples/iAudioDB/AppController.m @ 684:fed70cb84a92

Double-clicking table now plays result where possible.
author mas01mj
date Fri, 05 Mar 2010 17:20:06 +0000
parents df9639a5cad2
children e78e5a80b73d
rev   line source
mas01mj@669 1 //
mas01mj@669 2 // AppController.m
mas01mj@669 3 // iAudioDB
mas01mj@669 4 //
mas01mj@669 5 // Created by Mike Jewell on 27/01/2010.
mas01mj@669 6 // Copyright 2010 __MyCompanyName__. All rights reserved.
mas01mj@669 7 //
mas01mj@669 8
mas01mj@669 9 #import "AppController.h"
mas01mj@669 10
mas01mj@669 11
mas01mj@669 12 @implementation AppController
mas01mj@669 13
mas01mj@669 14 -(id)init
mas01mj@669 15 {
mas01mj@669 16 [super init];
mas01mj@669 17
mas01mj@669 18 // A max of 100 results.
mas01mj@669 19 results = [[NSMutableArray alloc] initWithCapacity: 100];
mas01mj@669 20
mas01mj@669 21 return self;
mas01mj@669 22 }
mas01mj@669 23
mas01mj@684 24 - (void)awakeFromNib {
mas01mj@684 25 [tracksView setTarget:self];
mas01mj@684 26 [tracksView setDoubleAction:@selector(tableDoubleClick:)];
mas01mj@684 27 }
mas01mj@684 28
mas01mj@684 29 - (IBAction)tableDoubleClick:(id)sender
mas01mj@684 30 {
mas01mj@684 31 [self playResult:Nil];
mas01mj@684 32 // NSLog(@"Table double clicked");
mas01mj@684 33 }
mas01mj@684 34
mas01mj@669 35
mas01mj@669 36 /**
mas01mj@669 37 * Create a new database, given the selected filename.
mas01mj@669 38 */
mas01mj@669 39 -(IBAction)newDatabase:(id)sender
mas01mj@669 40 {
mas01mj@669 41 NSSavePanel* panel = [NSSavePanel savePanel];
mas01mj@669 42 NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@""];
mas01mj@669 43
mas01mj@669 44 [results removeAllObjects];
mas01mj@669 45 [tracksView reloadData];
mas01mj@669 46
mas01mj@669 47 if(response == NSFileHandlingPanelOKButton)
mas01mj@669 48 {
mas01mj@669 49 // TODO: Refactor this into a 'tidy' method.
mas01mj@669 50 // Tidy any existing references up.
mas01mj@669 51 if(db)
mas01mj@669 52 {
mas01mj@669 53 audiodb_close(db);
mas01mj@669 54 }
mas01mj@669 55
mas01mj@669 56 if(dbFilename)
mas01mj@669 57 {
mas01mj@669 58 [dbFilename release];
mas01mj@669 59 [dbName release];
mas01mj@669 60 [plistFilename release];
mas01mj@669 61 }
mas01mj@669 62
mas01mj@669 63 // Create new db, and set flags.
mas01mj@669 64 db = audiodb_create([[panel filename] cStringUsingEncoding:NSUTF8StringEncoding], 0, 0, 0);
mas01mj@669 65 audiodb_l2norm(db);
mas01mj@680 66 // audiodb_power(db);
mas01mj@669 67
mas01mj@669 68 // Store useful paths.
mas01mj@669 69 dbName = [[[panel URL] relativePath] retain];
mas01mj@669 70 dbFilename = [[panel filename] retain];
mas01mj@669 71 plistFilename = [[NSString stringWithFormat:@"%@.plist", [dbFilename stringByDeletingPathExtension]] retain];
mas01mj@669 72
mas01mj@669 73 // Create the plist file (contains mapping from filename to key).
mas01mj@669 74 trackMap = [[NSMutableDictionary alloc] init];
mas01mj@669 75 [trackMap writeToFile:plistFilename atomically:YES];
mas01mj@669 76
mas01mj@669 77 [queryKey setStringValue:@"None Selected"];
mas01mj@669 78 [self updateStatus];
mas01mj@669 79 }
mas01mj@669 80 }
mas01mj@669 81
mas01mj@669 82 /**
mas01mj@669 83 * Open an existing adb (which must have a plist)
mas01mj@669 84 */
mas01mj@669 85 -(IBAction)openDatabase:(id)sender
mas01mj@669 86 {
mas01mj@669 87 NSArray *fileTypes = [NSArray arrayWithObject:@"adb"];
mas01mj@669 88 NSOpenPanel* panel = [NSOpenPanel openPanel];
mas01mj@669 89 NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@"" types:fileTypes];
mas01mj@669 90 if(response == NSFileHandlingPanelOKButton)
mas01mj@669 91 {
mas01mj@669 92 // Tidy any existing references up.
mas01mj@669 93 if(db)
mas01mj@669 94 {
mas01mj@680 95 NSLog(@"Close db");
mas01mj@669 96 audiodb_close(db);
mas01mj@669 97 }
mas01mj@669 98
mas01mj@669 99 if(dbFilename)
mas01mj@669 100 {
mas01mj@680 101 NSLog(@"Tidy up filenames");
mas01mj@669 102 [dbFilename release];
mas01mj@669 103 [dbName release];
mas01mj@669 104 [plistFilename release];
mas01mj@669 105 }
mas01mj@669 106
mas01mj@669 107 // Store useful paths.
mas01mj@680 108 NSLog(@"Open");
mas01mj@680 109 db = audiodb_open([[panel filename] cStringUsingEncoding:NSUTF8StringEncoding], O_RDONLY);
mas01mj@669 110 dbName = [[[panel URL] relativePath] retain];
mas01mj@669 111 dbFilename = [[panel filename] retain];
mas01mj@669 112
mas01mj@669 113 // TODO: Verify this exists!
mas01mj@669 114 plistFilename = [[NSString stringWithFormat:@"%@.plist", [dbFilename stringByDeletingPathExtension]] retain];
mas01mj@669 115
mas01mj@669 116 // Clear out any old results.
mas01mj@669 117 [results removeAllObjects];
mas01mj@669 118 [tracksView reloadData];
mas01mj@669 119
mas01mj@669 120 [queryKey setStringValue:@"None Selected"];
mas01mj@669 121 [self updateStatus];
mas01mj@669 122
mas01mj@669 123 adb_liszt_results_t* liszt_results = audiodb_liszt(db);
mas01mj@669 124
mas01mj@669 125 for(int k=0; k<liszt_results->nresults; k++)
mas01mj@669 126 {
mas01mj@669 127 NSMutableString *trackVal = [[NSMutableString alloc] init];
mas01mj@669 128 [trackVal appendFormat:@"%s", liszt_results->entries[k].key];
mas01mj@669 129 }
mas01mj@669 130
mas01mj@669 131 audiodb_liszt_free_results(db, liszt_results);
mas01mj@669 132 trackMap = [[[NSMutableDictionary alloc] initWithContentsOfFile:plistFilename] retain];
mas01mj@669 133 NSLog(@"Size: %d", [trackMap count]);
mas01mj@669 134 }
mas01mj@669 135 }
mas01mj@669 136
mas01mj@669 137 /**
mas01mj@669 138 * Update button states and status field based on current state.
mas01mj@669 139 */
mas01mj@669 140 -(void)updateStatus
mas01mj@669 141 {
mas01mj@680 142 NSLog(@"Update status");
mas01mj@669 143 if(db)
mas01mj@669 144 {
mas01mj@680 145 NSLog(@"Got a db");
mas01mj@682 146 adb_status_t *status = (adb_status_t *)malloc(sizeof(adb_status_t));
mas01mj@669 147 int flags;
mas01mj@669 148 flags = audiodb_status(db, status);
mas01mj@669 149 [statusField setStringValue: [NSString stringWithFormat:@"Database: %@ Dimensions: %d Files: %d", dbName, status->dim, status->numFiles]];
mas01mj@669 150 [chooseButton setEnabled:YES];
mas01mj@669 151 }
mas01mj@669 152 else
mas01mj@669 153 {
mas01mj@680 154 NSLog(@"No db");
mas01mj@669 155 [chooseButton setEnabled:NO];
mas01mj@669 156 [playBothButton setEnabled:FALSE];
mas01mj@669 157 [playResultButton setEnabled:FALSE];
mas01mj@669 158 }
mas01mj@669 159 }
mas01mj@669 160
mas01mj@669 161 /**
mas01mj@669 162 * Get user's import choices.
mas01mj@669 163 */
mas01mj@669 164 -(IBAction)importAudio:(id)sender
mas01mj@669 165 {
mas01mj@669 166 [NSApp beginSheet:importSheet modalForWindow:mainWindow modalDelegate:self didEndSelector:NULL contextInfo:nil];
mas01mj@669 167 session = [NSApp beginModalSessionForWindow: importSheet];
mas01mj@669 168 [NSApp runModalSession:session];
mas01mj@669 169 }
mas01mj@669 170
mas01mj@669 171 /**
mas01mj@669 172 * Cancel the import (at configuration time).
mas01mj@669 173 */
mas01mj@669 174 -(IBAction)cancelImport:(id)sender;
mas01mj@669 175 {
mas01mj@669 176 [NSApp endModalSession:session];
mas01mj@669 177 [importSheet orderOut:nil];
mas01mj@669 178 [NSApp endSheet:importSheet];
mas01mj@669 179 }
mas01mj@669 180
mas01mj@669 181 /**
mas01mj@669 182 * Choose the file(s) to be imported.
mas01mj@669 183 * TODO: Currently handles the import process too - split this off.
mas01mj@669 184 */
mas01mj@669 185 -(IBAction)selectFiles:(id)sender
mas01mj@669 186 {
mas01mj@669 187 [tracksView reloadData];
mas01mj@669 188
mas01mj@669 189 NSArray *fileTypes = [NSArray arrayWithObject:@"wav"];
mas01mj@669 190 NSOpenPanel* panel = [NSOpenPanel openPanel];
mas01mj@669 191 [panel setAllowsMultipleSelection:TRUE];
mas01mj@669 192 NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@"" types:fileTypes];
mas01mj@669 193 if(response == NSFileHandlingPanelOKButton)
mas01mj@669 194 {
mas01mj@669 195 NSRect newFrame;
mas01mj@669 196
mas01mj@669 197 [extractingBox setHidden:FALSE];
mas01mj@669 198 newFrame.origin.x = [importSheet frame].origin.x;
mas01mj@669 199 newFrame.origin.y = [importSheet frame].origin.y - [extractingBox frame].size.height;
mas01mj@669 200 newFrame.size.width = [importSheet frame].size.width;
mas01mj@669 201 newFrame.size.height = [importSheet frame].size.height + [extractingBox frame].size.height;
mas01mj@669 202
mas01mj@669 203 [indicator startAnimation:self];
mas01mj@669 204 [importSheet setFrame:newFrame display:YES animate:YES];
mas01mj@669 205
mas01mj@669 206 NSArray *filesToOpen = [panel filenames];
mas01mj@669 207
mas01mj@669 208 NSLog(@"Begin import");
mas01mj@669 209
mas01mj@680 210 /*
mas01mj@680 211 vamp:vamp-audiodb-plugins:cq:cq
mas01mj@680 212 vamp:vamp-audiodb-plugins:chromagram:chroma
mas01mj@680 213 vamp:qm-vamp-plugins:qm-mfcc:coefficients
mas01mj@680 214 vamp:qm-vamp-plugins:qm-chromagram:chromagram
mas01mj@680 215 */
mas01mj@680 216
mas01mj@680 217
mas01mj@680 218 // adb_chroma
mas01mj@680 219 // adb_cq
mas01mj@680 220 // qm_chroma
mas01mj@680 221 // qm_mfcc
mas01mj@680 222
mas01mj@669 223 // Work out which extractor to use
mas01mj@669 224 NSString* extractor = @"chromagram";
mas01mj@669 225 switch([extractorOptions selectedTag])
mas01mj@669 226 {
mas01mj@669 227 case 0:
mas01mj@680 228 extractor = @"adb_chroma";
mas01mj@669 229 break;
mas01mj@669 230 case 1:
mas01mj@680 231 extractor = @"adb_cq";
mas01mj@680 232 break;
mas01mj@680 233 case 2:
mas01mj@680 234 extractor = @"qm_chroma";
mas01mj@680 235 break;
mas01mj@680 236 case 3:
mas01mj@680 237 extractor = @"qm_mfcc";
mas01mj@669 238 break;
mas01mj@669 239 }
mas01mj@669 240
mas01mj@680 241
mas01mj@669 242 for(int i=0; i<[filesToOpen count]; i++)
mas01mj@680 243 {
mas01mj@680 244 audiodb_close(db);
mas01mj@680 245 NSString* tempFileTemplate = [NSTemporaryDirectory() stringByAppendingPathComponent:@"features.XXXXXX"];
mas01mj@680 246 const char* tempFileTemplateCString = [tempFileTemplate fileSystemRepresentation];
mas01mj@680 247 char* tempFileNameCString = (char *)malloc(strlen(tempFileTemplateCString) + 1);
mas01mj@669 248 strcpy(tempFileNameCString, tempFileTemplateCString);
mas01mj@669 249 mktemp(tempFileNameCString);
mas01mj@669 250
mas01mj@669 251 NSString* featuresFileName = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:tempFileNameCString length:strlen(tempFileNameCString)];
mas01mj@669 252 free(tempFileNameCString);
mas01mj@669 253
mas01mj@680 254 NSTask* task = [[NSTask alloc] init];
mas01mj@669 255
mas01mj@680 256 [task setLaunchPath:@"/usr/local/bin/sonic-annotator"];
mas01mj@669 257
mas01mj@682 258 NSString* extractorPath = [NSString stringWithFormat:@"/Users/mikej/Development/audioDB/examples/iAudioDB/rdf/%@.n3", extractor];
mas01mj@680 259 NSLog(@"Extractor path: %@", extractorPath);
mas01mj@680 260 NSArray* args;
mas01mj@680 261 args = [NSArray arrayWithObjects:@"-t", extractorPath, @"-w", @"rdf", @"-r", @"--rdf-network", @"--rdf-one-file", featuresFileName, @"--rdf-force", [filesToOpen objectAtIndex:i], nil];
mas01mj@680 262 [task setArguments:args];
mas01mj@669 263 [task launch];
mas01mj@669 264 [task waitUntilExit];
mas01mj@669 265 [task release];
mas01mj@669 266
mas01mj@680 267 NSTask* importTask = [[NSTask alloc] init];
mas01mj@680 268 [importTask setLaunchPath:@"/usr/local/bin/populate"];
mas01mj@680 269 args = [NSArray arrayWithObjects:featuresFileName, dbFilename, nil];
mas01mj@680 270 [importTask setArguments:args];
mas01mj@680 271 [importTask launch];
mas01mj@680 272 [importTask waitUntilExit];
mas01mj@680 273 [importTask release];
mas01mj@680 274
mas01mj@669 275 NSString* val = [[filesToOpen objectAtIndex:i] retain];
mas01mj@669 276 NSString* key = [[[filesToOpen objectAtIndex:i] lastPathComponent] retain];
mas01mj@680 277 /*
mas01mj@669 278 adb_insert_t insert;
mas01mj@669 279 insert.features = [featuresFileName cStringUsingEncoding:NSUTF8StringEncoding];
mas01mj@680 280 // insert.power = [powersFileName cStringUsingEncoding:NSUTF8StringEncoding];
mas01mj@669 281 insert.times = NULL;
mas01mj@669 282 insert.key = [key cStringUsingEncoding:NSUTF8StringEncoding];
mas01mj@669 283
mas01mj@669 284 // Insert into db.
mas01mj@669 285 if(audiodb_insert(db, &insert))
mas01mj@669 286 {
mas01mj@669 287 // TODO: Show an error message.
mas01mj@680 288 NSLog(@"Weep: %@ %@", featuresFileName, key);
mas01mj@669 289 continue;
mas01mj@680 290 }*/
mas01mj@669 291
mas01mj@669 292 // Update the plist store.
mas01mj@669 293 [trackMap setValue:val forKey:key];
mas01mj@669 294 [trackMap writeToFile:plistFilename atomically: YES];
mas01mj@669 295
mas01mj@680 296
mas01mj@680 297 db = audiodb_open([dbFilename cStringUsingEncoding:NSUTF8StringEncoding], O_RDONLY);
mas01mj@669 298 [self updateStatus];
mas01mj@669 299 }
mas01mj@669 300
mas01mj@669 301 newFrame.origin.x = [importSheet frame].origin.x;
mas01mj@669 302 newFrame.origin.y = [importSheet frame].origin.y + [extractingBox frame].size.height;
mas01mj@669 303 newFrame.size.width = [importSheet frame].size.width;
mas01mj@669 304 newFrame.size.height = [importSheet frame].size.height - [extractingBox frame].size.height;
mas01mj@669 305
mas01mj@669 306 [importSheet setFrame:newFrame display:YES animate:YES];
mas01mj@669 307
mas01mj@669 308 [NSApp endModalSession:session];
mas01mj@669 309 [importSheet orderOut:nil];
mas01mj@669 310 [NSApp endSheet:importSheet];
mas01mj@669 311 [indicator stopAnimation:self];
mas01mj@669 312 [extractingBox setHidden:TRUE];
mas01mj@669 313 }
mas01mj@669 314 }
mas01mj@669 315
mas01mj@669 316 /**
mas01mj@669 317 * Required table methods begin here.
mas01mj@669 318 */
mas01mj@669 319 -(int)numberOfRowsInTableView:(NSTableView *)v
mas01mj@669 320 {
mas01mj@669 321 return [results count];
mas01mj@669 322 }
mas01mj@669 323
mas01mj@669 324 /**
mas01mj@669 325 * Return appropriate values - or the distance indicator if it's the meter column.
mas01mj@669 326 */
mas01mj@669 327 -(id)tableView:(NSTableView *)v objectValueForTableColumn:(NSTableColumn *)tc row:(NSInteger)row
mas01mj@669 328 {
mas01mj@669 329 id result = [results objectAtIndex:row];
mas01mj@669 330 id value = [result objectForKey:[tc identifier]];
mas01mj@669 331
mas01mj@669 332 if([[tc identifier] isEqualToString:@"meter"])
mas01mj@669 333 {
mas01mj@669 334 NSLevelIndicatorCell *distance = [[NSLevelIndicatorCell alloc] initWithLevelIndicatorStyle:NSRelevancyLevelIndicatorStyle];
mas01mj@669 335 [distance setFloatValue:10-[(NSNumber*)value floatValue]*100];
mas01mj@669 336 return distance;
mas01mj@669 337 }
mas01mj@669 338 else
mas01mj@669 339 {
mas01mj@669 340 return value;
mas01mj@669 341 }
mas01mj@669 342 }
mas01mj@669 343
mas01mj@669 344 /**
mas01mj@669 345 * Handle column sorting.
mas01mj@669 346 */
mas01mj@669 347 - (void)tableView:(NSTableView *)v sortDescriptorsDidChange:(NSArray *)oldDescriptors
mas01mj@669 348 {
mas01mj@669 349 [results sortUsingDescriptors:[v sortDescriptors]];
mas01mj@669 350 [v reloadData];
mas01mj@669 351 }
mas01mj@669 352
mas01mj@669 353 /**
mas01mj@669 354 * Only enable the import menu option if a database is loaded.
mas01mj@669 355 */
mas01mj@669 356 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem
mas01mj@669 357 {
mas01mj@669 358 SEL theAction = [anItem action];
mas01mj@669 359 if (theAction == @selector(importAudio:))
mas01mj@669 360 {
mas01mj@669 361 if(!db)
mas01mj@669 362 {
mas01mj@669 363 return NO;
mas01mj@669 364 }
mas01mj@669 365 }
mas01mj@669 366 return YES;
mas01mj@669 367 }
mas01mj@669 368
mas01mj@669 369 /**
mas01mj@669 370 * Ensure play buttons are only enabled if a track is selected.
mas01mj@669 371 */
mas01mj@669 372 -(IBAction)selectedChanged:(id)sender
mas01mj@669 373 {
mas01mj@669 374 if([tracksView numberOfSelectedRows] == 0)
mas01mj@669 375 {
mas01mj@669 376 [playBothButton setEnabled:FALSE];
mas01mj@669 377 [playResultButton setEnabled:FALSE];
mas01mj@669 378 }
mas01mj@669 379 else
mas01mj@669 380 {
mas01mj@669 381 [playBothButton setEnabled:TRUE];
mas01mj@669 382 [playResultButton setEnabled:TRUE];
mas01mj@669 383 }
mas01mj@669 384 }
mas01mj@669 385
mas01mj@669 386 /**
mas01mj@669 387 * Play just the result track.
mas01mj@669 388 */
mas01mj@669 389 -(IBAction)playResult:(id)sender
mas01mj@669 390 {
mas01mj@669 391
mas01mj@684 392 if([tracksView selectedRow] == -1)
mas01mj@684 393 {
mas01mj@684 394 return;
mas01mj@684 395 }
mas01mj@684 396
mas01mj@669 397 NSDictionary* selectedRow = [results objectAtIndex:[tracksView selectedRow]];
mas01mj@669 398 NSString* value = [selectedRow objectForKey:@"key"];
mas01mj@669 399 float ipos = [[selectedRow objectForKey:@"ipos"] floatValue];
mas01mj@669 400 NSString* filename = [trackMap objectForKey:value];
mas01mj@669 401 NSLog(@"Key: %@ Value: %@", value, filename);
mas01mj@669 402
mas01mj@669 403 if(queryTrack)
mas01mj@669 404 {
mas01mj@669 405 if([queryTrack isPlaying])
mas01mj@669 406 {
mas01mj@669 407 [queryTrack setDelegate:Nil];
mas01mj@669 408 [queryTrack stop];
mas01mj@669 409 }
mas01mj@669 410 [queryTrack release];
mas01mj@669 411 }
mas01mj@669 412
mas01mj@669 413 if(resultTrack)
mas01mj@669 414 {
mas01mj@669 415 if([resultTrack isPlaying])
mas01mj@669 416 {
mas01mj@669 417 [resultTrack setDelegate:Nil];
mas01mj@669 418 [resultTrack stop];
mas01mj@669 419 }
mas01mj@669 420 [resultTrack release];
mas01mj@669 421 }
mas01mj@669 422
mas01mj@669 423 resultTrack = [[[NSSound alloc] initWithContentsOfFile:filename byReference:YES] retain];
mas01mj@669 424 [resultTrack setCurrentTime:ipos];
mas01mj@669 425 [resultTrack setDelegate:self];
mas01mj@669 426 [resultTrack play];
mas01mj@669 427
mas01mj@669 428 [stopButton setEnabled:YES];
mas01mj@669 429 }
mas01mj@669 430
mas01mj@669 431 /**
mas01mj@669 432 * Play the result and query simultaneously.
mas01mj@669 433 */
mas01mj@669 434 -(IBAction)playBoth:(id)sender
mas01mj@669 435 {
mas01mj@669 436
mas01mj@669 437 NSDictionary* selectedRow = [results objectAtIndex:[tracksView selectedRow]];
mas01mj@669 438 NSString* value = [selectedRow objectForKey:@"key"];
mas01mj@669 439 float ipos = [[selectedRow objectForKey:@"ipos"] floatValue];
mas01mj@669 440 float qpos = [[selectedRow objectForKey:@"qpos"] floatValue];
mas01mj@669 441 NSString* filename = [trackMap objectForKey:value];
mas01mj@669 442 NSLog(@"Key: %@ Value: %@", value, filename);
mas01mj@669 443
mas01mj@669 444 if(queryTrack)
mas01mj@669 445 {
mas01mj@669 446
mas01mj@669 447 if([queryTrack isPlaying])
mas01mj@669 448 {
mas01mj@669 449 [queryTrack setDelegate:Nil];
mas01mj@669 450 [queryTrack stop];
mas01mj@669 451 }
mas01mj@669 452 [queryTrack release];
mas01mj@669 453 }
mas01mj@669 454 if(resultTrack)
mas01mj@669 455 {
mas01mj@669 456 if([resultTrack isPlaying])
mas01mj@669 457 {
mas01mj@669 458 [resultTrack setDelegate:Nil];
mas01mj@669 459 [resultTrack stop];
mas01mj@669 460 }
mas01mj@669 461 [resultTrack release];
mas01mj@669 462 }
mas01mj@669 463
mas01mj@669 464 // Get query track and shift to start point
mas01mj@669 465 queryTrack = [[[NSSound alloc] initWithContentsOfFile:selectedFilename byReference:YES] retain];
mas01mj@669 466 [queryTrack setCurrentTime:qpos];
mas01mj@669 467 [queryTrack setDelegate:self];
mas01mj@669 468
mas01mj@669 469 [queryTrack play];
mas01mj@669 470
mas01mj@669 471 resultTrack = [[[NSSound alloc] initWithContentsOfFile:filename byReference:YES] retain];
mas01mj@669 472 [resultTrack setCurrentTime:ipos];
mas01mj@669 473 [resultTrack setDelegate:self];
mas01mj@669 474 [resultTrack play];
mas01mj@669 475
mas01mj@669 476 [stopButton setEnabled:YES];
mas01mj@669 477 }
mas01mj@669 478
mas01mj@669 479 /**
mas01mj@669 480 * Disable the stop button after playback of both tracks.
mas01mj@669 481 */
mas01mj@669 482 - (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)playbackSuccessful
mas01mj@669 483 {
mas01mj@669 484
mas01mj@669 485 if((queryTrack && [queryTrack isPlaying]) || (resultTrack && [resultTrack isPlaying]))
mas01mj@669 486 {
mas01mj@669 487 return;
mas01mj@669 488 }
mas01mj@669 489 else
mas01mj@669 490 {
mas01mj@669 491 [stopButton setEnabled:NO];
mas01mj@669 492 }
mas01mj@669 493 }
mas01mj@669 494
mas01mj@669 495 /**
mas01mj@669 496 * Stop playback.
mas01mj@669 497 */
mas01mj@669 498 -(IBAction)stopPlay:(id)sender
mas01mj@669 499 {
mas01mj@669 500 if(queryTrack)
mas01mj@669 501 {
mas01mj@669 502 [queryTrack stop];
mas01mj@669 503 }
mas01mj@669 504 if(resultTrack)
mas01mj@669 505 {
mas01mj@669 506 [resultTrack stop];
mas01mj@669 507 }
mas01mj@669 508 }
mas01mj@669 509
mas01mj@669 510 /**
mas01mj@669 511 * Select an audio file, determine the key, and fire off a query.
mas01mj@669 512 */
mas01mj@669 513 -(IBAction)chooseQuery:(id)sender
mas01mj@669 514 {
mas01mj@669 515 NSArray* fileTypes = [NSArray arrayWithObject:@"wav"];
mas01mj@669 516 NSOpenPanel* panel = [NSOpenPanel openPanel];
mas01mj@669 517 NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@"" types:fileTypes];
mas01mj@669 518 if(response == NSFileHandlingPanelOKButton)
mas01mj@669 519 {
mas01mj@669 520 NSLog(@"%@", [panel filename]);
mas01mj@669 521 // Grab key
mas01mj@669 522 NSArray* opts = [trackMap allKeysForObject:[panel filename]];
mas01mj@669 523 if([opts count] != 1)
mas01mj@669 524 {
mas01mj@669 525 NSAlert *alert = [[[NSAlert alloc] init] autorelease];
mas01mj@669 526 [alert addButtonWithTitle:@"OK"];
mas01mj@669 527 [alert setMessageText:@"Track not found"];
mas01mj@669 528 [alert setInformativeText:@"Make sure you have specified a valid track identifier."];
mas01mj@669 529 [alert setAlertStyle:NSWarningAlertStyle];
mas01mj@669 530 [alert beginSheetModalForWindow:mainWindow modalDelegate:self didEndSelector:NULL contextInfo:nil];
mas01mj@669 531 }
mas01mj@669 532 else
mas01mj@669 533 {
mas01mj@669 534 selectedKey = [opts objectAtIndex:0];
mas01mj@669 535 [queryKey setStringValue:selectedKey];
mas01mj@669 536 selectedFilename = [[panel filename] retain];
mas01mj@669 537 [self performQuery];
mas01mj@669 538 }
mas01mj@669 539 }
mas01mj@669 540 }
mas01mj@669 541
mas01mj@669 542 /**
mas01mj@669 543 * Actually perform the query. TODO: Monolithic.
mas01mj@669 544 */
mas01mj@669 545 -(void)performQuery
mas01mj@669 546 {
mas01mj@669 547 NSLog(@"Perform query! %@, %@", selectedKey, selectedFilename);
mas01mj@669 548
mas01mj@669 549 adb_query_spec_t *spec = (adb_query_spec_t *)malloc(sizeof(adb_query_spec_t));
mas01mj@669 550 spec->qid.datum = (adb_datum_t *)malloc(sizeof(adb_datum_t));
mas01mj@669 551
mas01mj@669 552 spec->qid.sequence_length = 20;
mas01mj@669 553 spec->qid.sequence_start = 0;
mas01mj@669 554 spec->qid.flags = 0;
mas01mj@669 555
mas01mj@669 556 // spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_EXHAUSTIVE;
mas01mj@669 557 spec->params.accumulation = ADB_ACCUMULATION_PER_TRACK;
mas01mj@669 558 spec->params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED;
mas01mj@669 559
mas01mj@669 560 spec->params.npoints = 1;
mas01mj@669 561 spec->params.ntracks = 100;
mas01mj@669 562 //spec->refine.radius = 5.0;
mas01mj@669 563 // spec->refine.absolute_threshold = -6;
mas01mj@669 564 // spec->refine.relative_threshold = 10;
mas01mj@669 565 // spec->refine.duration_ratio = 0;
mas01mj@669 566
mas01mj@669 567 spec->refine.flags = 0;
mas01mj@669 568 // spec->refine.flags |= ADB_REFINE_ABSOLUTE_THRESHOLD;
mas01mj@669 569 // spec->refine.flags |= ADB_REFINE_RELATIVE_THRESHOLD;
mas01mj@682 570 // spec->refine.flags |= ADB_REFINE_HOP_SIZE;
mas01mj@669 571 //spec->refine.flags |= ADB_REFINE_RADIUS;
mas01mj@669 572
mas01mj@669 573 adb_query_results_t *result = (adb_query_results_t *)malloc(sizeof(adb_query_results_t));
mas01mj@669 574 spec->qid.datum->data = NULL;
mas01mj@669 575 spec->qid.datum->power = NULL;
mas01mj@669 576 spec->qid.datum->times = NULL;
mas01mj@669 577
mas01mj@669 578 [results removeAllObjects];
mas01mj@669 579
mas01mj@669 580 int ok = audiodb_retrieve_datum(db, [selectedKey cStringUsingEncoding:NSUTF8StringEncoding], spec->qid.datum);
mas01mj@669 581 if(ok == 0)
mas01mj@669 582 {
mas01mj@669 583 NSLog(@"Got a datum");
mas01mj@669 584 result = audiodb_query_spec(db, spec);
mas01mj@669 585 if(result == NULL)
mas01mj@669 586 {
mas01mj@669 587
mas01mj@669 588 NSLog(@"No results");
mas01mj@669 589 }
mas01mj@669 590 else
mas01mj@669 591 {
mas01mj@680 592 float divisor = (44100/2048);
mas01mj@669 593 for(int i=0; i<result->nresults; i++)
mas01mj@669 594 {
mas01mj@682 595
mas01mj@669 596 NSMutableDictionary* dict = [[NSMutableDictionary alloc] initWithCapacity:4];
mas01mj@682 597 [dict setValue:[NSString stringWithFormat:@"%s", result->results[i].ikey] forKey:@"key"];
mas01mj@669 598 [dict setValue:[NSNumber numberWithFloat:result->results[i].dist] forKey:@"distance"];
mas01mj@669 599 [dict setValue:[NSNumber numberWithFloat:result->results[i].dist] forKey:@"meter"];
mas01mj@680 600 [dict setValue:[NSNumber numberWithFloat:result->results[i].qpos/divisor] forKey:@"qpos"];
mas01mj@680 601 [dict setValue:[NSNumber numberWithFloat:result->results[i].ipos/divisor] forKey:@"ipos"];
mas01mj@682 602 NSLog(@"%s qpos %d ipos %d", result->results[i].ikey, result->results[i].qpos/divisor, result->results[i].ipos/divisor);
mas01mj@669 603 [results addObject: dict];
mas01mj@669 604 }
mas01mj@669 605 }
mas01mj@669 606
mas01mj@669 607 NSSortDescriptor *distSort = [[NSSortDescriptor alloc]initWithKey:@"meter" ascending:YES];
mas01mj@669 608 NSArray *distDescs = [NSArray arrayWithObject:distSort];
mas01mj@669 609
mas01mj@669 610 [results sortUsingDescriptors:distDescs];
mas01mj@669 611 [tracksView setSortDescriptors:distDescs];
mas01mj@669 612 [tracksView reloadData];
mas01mj@669 613
mas01mj@669 614 }
mas01mj@669 615 else
mas01mj@669 616 {
mas01mj@669 617 NSAlert *alert = [[[NSAlert alloc] init] autorelease];
mas01mj@669 618 [alert addButtonWithTitle:@"OK"];
mas01mj@669 619 [alert setMessageText:@"Track not found"];
mas01mj@669 620 [alert setInformativeText:@"Make sure you have specified a valid track identifier."];
mas01mj@669 621 [alert setAlertStyle:NSWarningAlertStyle];
mas01mj@669 622 [alert beginSheetModalForWindow:mainWindow modalDelegate:self didEndSelector:NULL contextInfo:nil];
mas01mj@669 623 }
mas01mj@669 624 // audiodb_query_free_results(db, spec, result);
mas01mj@669 625 }
mas01mj@669 626
mas01mj@669 627 @end