annotate examples/iAudioDB/AppController.m @ 682:df9639a5cad2

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