annotate examples/iAudioDB/AppController.m @ 692:02756c5ca15a

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