#import "mediaEngine.h"#import <QuickTime/QuickTime.h>#import <QTKit/QTKit.h>#import <QTKit/QTMovieView.h>#import <QTKit/QTTime.h>#import <Foundation/Foundation.h>#import <Appkit/Appkit.h>#import "appControl.h"/// DECLARATION OF PUBLIC SCOPE VARIABLESint actualTrack = 0;int totalTracks;NSArray* trackList;NSTimer *timer=nil;QTTime tempTime;QTMovie* mainSoundEngine;NSValue* tTime;@implementation mediaEngine- (IBAction)next:(id)sender{ if (actualTrack < (totalTracks -1)) { actualTrack = actualTrack + 1; //[mainSoundEngine release]; [self playBtn:nil]; }}- (IBAction)playBtn:(id)sender{ [mainSoundEngine release]; /// IF THERE IS A TIMER ALREADY RUNNING, WE DESTROY IT. SHOULD NOT BE NECESSARY, BUT I DONT KNOW YET HOW COCOA API /// MANAGES THAT INTERNALLY, PLUS IT CAN AVOID PROBLEMS WITH A USER CLICKING LOTS OF TIMES IN THE "PLAY" BUTTON UI. [timer invalidate]; /// WE CREATE A TIMER TO UPDATE ALL THE INTERFACE OBJECTS EVERY 0.5 SECONDS /// timer = [NSTimer scheduledTimerWithTimeInterval: 0.1 target: self selector: @selector(displayUpdate:) userInfo: nil repeats: YES]; /// WE LOAD ALL THE TRACKS IN AN ARRAY trackList = [[NSBundle mainBundle] pathsForResourcesOfType:@"m4a" inDirectory:@""]; totalTracks = [trackList count]; NSString* track = [trackList objectAtIndex:actualTrack]; /// 02-jul-2006 /// REPLACED HIGH LEVEL API QTMOVIEVIEW WITH NEW QTMOVIE LOW LEVEL API AS PER APPLE RECOMMENDATION. /// 100% WINDOWS CROSS-PLATFORM CODE NOW. mainSoundEngine = [QTMovie movieWithFile:track error:nil]; [mainSoundEngine retain]; [mainSoundEngine setVolume:[volumeSlider floatValue]]; /// THESE FOLLOWING PARAMETERS SHOULD BE HANDLED BY A .PLIST FILE IN FUTURE VERSION. [songName setStringValue:[mainSoundEngine attributeForKey:@"QTMovieDisplayNameAttribute"]]; [songArtist setStringValue:@"Insphire"]; [songNumber setStringValue:[NSString stringWithFormat:@"Track %i of %i", (actualTrack+1), totalTracks]]; tempTime = [mainSoundEngine duration]; //tempTime = [mainSoundEngine decodeQTTimeForKey:@"QTMovieCurrentTimeAttribute"]; //tempTime = [mainSoundEngine currentTime]; //NSString* caca = [mainSoundEngine attributeForKey:@"QTMovieCurrentTimeAttribute"]; //NSLog(caca); /// WE SEND SOME MESSAGES TO INFORM THE NOTIFICATION CENTER ABOUT PLAYER STATUS. /// I SHOULD IMPROVE THE MESSAGING SYSTEM IN NEW VERSIONS. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(QTMovieDidEndNotification:) name:@"QTMovieDidEndNotification" object:mainSoundEngine]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(QTMovieTimeDidChangeNotification:) name:@"QTMovieTimeDidChangeNotification" object:mainSoundEngine]; [mainSoundEngine play]; NSLog([tTime description]);}- (IBAction)previous:(id)sender{ if ( actualTrack > 0) { actualTrack = actualTrack - 1; [self playBtn:nil]; }}- (IBAction)stop:(id)sender{ [mainSoundEngine stop]; /// THE "timer = nil;" LINE IS VERY IMPORTANT! AFTER SOME RESEARCH, IT SEEMS THAT THE "INVALIDATE" METHOD TOTALLY CLEARS THE OBJECT. /// APPLICATION WILL CRASH WITHOUT THIS LINE! if ([timer isValid]) { [timer invalidate]; timer = nil; }}- (IBAction)volumeChange:(id)sender{ [mainSoundEngine setVolume:[volumeSlider floatValue]];}- (IBAction)exportMusic:(id)sender{ /// FILE COPY AND MANAGEMENT ROUTINES. THIS IS VERY SKELETON CODE, AT THE MOMENT IS NOT CHECKING FOR FILE OR DIR EXISTENCE, ETC. /// WILL BE IMPROVED IN FUTURE REVISIONS. /// I NEED TO *** REMEMBER *** THAT I WANT TO ADD FILE AND AUDIO COMPRESSION ROUTINES TO THIS. NSFileManager *fileManager = [NSFileManager defaultManager]; [fileManager createDirectoryAtPath:[NSString stringWithFormat:@"%@/Music/MediaPacks", NSHomeDirectory()] attributes:nil]; [fileManager removeFileAtPath:[NSString stringWithFormat:@"%@/Music/MediaPacks/Insphire - Afterdark", NSHomeDirectory()] handler:nil]; [fileManager createDirectoryAtPath:[NSString stringWithFormat:@"%@/Music/MediaPacks/Insphire - AfterDark", NSHomeDirectory()] attributes:nil]; NSArray* filebase = [[NSBundle mainBundle] pathsForResourcesOfType:@"m4a" inDirectory:@""]; /// THESE VARIABLES ARE DECLARED UNSIGNED *** ON PURPOSE *** unsigned i, total = [filebase count]; i = 0; total = [filebase count]; [NSApp beginSheet:progressWindow modalForWindow:[NSApp mainWindow] modalDelegate:nil didEndSelector:nil contextInfo:nil]; [progressWindowBar setUsesThreadedAnimation:YES]; [progressWindowBar setIndeterminate:NO]; [progressWindowBar setMinValue:0.0]; [progressWindowBar setMaxValue:(double)total]; [progressWindowBar setDoubleValue:0.0]; for (i=0; i<total; ++i) { [progressWindowBar display]; NSString* path = [filebase objectAtIndex:i]; NSString* fileName = [path lastPathComponent]; /// /// *** WARNING HERE *** /// /// IF YOU PLAN TO TOUCH THIS FOLLOWING LINE BE REALLY CAREFUL. AN ERROR HERE CAN RESULT IN DATA DELETION FROM YOUR HD!, /// SINCE I DID NOT WROTE FILE COMPROBATION ROUTINES YET AND THE PROCESS WILL ***OVERWRITE*** DATA WITHOUT ASKING. [fileManager copyPath:path toPath:[NSString stringWithFormat:@"%@/Music/MediaPacks/Insphire - AfterDark/%@", NSHomeDirectory(), fileName] handler:nil]; [progressWindowBar setDoubleValue:(double)(i+1)]; NSLog(path); /// THIS LINE IS FOR VISUAL PURPOSES ONLY, IT ADD'S A 1 SECOND PAUSE BETWEEN EVERY LOOP ACTION /// THAT WAY IM SURE THAT THE APPLICATION DONT FEEL'S "HANG".....DIRTY, BUT WORKS. DIEGO. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]; } /// LET'S CONSERVE MEMORY, WE DEALLOCATE AND DESTROY THE FILEMANAGER OBJECT, WE DONT NEED IT ANYMORE. [fileManager dealloc]; [fileManager release]; /// WE DESTROY THE "COPY PROGRESS" SHEET [NSApp endSheet:progressWindow]; [progressWindow orderOut:self]; /// WE DISPLAY THE "COPY OK" SHEET /// AT THIS MOMENT, THE APPLICATION IS NOT CHECKING FOR ERRORS IN THE FILE COPY PROGRESS. /// REMEMBER TO WRITE A CUSTOM CLASS FOR ALL THE APPLICATION DIALOGS, INSTEAD OF CREATING THE ALERTS MANUALLY. [NSApp beginSheet:copyOkWindow modalForWindow:[NSApp mainWindow] modalDelegate:nil didEndSelector:nil contextInfo:nil];}- (IBAction)showProgressDialog:(id)sender{ }- (IBAction)viewFiles:(id)sender{ NSString* path = [NSString stringWithFormat:@"%@/Music/MediaPacks", NSHomeDirectory()]; [[NSWorkspace sharedWorkspace]openFile:path]; [NSApp endSheet:copyOkWindow]; [copyOkWindow orderOut:self];}- (IBAction)dismissCopyPanel:(id)sender{ [NSApp endSheet:copyOkWindow]; [copyOkWindow orderOut:self];}- (void) QTMovieDidEndNotification: (NSNotification *) aNotification{ /// WHEN FINISHING PLAYING THE ACTUAL TRACK, WE INSTRUCT THE MEDIA ENGINE TO GO FOR THE NEXT ONE. SIMPLE EH? :P [self next:nil];}- (void) QTMovieTimeDidChangeNotification: (NSNotification *) aNotification{ /// TO DO: CUSTOM ROUTINE FOR UPDATING ALL INTERFACE COMPONENTS I.E: ELAPSED TIME, PROGRESS BAR, ETC.}- (void) displayUpdate: (NSTimer *) timer{ NSString* timeString = QTStringFromTime([mainSoundEngine currentTime]); NSString* formattedTime = [timeString substringWithRange:NSMakeRange(5,5)]; /// WE UPDATE ALL THE UI ELEMENTS [playTime setStringValue:formattedTime];}+ (void)initialization{ /// INITIALIZATION OF THE MAIN PLAYLIST /// THIS CLASS METHOD IS VERY IMPORTANT AND IS BEING CALLED FROM THE "APPENGINE" CLASS. trackList = [[NSBundle mainBundle] pathsForResourcesOfType:@"m4a" inDirectory:@""];}@end