#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 VARIABLES
int 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