annotate examples/iAudioDB/AppController.m @ 669:780ebab29268

Added initial increment of OSX audioDB interface
author mas01mj
date Wed, 03 Mar 2010 17:17:08 +0000
parents
children 15e71890b584
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@669 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@669 85 audiodb_close(db);
mas01mj@669 86 }
mas01mj@669 87
mas01mj@669 88 if(dbFilename)
mas01mj@669 89 {
mas01mj@669 90 [dbFilename release];
mas01mj@669 91 [dbName release];
mas01mj@669 92 [plistFilename release];
mas01mj@669 93 }
mas01mj@669 94
mas01mj@669 95 // Store useful paths.
mas01mj@669 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@669 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@669 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@669 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@669 134 [statusField setStringValue: [NSString stringWithFormat:@"Database: %@ Dimensions: %d Files: %d", dbName, status->dim, status->numFiles]];
mas01mj@669 135 [chooseButton setEnabled:YES];
mas01mj@669 136 }
mas01mj@669 137 else
mas01mj@669 138 {
mas01mj@669 139 [chooseButton setEnabled:NO];
mas01mj@669 140 [playBothButton setEnabled:FALSE];
mas01mj@669 141 [playResultButton setEnabled:FALSE];
mas01mj@669 142 }
mas01mj@669 143 }
mas01mj@669 144
mas01mj@669 145 /**
mas01mj@669 146 * Get user's import choices.
mas01mj@669 147 */
mas01mj@669 148 -(IBAction)importAudio:(id)sender
mas01mj@669 149 {
mas01mj@669 150 [NSApp beginSheet:importSheet modalForWindow:mainWindow modalDelegate:self didEndSelector:NULL contextInfo:nil];
mas01mj@669 151 session = [NSApp beginModalSessionForWindow: importSheet];
mas01mj@669 152 [NSApp runModalSession:session];
mas01mj@669 153 }
mas01mj@669 154
mas01mj@669 155 /**
mas01mj@669 156 * Cancel the import (at configuration time).
mas01mj@669 157 */
mas01mj@669 158 -(IBAction)cancelImport:(id)sender;
mas01mj@669 159 {
mas01mj@669 160 [NSApp endModalSession:session];
mas01mj@669 161 [importSheet orderOut:nil];
mas01mj@669 162 [NSApp endSheet:importSheet];
mas01mj@669 163 }
mas01mj@669 164
mas01mj@669 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@669 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@669 179 NSRect newFrame;
mas01mj@669 180
mas01mj@669 181 [extractingBox setHidden:FALSE];
mas01mj@669 182 newFrame.origin.x = [importSheet frame].origin.x;
mas01mj@669 183 newFrame.origin.y = [importSheet frame].origin.y - [extractingBox frame].size.height;
mas01mj@669 184 newFrame.size.width = [importSheet frame].size.width;
mas01mj@669 185 newFrame.size.height = [importSheet frame].size.height + [extractingBox frame].size.height;
mas01mj@669 186
mas01mj@669 187 [indicator startAnimation:self];
mas01mj@669 188 [importSheet setFrame:newFrame display:YES animate:YES];
mas01mj@669 189
mas01mj@669 190 NSArray *filesToOpen = [panel filenames];
mas01mj@669 191
mas01mj@669 192 NSLog(@"Begin import");
mas01mj@669 193
mas01mj@669 194 // Work out which extractor to use
mas01mj@669 195 NSString* extractor = @"chromagram";
mas01mj@669 196 switch([extractorOptions selectedTag])
mas01mj@669 197 {
mas01mj@669 198 case 0:
mas01mj@669 199 extractor = @"mfcc";
mas01mj@669 200 break;
mas01mj@669 201 case 1:
mas01mj@669 202 extractor = @"chromagram";
mas01mj@669 203 break;
mas01mj@669 204 }
mas01mj@669 205
mas01mj@669 206 for(int i=0; i<[filesToOpen count]; i++)
mas01mj@669 207 {
mas01mj@669 208 // First extract powers
mas01mj@669 209
mas01mj@669 210 NSString *tempFileTemplate = [NSTemporaryDirectory() stringByAppendingPathComponent:@"powers.XXXXXX"];
mas01mj@669 211 const char *tempFileTemplateCString = [tempFileTemplate fileSystemRepresentation];
mas01mj@669 212 char *tempFileNameCString = (char *)malloc(strlen(tempFileTemplateCString) + 1);
mas01mj@669 213 strcpy(tempFileNameCString, tempFileTemplateCString);
mas01mj@669 214 mktemp(tempFileNameCString);
mas01mj@669 215
mas01mj@669 216 NSString* powersFileName = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:tempFileNameCString length:strlen(tempFileNameCString)];
mas01mj@669 217 free(tempFileNameCString);
mas01mj@669 218
mas01mj@669 219 NSTask *task = [[NSTask alloc] init];
mas01mj@669 220 [task setLaunchPath:@"/usr/local/bin/fftExtract2"];
mas01mj@669 221 NSArray *args = [NSArray arrayWithObjects:@"-P", @"-h", @"11025", @"-w", @"16384", @"-n", @"32768", @"-i", @"1000", [filesToOpen objectAtIndex:i], powersFileName, nil];
mas01mj@669 222 [task setArguments:args];
mas01mj@669 223 [task launch];
mas01mj@669 224 [task waitUntilExit];
mas01mj@669 225 [task release];
mas01mj@669 226
mas01mj@669 227 // Then features
mas01mj@669 228
mas01mj@669 229 tempFileTemplate = [NSTemporaryDirectory() stringByAppendingPathComponent:@"features.XXXXXX"];
mas01mj@669 230 tempFileTemplateCString = [tempFileTemplate fileSystemRepresentation];
mas01mj@669 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@669 238 task = [[NSTask alloc] init];
mas01mj@669 239
mas01mj@669 240 [task setLaunchPath:@"/usr/local/bin/fftExtract2"];
mas01mj@669 241
mas01mj@669 242 NSArray *args2;
mas01mj@669 243
mas01mj@669 244 // Choose the args (TODO: This should use sonic annotator eventually)
mas01mj@669 245 if([extractor isEqualToString:@"chromagram"])
mas01mj@669 246 {
mas01mj@669 247 args2 = [NSArray arrayWithObjects:@"-p",@"/Users/moj/planfile",@"-c", @"36", @"-h", @"11025", @"-w", @"16384", @"-n", @"32768", @"-i", @"1000", [filesToOpen objectAtIndex:i], featuresFileName, nil];
mas01mj@669 248 }
mas01mj@669 249 else
mas01mj@669 250 {
mas01mj@669 251 args2 = [NSArray arrayWithObjects:@"-p",@"/Users/moj/planfile",@"-m", @"13", @"-h", @"11025", @"-w", @"16384", @"-n ", @"32768", @"-i", @"1000", [filesToOpen objectAtIndex:i], featuresFileName, nil];
mas01mj@669 252 }
mas01mj@669 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@669 260
mas01mj@669 261 adb_insert_t insert;
mas01mj@669 262 insert.features = [featuresFileName cStringUsingEncoding:NSUTF8StringEncoding];
mas01mj@669 263 insert.power = [powersFileName cStringUsingEncoding:NSUTF8StringEncoding];
mas01mj@669 264 insert.times = NULL;
mas01mj@669 265 insert.key = [key cStringUsingEncoding:NSUTF8StringEncoding];
mas01mj@669 266
mas01mj@669 267 // Insert into db.
mas01mj@669 268 if(audiodb_insert(db, &insert))
mas01mj@669 269 {
mas01mj@669 270 // TODO: Show an error message.
mas01mj@669 271 NSLog(@"Weep: %@ %@ %@", featuresFileName, powersFileName, key);
mas01mj@669 272 continue;
mas01mj@669 273 }
mas01mj@669 274
mas01mj@669 275 // Update the plist store.
mas01mj@669 276 [trackMap setValue:val forKey:key];
mas01mj@669 277 [trackMap writeToFile:plistFilename atomically: YES];
mas01mj@669 278
mas01mj@669 279 [self updateStatus];
mas01mj@669 280 }
mas01mj@669 281
mas01mj@669 282 newFrame.origin.x = [importSheet frame].origin.x;
mas01mj@669 283 newFrame.origin.y = [importSheet frame].origin.y + [extractingBox frame].size.height;
mas01mj@669 284 newFrame.size.width = [importSheet frame].size.width;
mas01mj@669 285 newFrame.size.height = [importSheet frame].size.height - [extractingBox frame].size.height;
mas01mj@669 286
mas01mj@669 287 [importSheet setFrame:newFrame display:YES animate:YES];
mas01mj@669 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@669 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@669 357 [playBothButton setEnabled:FALSE];
mas01mj@669 358 [playResultButton setEnabled:FALSE];
mas01mj@669 359 }
mas01mj@669 360 else
mas01mj@669 361 {
mas01mj@669 362 [playBothButton setEnabled:TRUE];
mas01mj@669 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@669 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@669 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@669 496 NSLog(@"%@", [panel filename]);
mas01mj@669 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@669 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@669 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@669 528 spec->qid.sequence_length = 20;
mas01mj@669 529 spec->qid.sequence_start = 0;
mas01mj@669 530 spec->qid.flags = 0;
mas01mj@669 531
mas01mj@669 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@669 536 spec->params.npoints = 1;
mas01mj@669 537 spec->params.ntracks = 100;
mas01mj@669 538 //spec->refine.radius = 5.0;
mas01mj@669 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@669 547 spec->refine.flags |= ADB_REFINE_HOP_SIZE;
mas01mj@669 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@669 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@669 575 [dict setValue:[NSNumber numberWithFloat:result->results[i].qpos/4] forKey:@"qpos"];
mas01mj@669 576 [dict setValue:[NSNumber numberWithFloat:result->results[i].ipos/4] forKey:@"ipos"];
mas01mj@669 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