{
ACTIONS = {
changeGeneralSetting = id;
+ changeSharingSetting = id;
changeStatusWindowSetting = id;
clearHotKey = id;
editHotKey = id;
appearanceEffectPopup = NSPopUpButton;
appearanceSpeedSlider = NSSlider;
artistCheckbox = NSButton;
+ hostTextField = NSTextField;
hotKeysTableView = NSTableView;
launchAtLoginCheckbox = NSButton;
launchPlayerAtLaunchCheckbox = NSButton;
+ manualView = NSView;
menuTableView = CustomMenuTableView;
nameCheckbox = NSButton;
ratingCheckbox = NSButton;
+ selectPlayerBox = NSBox;
+ selectPlayerSheet = NSPanel;
+ selectSharedPlayerButton = NSButton;
+ shareMenuTunesCheckbox = NSButton;
+ sharePasswordCheckbox = NSButton;
+ sharePasswordTextField = NSTextField;
+ sharingTableView = NSTableView;
showOnChangeCheckbox = NSButton;
songsInAdvance = NSTextField;
trackNumberCheckbox = NSButton;
trackTimeCheckbox = NSButton;
+ useSharedMenuTunesCheckbox = NSButton;
vanishDelaySlider = NSSlider;
vanishEffectPopup = NSPopUpButton;
vanishSpeedSlider = NSSlider;
window = NSWindow;
+ zeroConfView = NSView;
};
SUPERCLASS = NSObject;
}
<dict>
<key>IBDocumentLocation</key>
<string>6 66 356 240 0 0 1152 746 </string>
+ <key>IBEditorPositions</key>
+ <dict>
+ <key>634</key>
+ <string>386 421 380 180 0 0 1152 746 </string>
+ <key>639</key>
+ <string>386 450 380 122 0 0 1152 746 </string>
+ </dict>
<key>IBFramework Version</key>
- <string>291.0</string>
- <key>IBGroupedObjects</key>
- <dict/>
- <key>IBLastGroupID</key>
- <string>1</string>
+ <string>349.0</string>
<key>IBLockedObjects</key>
<array>
<integer>281</integer>
<key>IBOpenObjects</key>
<array>
<integer>6</integer>
+ <integer>634</integer>
+ <integer>639</integer>
</array>
<key>IBSystem Version</key>
- <string>6L60</string>
+ <string>7B85</string>
</dict>
</plist>
#import <ITMTRemote/ITMTRemote.h>
#import "MTBlingController.h"
-@class StatusWindowController, MenuController;
+@class StatusWindowController, MenuController, NetworkController;
@interface MainController : NSObject
{
StatusWindowController *statusWindowController; //Shows status windows
MenuController *menuController;
+ NetworkController *networkController;
NSUserDefaults *df;
MTBlingController *bling;
//
+- (void)setServerStatus:(BOOL)newStatus;
+- (BOOL)connectToServer;
+- (BOOL)disconnectFromServer;
+- (void)networkError:(NSException *)exception;
+
+//
+
- (ITMTRemote *)currentRemote;
- (void)clearHotKeys;
- (void)setupHotKeys;
#import "MainController.h"
#import "MenuController.h"
#import "PreferencesController.h"
+#import "NetworkController.h"
#import <ITKit/ITHotKeyCenter.h>
#import <ITKit/ITHotKey.h>
#import <ITKit/ITKeyCombo.h>
}
currentRemote = [self loadRemote];
- [currentRemote begin];
+ [[self currentRemote] begin];
+
+ //Turn on network stuff if needed
+ networkController = [[NetworkController alloc] init];
+ if ([df boolForKey:@"enableSharing"]) {
+ [self setServerStatus:YES];
+ } else if ([df boolForKey:@"useSharedPlayer"] && [df boolForKey:@"alwaysUseSharedPlayer"]) {
+ [self connectToServer];
+ }
//Setup for notification of the remote player launching or quitting
[[[NSWorkspace sharedWorkspace] notificationCenter]
userInfo:nil
repeats:YES] retain];
- if ([currentRemote playerRunningState] == ITMTRemotePlayerRunning) {
- [self applicationLaunched:nil];
- } else {
- if ([df boolForKey:@"LaunchPlayerWithMT"])
- [self showPlayer];
- else
- [self applicationTerminated:nil];
- }
+ NS_DURING
+ if ([[self currentRemote] playerRunningState] == ITMTRemotePlayerRunning) {
+ [self applicationLaunched:nil];
+ } else {
+ if ([df boolForKey:@"LaunchPlayerWithMT"])
+ [self showPlayer];
+ else
+ [self applicationTerminated:nil];
+ }
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
[statusItem setImage:[NSImage imageNamed:@"MenuNormal"]];
[statusItem setAlternateImage:[NSImage imageNamed:@"MenuInverted"]];
+ [networkController startRemoteServerSearch];
[NSApp deactivate];
}
[self setupHotKeys];
if (![refreshTimer isValid]) {
[refreshTimer release];
- refreshTimer = refreshTimer = [[NSTimer scheduledTimerWithTimeInterval:0.5
+ refreshTimer = [[NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:@selector(timerUpdate)
userInfo:nil
- (BOOL)songIsPlaying
{
- return ( ! ([[currentRemote playerStateUniqueIdentifier] isEqualToString:@"0-0"]) );
+ NSString *identifier;
+ NS_DURING
+ identifier = [[self currentRemote] playerStateUniqueIdentifier];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
+ return ( ! ([identifier isEqualToString:@"0-0"]) );
}
- (BOOL)radioIsPlaying
{
- return ( [currentRemote currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist );
+ ITMTRemotePlayerPlaylistClass class;
+ NS_DURING
+ class = [[self currentRemote] currentPlaylistClass];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
+ return (class == ITMTRemotePlayerRadioPlaylist );
}
- (BOOL)songChanged
{
- return ( ! [[currentRemote playerStateUniqueIdentifier] isEqualToString:_latestSongIdentifier] );
+ NSString *identifier;
+ NS_DURING
+ identifier = [[self currentRemote] playerStateUniqueIdentifier];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
+ return ( ! [identifier isEqualToString:_latestSongIdentifier] );
}
- (NSString *)latestSongIdentifier
- (void)timerUpdate
{
+ if ([networkController isConnectedToServer]) {
+ [statusItem setMenu:[menuController menu]];
+ }
+
if ( [self songChanged] && (timerUpdating != YES) ) {
ITDebugLog(@"The song changed.");
timerUpdating = YES;
- latestPlaylistClass = [currentRemote currentPlaylistClass];
+
+ NS_DURING
+ latestPlaylistClass = [[self currentRemote] currentPlaylistClass];
[menuController rebuildSubmenus];
if ( [df boolForKey:@"showSongInfoOnChange"] ) {
[self performSelector:@selector(showCurrentTrackInfo) withObject:nil afterDelay:0.0];
}
- [self setLatestSongIdentifier:[currentRemote playerStateUniqueIdentifier]];
+ [self setLatestSongIdentifier:[[self currentRemote] playerStateUniqueIdentifier]];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
timerUpdating = NO;
}
- (void)menuClicked
{
ITDebugLog(@"Menu clicked.");
- if ([currentRemote playerRunningState] == ITMTRemotePlayerRunning) {
- [statusItem setMenu:[menuController menu]];
- } else {
- [statusItem setMenu:[menuController menuForNoPlayer]];
+ if ([networkController isConnectedToServer]) {
+ //Used the cached version
+ return;
}
+
+ NS_DURING
+ if ([[self currentRemote] playerRunningState] == ITMTRemotePlayerRunning) {
+ [statusItem setMenu:[menuController menu]];
+ } else {
+ [statusItem setMenu:[menuController menuForNoPlayer]];
+ }
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
//
- (void)playPause
{
- ITMTRemotePlayerPlayingState state = [currentRemote playerPlayingState];
- ITDebugLog(@"Play/Pause toggled");
- if (state == ITMTRemotePlayerPlaying) {
- [currentRemote pause];
- } else if ((state == ITMTRemotePlayerForwarding) || (state == ITMTRemotePlayerRewinding)) {
- [currentRemote pause];
- [currentRemote play];
- } else {
- [currentRemote play];
- }
+ NS_DURING
+ ITMTRemotePlayerPlayingState state = [[self currentRemote] playerPlayingState];
+ ITDebugLog(@"Play/Pause toggled");
+ if (state == ITMTRemotePlayerPlaying) {
+ [[self currentRemote] pause];
+ } else if ((state == ITMTRemotePlayerForwarding) || (state == ITMTRemotePlayerRewinding)) {
+ [[self currentRemote] pause];
+ [[self currentRemote] play];
+ } else {
+ [[self currentRemote] play];
+ }
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
+
[self timerUpdate];
}
- (void)nextSong
{
ITDebugLog(@"Going to next song.");
- [currentRemote goToNextSong];
+ NS_DURING
+ [[self currentRemote] goToNextSong];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
[self timerUpdate];
}
- (void)prevSong
{
ITDebugLog(@"Going to previous song.");
- [currentRemote goToPreviousSong];
+ NS_DURING
+ [[self currentRemote] goToPreviousSong];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
[self timerUpdate];
}
- (void)fastForward
{
ITDebugLog(@"Fast forwarding.");
- [currentRemote forward];
+ NS_DURING
+ [[self currentRemote] forward];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
[self timerUpdate];
}
- (void)rewind
{
ITDebugLog(@"Rewinding.");
- [currentRemote rewind];
+ NS_DURING
+ [[self currentRemote] rewind];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
[self timerUpdate];
}
- (void)selectPlaylistAtIndex:(int)index
{
ITDebugLog(@"Selecting playlist %i", index);
- [currentRemote switchToPlaylistAtIndex:index];
+ NS_DURING
+ [[self currentRemote] switchToPlaylistAtIndex:index];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
[self timerUpdate];
}
- (void)selectSongAtIndex:(int)index
{
ITDebugLog(@"Selecting song %i", index);
- [currentRemote switchToSongAtIndex:index];
+ NS_DURING
+ [[self currentRemote] switchToSongAtIndex:index];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
[self timerUpdate];
}
- (void)selectSongRating:(int)rating
{
ITDebugLog(@"Selecting song rating %i", rating);
- [currentRemote setCurrentSongRating:(float)rating / 100.0];
+ NS_DURING
+ [[self currentRemote] setCurrentSongRating:(float)rating / 100.0];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
[self timerUpdate];
}
- (void)selectEQPresetAtIndex:(int)index
{
ITDebugLog(@"Selecting EQ preset %i", index);
- [currentRemote switchToEQAtIndex:index];
+ NS_DURING
+ [[self currentRemote] switchToEQAtIndex:index];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
[self timerUpdate];
}
ITDebugLog(@"Beginning show player.");
if ( ( playerRunningState == ITMTRemotePlayerRunning) ) {
ITDebugLog(@"Showing player interface.");
- [currentRemote showPrimaryInterface];
+ NS_DURING
+ [[self currentRemote] showPrimaryInterface];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
} else {
ITDebugLog(@"Launching player.");
- if (![[NSWorkspace sharedWorkspace] launchApplication:[currentRemote playerFullName]]) {
- ITDebugLog(@"Error Launching Player");
- }
+ NS_DURING
+ if (![[NSWorkspace sharedWorkspace] launchApplication:[[self currentRemote] playerFullName]]) {
+ ITDebugLog(@"Error Launching Player");
+ }
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
ITDebugLog(@"Finished show player.");
}
- (void)showCurrentTrackInfo
{
- ITMTRemotePlayerSource source = [currentRemote currentSource];
- NSString *title = [currentRemote currentSongTitle];
+ ITMTRemotePlayerSource source;
+ NSString *title;
NSString *album = nil;
NSString *artist = nil;
NSString *time = nil;
NSString *track = nil;
int rating = -1;
+ NS_DURING
+ source = [[self currentRemote] currentSource];
+ title = [[self currentRemote] currentSongTitle];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
+
ITDebugLog(@"Showing track info status window.");
if ( title ) {
if ( [df boolForKey:@"showAlbum"] ) {
- album = [currentRemote currentSongAlbum];
+ NS_DURING
+ album = [[self currentRemote] currentSongAlbum];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
if ( [df boolForKey:@"showArtist"] ) {
- artist = [currentRemote currentSongArtist];
+ NS_DURING
+ artist = [[self currentRemote] currentSongArtist];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
if ( [df boolForKey:@"showTime"] ) {
- time = [NSString stringWithFormat:@"%@: %@ / %@",
+ NS_DURING
+ time = [NSString stringWithFormat:@"%@: %@ / %@",
@"Time",
- [currentRemote currentSongElapsed],
- [currentRemote currentSongLength]];
+ [[self currentRemote] currentSongElapsed],
+ [[self currentRemote] currentSongLength]];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
if ( [df boolForKey:@"showTrackNumber"] ) {
- int trackNo = [currentRemote currentSongTrack];
- int trackCount = [currentRemote currentAlbumTrackCount];
+ int trackNo;
+ int trackCount;
+
+ NS_DURING
+ trackNo = [[self currentRemote] currentSongTrack];
+ trackCount = [[self currentRemote] currentAlbumTrackCount];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
if ( (trackNo > 0) || (trackCount > 0) ) {
track = [NSString stringWithFormat:@"%@: %i %@ %i",
}
if ( [df boolForKey:@"showTrackRating"] ) {
- float currentRating = [currentRemote currentSongRating];
+ float currentRating;
+
+ NS_DURING
+ currentRating = [[self currentRemote] currentSongRating];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
+
if (currentRating >= 0.0) {
rating = ( currentRating * 5 );
}
- (void)showUpcomingSongs
{
- int curPlaylist = [currentRemote currentPlaylistIndex];
- int numSongs = [currentRemote numberOfSongsInPlaylistAtIndex:curPlaylist];
+ int numSongs;
+
+ NS_DURING
+ numSongs = [[self currentRemote] numberOfSongsInPlaylistAtIndex:[[self currentRemote] currentPlaylistIndex]];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
+
ITDebugLog(@"Showing upcoming songs status window.");
- if (numSongs > 0) {
- NSMutableArray *songList = [NSMutableArray arrayWithCapacity:5];
- int numSongsInAdvance = [df integerForKey:@"SongsInAdvance"];
- int curTrack = [currentRemote currentSongIndex];
- int i;
-
- for (i = curTrack + 1; i <= curTrack + numSongsInAdvance; i++) {
- if (i <= numSongs) {
- [songList addObject:[currentRemote songTitleAtIndex:i]];
+ NS_DURING
+ if (numSongs > 0) {
+ NSMutableArray *songList = [NSMutableArray arrayWithCapacity:5];
+ int numSongsInAdvance = [df integerForKey:@"SongsInAdvance"];
+ int curTrack = [[self currentRemote] currentSongIndex];
+ int i;
+
+ for (i = curTrack + 1; i <= curTrack + numSongsInAdvance; i++) {
+ if (i <= numSongs) {
+ [songList addObject:[[self currentRemote] songTitleAtIndex:i]];
+ }
}
+
+ [statusWindowController showUpcomingSongsWindowWithTitles:songList];
+ } else {
+ [statusWindowController showUpcomingSongsWindowWithTitles:[NSArray arrayWithObject:NSLocalizedString(@"noUpcomingSongs", @"No upcoming songs.")]];
}
-
- [statusWindowController showUpcomingSongsWindowWithTitles:songList];
-
- } else {
- [statusWindowController showUpcomingSongsWindowWithTitles:[NSArray arrayWithObject:NSLocalizedString(@"noUpcomingSongs", @"No upcoming songs.")]];
- }
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
- (void)incrementVolume
{
- float volume = [currentRemote volume];
- float dispVol = volume;
- ITDebugLog(@"Incrementing volume.");
- volume += 0.110;
- dispVol += 0.100;
+ NS_DURING
+ float volume = [[self currentRemote] volume];
+ float dispVol = volume;
+ ITDebugLog(@"Incrementing volume.");
+ volume += 0.110;
+ dispVol += 0.100;
+
+ if (volume > 1.0) {
+ volume = 1.0;
+ dispVol = 1.0;
+ }
- if (volume > 1.0) {
- volume = 1.0;
- dispVol = 1.0;
- }
-
- ITDebugLog(@"Setting volume to %f", volume);
- [currentRemote setVolume:volume];
-
- // Show volume status window
- [statusWindowController showVolumeWindowWithLevel:dispVol];
+ ITDebugLog(@"Setting volume to %f", volume);
+ [[self currentRemote] setVolume:volume];
+
+ // Show volume status window
+ [statusWindowController showVolumeWindowWithLevel:dispVol];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
- (void)decrementVolume
{
- float volume = [currentRemote volume];
- float dispVol = volume;
- ITDebugLog(@"Decrementing volume.");
- volume -= 0.090;
- dispVol -= 0.100;
-
- if (volume < 0.0) {
- volume = 0.0;
- dispVol = 0.0;
- }
+ NS_DURING
+ float volume = [[self currentRemote] volume];
+ float dispVol = volume;
+ ITDebugLog(@"Decrementing volume.");
+ volume -= 0.090;
+ dispVol -= 0.100;
- ITDebugLog(@"Setting volume to %f", volume);
- [currentRemote setVolume:volume];
-
- //Show volume status window
- [statusWindowController showVolumeWindowWithLevel:dispVol];
+ if (volume < 0.0) {
+ volume = 0.0;
+ dispVol = 0.0;
+ }
+
+ ITDebugLog(@"Setting volume to %f", volume);
+ [[self currentRemote] setVolume:volume];
+
+ //Show volume status window
+ [statusWindowController showVolumeWindowWithLevel:dispVol];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
- (void)incrementRating
{
- float rating = [currentRemote currentSongRating];
- ITDebugLog(@"Incrementing rating.");
-
- if ([currentRemote currentPlaylistIndex] == 0) {
- ITDebugLog(@"No song playing, rating change aborted.");
- return;
- }
-
- rating += 0.2;
- if (rating > 1.0) {
- rating = 1.0;
- }
- ITDebugLog(@"Setting rating to %f", rating);
- [currentRemote setCurrentSongRating:rating];
-
- //Show rating status window
- [statusWindowController showRatingWindowWithRating:rating];
+ NS_DURING
+ float rating = [[self currentRemote] currentSongRating];
+ ITDebugLog(@"Incrementing rating.");
+
+ if ([[self currentRemote] currentPlaylistIndex] == 0) {
+ ITDebugLog(@"No song playing, rating change aborted.");
+ return;
+ }
+
+ rating += 0.2;
+ if (rating > 1.0) {
+ rating = 1.0;
+ }
+ ITDebugLog(@"Setting rating to %f", rating);
+ [[self currentRemote] setCurrentSongRating:rating];
+
+ //Show rating status window
+ [statusWindowController showRatingWindowWithRating:rating];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
- (void)decrementRating
{
- float rating = [currentRemote currentSongRating];
- ITDebugLog(@"Decrementing rating.");
-
- if ([currentRemote currentPlaylistIndex] == 0) {
- ITDebugLog(@"No song playing, rating change aborted.");
- return;
- }
-
- rating -= 0.2;
- if (rating < 0.0) {
- rating = 0.0;
- }
- ITDebugLog(@"Setting rating to %f", rating);
- [currentRemote setCurrentSongRating:rating];
-
- //Show rating status window
- [statusWindowController showRatingWindowWithRating:rating];
+ NS_DURING
+ float rating = [[self currentRemote] currentSongRating];
+ ITDebugLog(@"Decrementing rating.");
+
+ if ([[self currentRemote] currentPlaylistIndex] == 0) {
+ ITDebugLog(@"No song playing, rating change aborted.");
+ return;
+ }
+
+ rating -= 0.2;
+ if (rating < 0.0) {
+ rating = 0.0;
+ }
+ ITDebugLog(@"Setting rating to %f", rating);
+ [[self currentRemote] setCurrentSongRating:rating];
+
+ //Show rating status window
+ [statusWindowController showRatingWindowWithRating:rating];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
- (void)toggleLoop
{
- ITMTRemotePlayerRepeatMode repeatMode = [currentRemote repeatMode];
- ITDebugLog(@"Toggling repeat mode.");
- switch (repeatMode) {
- case ITMTRemotePlayerRepeatOff:
- repeatMode = ITMTRemotePlayerRepeatAll;
- break;
- case ITMTRemotePlayerRepeatAll:
- repeatMode = ITMTRemotePlayerRepeatOne;
- break;
- case ITMTRemotePlayerRepeatOne:
- repeatMode = ITMTRemotePlayerRepeatOff;
- break;
- }
- ITDebugLog(@"Setting repeat mode to %i", repeatMode);
- [currentRemote setRepeatMode:repeatMode];
-
- //Show loop status window
- [statusWindowController showRepeatWindowWithMode:repeatMode];
+ NS_DURING
+ ITMTRemotePlayerRepeatMode repeatMode = [[self currentRemote] repeatMode];
+ ITDebugLog(@"Toggling repeat mode.");
+ switch (repeatMode) {
+ case ITMTRemotePlayerRepeatOff:
+ repeatMode = ITMTRemotePlayerRepeatAll;
+ break;
+ case ITMTRemotePlayerRepeatAll:
+ repeatMode = ITMTRemotePlayerRepeatOne;
+ break;
+ case ITMTRemotePlayerRepeatOne:
+ repeatMode = ITMTRemotePlayerRepeatOff;
+ break;
+ }
+ ITDebugLog(@"Setting repeat mode to %i", repeatMode);
+ [[self currentRemote] setRepeatMode:repeatMode];
+
+ //Show loop status window
+ [statusWindowController showRepeatWindowWithMode:repeatMode];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
- (void)toggleShuffle
{
- BOOL newShuffleEnabled = ( ! [currentRemote shuffleEnabled] );
- ITDebugLog(@"Toggling shuffle mode.");
- [currentRemote setShuffleEnabled:newShuffleEnabled];
- //Show shuffle status window
- ITDebugLog(@"Setting shuffle mode to %i", newShuffleEnabled);
- [statusWindowController showShuffleWindow:newShuffleEnabled];
+ NS_DURING
+ BOOL newShuffleEnabled = ( ! [[self currentRemote] shuffleEnabled] );
+ ITDebugLog(@"Toggling shuffle mode.");
+ [[self currentRemote] setShuffleEnabled:newShuffleEnabled];
+ //Show shuffle status window
+ ITDebugLog(@"Setting shuffle mode to %i", newShuffleEnabled);
+ [statusWindowController showShuffleWindow:newShuffleEnabled];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
- (void)registerNowOK
[NSApp terminate:self];
}
+/*************************************************************************/
+#pragma mark -
+#pragma mark NETWORK HANDLERS
+/*************************************************************************/
+
+- (void)setServerStatus:(BOOL)newStatus
+{
+ if (newStatus) {
+ //Turn on
+ [networkController setServerStatus:YES];
+ } else {
+ //Tear down
+ [networkController setServerStatus:NO];
+ }
+}
+
+- (BOOL)connectToServer
+{
+ //Connect
+ if ([networkController connectToHost:[df stringForKey:@"sharedPlayerHost"]]) {
+ currentRemote = [networkController sharedRemote];
+ [refreshTimer invalidate];
+ return YES;
+ } else {
+ currentRemote = [remoteArray objectAtIndex:0];
+ return NO;
+ }
+}
+
+- (BOOL)disconnectFromServer
+{
+ //Disconnect
+ currentRemote = [remoteArray objectAtIndex:0];
+ [networkController disconnect];
+ [self timerUpdate];
+ return YES;
+}
+
+- (void)networkError:(NSException *)exception
+{
+ ITDebugLog(@"Remote exception thrown: %@: %@", [exception name], [exception reason]);
+ NSRunAlertPanel(@"Remote MenuTunes Disconnected", @"The MenuTunes server you were connected to stopped responding or quit. MenuTunes will revert back to the local player.", @"OK", nil, nil);
+ if ([networkController isConnectedToServer] && [self disconnectFromServer]) {
+ } else {
+ ITDebugLog(@"CRITICAL ERROR DISCONNECTING!");
+ }
+}
/*************************************************************************/
#pragma mark -
- (void)applicationLaunched:(NSNotification *)note
{
- if (!note || [[[note userInfo] objectForKey:@"NSApplicationName"] isEqualToString:[currentRemote playerFullName]]) {
- ITDebugLog(@"Remote application launched.");
- playerRunningState = ITMTRemotePlayerRunning;
- [currentRemote begin];
- [self setLatestSongIdentifier:@""];
- [self timerUpdate];
- refreshTimer = [[NSTimer scheduledTimerWithTimeInterval:0.5
- target:self
- selector:@selector(timerUpdate)
- userInfo:nil
- repeats:YES] retain];
- //[NSThread detachNewThreadSelector:@selector(startTimerInNewThread) toTarget:self withObject:nil];
- [self setupHotKeys];
- }
+ NS_DURING
+ if (!note || [[[note userInfo] objectForKey:@"NSApplicationName"] isEqualToString:[[self currentRemote] playerFullName]]) {
+ ITDebugLog(@"Remote application launched.");
+ playerRunningState = ITMTRemotePlayerRunning;
+ [[self currentRemote] begin];
+ [self setLatestSongIdentifier:@""];
+ [self timerUpdate];
+ refreshTimer = [[NSTimer scheduledTimerWithTimeInterval:([networkController isConnectedToServer] ? 10.0 : 0.5)
+ target:self
+ selector:@selector(timerUpdate)
+ userInfo:nil
+ repeats:YES] retain];
+ //[NSThread detachNewThreadSelector:@selector(startTimerInNewThread) toTarget:self withObject:nil];
+ [self setupHotKeys];
+ }
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
- (void)applicationTerminated:(NSNotification *)note
{
- if (!note || [[[note userInfo] objectForKey:@"NSApplicationName"] isEqualToString:[currentRemote playerFullName]]) {
- ITDebugLog(@"Remote application terminated.");
- [currentRemote halt];
- [refreshTimer invalidate];
- [refreshTimer release];
- refreshTimer = nil;
- [self clearHotKeys];
- playerRunningState = ITMTRemotePlayerNotRunning;
- }
+ NS_DURING
+ if (!note || [[[note userInfo] objectForKey:@"NSApplicationName"] isEqualToString:[[self currentRemote] playerFullName]]) {
+ ITDebugLog(@"Remote application terminated.");
+ [[self currentRemote] halt];
+ [refreshTimer invalidate];
+ [refreshTimer release];
+ refreshTimer = nil;
+ [self clearHotKeys];
+ playerRunningState = ITMTRemotePlayerNotRunning;
+ }
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
}
- (void)applicationWillTerminate:(NSNotification *)note
{
[self clearHotKeys];
+ [networkController stopRemoteServerSearch];
[[NSStatusBar systemStatusBar] removeStatusItem:statusItem];
}
[statusItem release];
[statusWindowController release];
[menuController release];
+ [networkController release];
[super dealloc];
}
//
#import <Cocoa/Cocoa.h>
-#import "ITMTRemote.h"
// Internal: To be used with NSMenuItems as their tag, for use with the NSMenuValidation stuff.
// Also will be used in supplying the controller with the layout to use for the MenuItems, unless
NSMenu *_currentMenu;
NSMenu *_ratingMenu, *_upcomingSongsMenu, *_eqMenu, *_playlistsMenu; //Submenus
- ITMTRemote *currentRemote;
int _currentPlaylist, _currentTrack;
BOOL _playingRadio;
}
#import "MenuController.h"
#import "MainController.h"
+#import "ITMTRemote.h"
#import <ITFoundation/ITDebug.h>
#import <ITKit/ITHotKeyCenter.h>
#import <ITKit/ITHotKey.h>
NSEnumerator *itemEnum;
ITHotKey *hotKey;
NSArray *hotKeys = [[ITHotKeyCenter sharedCenter] allHotKeys];
+ int currentSongRating;
//Get the information
- _currentPlaylist = [currentRemote currentPlaylistIndex];
- _playingRadio = ([currentRemote currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
+ NS_DURING
+ _currentPlaylist = [[[MainController sharedController] currentRemote] currentPlaylistIndex];
+ _playingRadio = ([[[MainController sharedController] currentRemote] currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
+ currentSongRating = ( [[[MainController sharedController] currentRemote] currentSongRating] != -1 );
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
ITDebugLog(@"Reset menu if required.");
}
ITDebugLog(@"Set \"Play\"/\"Pause\" menu item's title to correct state.");
- switch ([currentRemote playerPlayingState]) {
- case ITMTRemotePlayerPlaying:
- [tempItem setTitle:NSLocalizedString(@"pause", @"Pause")];
- break;
- case ITMTRemotePlayerRewinding:
- case ITMTRemotePlayerForwarding:
- [tempItem setTitle:NSLocalizedString(@"resume", @"Resume")];
- break;
- default:
- break;
- }
+ NS_DURING
+ switch ([[[MainController sharedController] currentRemote] playerPlayingState]) {
+ case ITMTRemotePlayerPlaying:
+ [tempItem setTitle:NSLocalizedString(@"pause", @"Pause")];
+ break;
+ case ITMTRemotePlayerRewinding:
+ case ITMTRemotePlayerForwarding:
+ [tempItem setTitle:NSLocalizedString(@"resume", @"Resume")];
+ break;
+ default:
+ break;
+ }
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
} else if ([nextObject isEqualToString:@"nextTrack"]) {
ITDebugLog(@"Add \"Next Track\" menu item.");
tempItem = [menu addItemWithTitle:NSLocalizedString(@"nextTrack", @"Next Track")
}
} else if ([nextObject isEqualToString:@"showPlayer"]) {
ITDebugLog(@"Add \"Show Player\" menu item.");
- tempItem = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@",
- NSLocalizedString(@"show", @"Show"),
- [[[MainController sharedController] currentRemote] playerSimpleName]]
- action:@selector(performMainMenuAction:)
- keyEquivalent:@""];
+ NS_DURING
+ tempItem = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@",
+ NSLocalizedString(@"show", @"Show"),
+ [[[MainController sharedController] currentRemote] playerSimpleName]]
+ action:@selector(performMainMenuAction:)
+ keyEquivalent:@""];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
itemEnum = [hotKeys objectEnumerator];
while ( (hotKey = [itemEnum nextObject]) ) {
ITDebugLog(@"Check to see if a Track is playing...");
//Handle playing radio too
if (_currentPlaylist) {
- NSString *title = [currentRemote currentSongTitle];
+ NSString *title;
+ NS_DURING
+ title = [[[MainController sharedController] currentRemote] currentSongTitle];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
ITDebugLog(@"A Track is Playing, Add \"Track Info\" menu items.");
ITDebugLog(@"Add \"Now Playing\" menu item.");
[menu addItemWithTitle:NSLocalizedString(@"nowPlaying", @"Now Playing") action:NULL keyEquivalent:@""];
if (!_playingRadio) {
if ([defaults boolForKey:@"showAlbum"]) {
- NSString *curAlbum = [currentRemote currentSongAlbum];
+ NSString *curAlbum;
+ NS_DURING
+ curAlbum = [[[MainController sharedController] currentRemote] currentSongAlbum];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
ITDebugLog(@"Add Track Album (\"%@\") menu item.", curAlbum);
if ( curAlbum ) {
[menu indentItem:
}
if ([defaults boolForKey:@"showArtist"]) {
- NSString *curArtist = [currentRemote currentSongArtist];
+ NSString *curArtist;
+ NS_DURING
+ curArtist = [[[MainController sharedController] currentRemote] currentSongArtist];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
ITDebugLog(@"Add Track Artist (\"%@\") menu item.", curArtist);
if ( curArtist ) {
[menu indentItem:
}
if ([defaults boolForKey:@"showTrackNumber"]) {
- int track = [currentRemote currentSongTrack];
+ int track;
+ NS_DURING
+ track = [[[MainController sharedController] currentRemote] currentSongTrack];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
ITDebugLog(@"Add Track Number (\"Track %i\") menu item.", track);
if ( track > 0 ) {
[menu indentItem:
}
}
- if ([defaults boolForKey:@"showTime"] && ( ([currentRemote currentSongElapsed] != nil) || ([currentRemote currentSongLength] != nil) )) {
- ITDebugLog(@"Add Track Elapsed (\"%@/%@\") menu item.", [currentRemote currentSongElapsed], [currentRemote currentSongLength]);
- [menu indentItem:[menu addItemWithTitle:[NSString stringWithFormat:@"%@/%@", [currentRemote currentSongElapsed], [currentRemote currentSongLength]] action:nil keyEquivalent:@""]];
- }
+ NS_DURING
+ if ([defaults boolForKey:@"showTime"] && ( ([[[MainController sharedController] currentRemote] currentSongElapsed] != nil) || ([[[MainController sharedController] currentRemote] currentSongLength] != nil) )) {
+ ITDebugLog(@"Add Track Elapsed (\"%@/%@\") menu item.", [[[MainController sharedController] currentRemote] currentSongElapsed], [[[MainController sharedController] currentRemote] currentSongLength]);
+ [menu indentItem:[menu addItemWithTitle:[NSString stringWithFormat:@"%@/%@", [[[MainController sharedController] currentRemote] currentSongElapsed], [[[MainController sharedController] currentRemote] currentSongLength]] action:nil keyEquivalent:@""]];
+ }
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
if (!_playingRadio) {
- if ([defaults boolForKey:@"showTrackRating"] && ( [currentRemote currentSongRating] != -1.0 )) {
- NSString *string = nil;
- switch ((int)([currentRemote currentSongRating] * 5)) {
- case 0:
- string = [NSString stringWithUTF8String:"☆☆☆☆☆"];
- break;
- case 1:
- string = [NSString stringWithUTF8String:"★☆☆☆☆"];
- break;
- case 2:
- string = [NSString stringWithUTF8String:"★★☆☆☆"];
- break;
- case 3:
- string = [NSString stringWithUTF8String:"★★★☆☆"];
- break;
- case 4:
- string = [NSString stringWithUTF8String:"★★★★☆"];
- break;
- case 5:
- string = [NSString stringWithUTF8String:"★★★★★"];
- break;
+ NS_DURING
+ if ([defaults boolForKey:@"showTrackRating"] && ( [[[MainController sharedController] currentRemote] currentSongRating] != -1.0 )) {
+ NSString *string = nil;
+ switch ((int)([[[MainController sharedController] currentRemote] currentSongRating] * 5)) {
+ case 0:
+ string = [NSString stringWithUTF8String:"☆☆☆☆☆"];
+ break;
+ case 1:
+ string = [NSString stringWithUTF8String:"★☆☆☆☆"];
+ break;
+ case 2:
+ string = [NSString stringWithUTF8String:"★★☆☆☆"];
+ break;
+ case 3:
+ string = [NSString stringWithUTF8String:"★★★☆☆"];
+ break;
+ case 4:
+ string = [NSString stringWithUTF8String:"★★★★☆"];
+ break;
+ case 5:
+ string = [NSString stringWithUTF8String:"★★★★★"];
+ break;
+ }
+ ITDebugLog(@"Add Track Rating (\"%@\") menu item.", string);
+ [menu indentItem:[menu addItemWithTitle:string action:nil keyEquivalent:@""]];
}
- ITDebugLog(@"Add Track Rating (\"%@\") menu item.", string);
- [menu indentItem:[menu addItemWithTitle:string action:nil keyEquivalent:@""]];
- }
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
}
} else {
ITDebugLog(@"No Track is Playing, Add \"No Song\" menu item.");
while ( (tempItem = [itemEnum nextObject]) ) {
[tempItem setState:NSOffState];
}
- [[_eqMenu itemAtIndex:([currentRemote currentEQPresetIndex] - 1)] setState:NSOnState];
- } else if ([nextObject isEqualToString:@"songRating"] && ( [currentRemote currentSongRating] != -1 )) {
+ NS_DURING
+ [[_eqMenu itemAtIndex:([[[MainController sharedController] currentRemote] currentEQPresetIndex] - 1)] setState:NSOnState];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
+ } else if ([nextObject isEqualToString:@"songRating"] && currentSongRating) {
ITDebugLog(@"Add \"Song Rating\" submenu.");
tempItem = [menu addItemWithTitle:NSLocalizedString(@"songRating", @"Song Rating")
action:nil
[tempItem setState:NSOffState];
}
- [[_ratingMenu itemAtIndex:([currentRemote currentSongRating] * 5)] setState:NSOnState];
+ NS_DURING
+ [[_ratingMenu itemAtIndex:([[[MainController sharedController] currentRemote] currentSongRating] * 5)] setState:NSOnState];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
} else if ([nextObject isEqualToString:@"upcomingSongs"]) {
ITDebugLog(@"Add \"Upcoming Songs\" submenu.");
tempItem = [menu addItemWithTitle:NSLocalizedString(@"upcomingSongs", @"Upcoming Songs")
NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
NSMenuItem *tempItem;
ITDebugLog(@"Creating menu for when player isn't running.");
- ITDebugLog(@"Add \"Open %@\" menu item.", [[[MainController sharedController] currentRemote] playerSimpleName]);
- tempItem = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"open", @"Open"), [[[MainController sharedController] currentRemote] playerSimpleName]] action:@selector(performMainMenuAction:) keyEquivalent:@""];
+ NS_DURING
+ ITDebugLog(@"Add \"Open %@\" menu item.", [[[MainController sharedController] currentRemote] playerSimpleName]);
+ tempItem = [menu addItemWithTitle:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"open", @"Open"), [[[MainController sharedController] currentRemote] playerSimpleName]] action:@selector(performMainMenuAction:) keyEquivalent:@""];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
[tempItem setTag:MTMenuShowPlayerItem];
[tempItem setTarget:self];
ITDebugLog(@"Add a separator menu item.");
{
ITDebugLog(@"Rebuilding all of the submenus.");
- currentRemote = [[MainController sharedController] currentRemote];
- _currentPlaylist = [currentRemote currentPlaylistIndex];
- _currentTrack = [currentRemote currentSongIndex];
- _playingRadio = ([currentRemote currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
+ NS_DURING
+ _currentPlaylist = [[[MainController sharedController] currentRemote] currentPlaylistIndex];
+ _currentTrack = [[[MainController sharedController] currentRemote] currentSongIndex];
+ _playingRadio = ([[[MainController sharedController] currentRemote] currentPlaylistClass] == ITMTRemotePlayerRadioPlaylist);
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
[_ratingMenu release];
[_upcomingSongsMenu release];
- (NSMenu *)upcomingSongsMenu
{
NSMenu *upcomingSongsMenu = [[NSMenu alloc] initWithTitle:@""];
- int numSongs = [currentRemote numberOfSongsInPlaylistAtIndex:_currentPlaylist];
- int numSongsInAdvance = [[NSUserDefaults standardUserDefaults] integerForKey:@"SongsInAdvance"];
+ int numSongs, numSongsInAdvance = [[NSUserDefaults standardUserDefaults] integerForKey:@"SongsInAdvance"];
+
+ NS_DURING
+ numSongs = [[[MainController sharedController] currentRemote] numberOfSongsInPlaylistAtIndex:_currentPlaylist];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
ITDebugLog(@"Building \"Upcoming Songs\" menu.");
for (i = _currentTrack + 1; i <= _currentTrack + numSongsInAdvance; i++) {
if (i <= numSongs) {
- NSString *curSong = [currentRemote songTitleAtIndex:i];
+ NSString *curSong;
+ NS_DURING
+ curSong = [[[MainController sharedController] currentRemote] songTitleAtIndex:i];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
NSMenuItem *songItem;
ITDebugLog(@"Adding song: %@", curSong);
songItem = [upcomingSongsMenu addItemWithTitle:curSong action:@selector(performUpcomingSongsMenuAction:) keyEquivalent:@""];
- (NSMenu *)playlistsMenu
{
NSMenu *playlistsMenu = [[NSMenu alloc] initWithTitle:@""];
- NSArray *playlists = [currentRemote playlists];
+ NSArray *playlists;
NSMenuItem *tempItem;
int i;
+ NS_DURING
+ playlists = [[[MainController sharedController] currentRemote] playlists];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
+
ITDebugLog(@"Building \"Playlists\" menu.");
for (i = 0; i < [playlists count]; i++) {
- (NSMenu *)eqMenu
{
NSMenu *eqMenu = [[NSMenu alloc] initWithTitle:@""];
- NSArray *eqPresets = [currentRemote eqPresets];
+ NSArray *eqPresets;
NSMenuItem *tempItem;
int i;
+ NS_DURING
+ eqPresets = [[[MainController sharedController] currentRemote] eqPresets];
+ NS_HANDLER
+ [[MainController sharedController] networkError:localException];
+ NS_ENDHANDLER
+
ITDebugLog(@"Building \"EQ Presets\" menu.");
for (i = 0; i < [eqPresets count]; i++) {
--- /dev/null
+/*
+ * MenuTunes
+ * NetworkController
+ * Rendezvous network controller
+ *
+ * Original Author : Kent Sutherland <ksuther@ithinksw.com>
+ * Responsibility : Kent Sutherland <ksuther@ithinksw.com>
+ *
+ * Copyright (c) 2003 iThink Software.
+ * All Rights Reserved
+ *
+ */
+
+#import <Foundation/Foundation.h>
+
+#define SERVER_PORT 5712
+
+@class ITMTRemote;
+
+@interface NetworkController : NSObject
+{
+ NSNetService *service;
+ NSNetServiceBrowser *browser;
+ NSMutableArray *remoteServices;
+
+ NSConnection *serverConnection, *clientConnection;
+ NSSocketPort *serverPort, *clientPort;
+ BOOL serverOn, clientConnected, connectedToServer;
+ ITMTRemote *clientProxy;
+}
++ (NetworkController *)sharedController;
+
+- (void)startRemoteServerSearch;
+- (void)stopRemoteServerSearch;
+
+- (void)setServerStatus:(BOOL)status;
+- (BOOL)connectToHost:(NSString *)host;
+- (BOOL)disconnect;
+- (BOOL)isServerOn;
+- (BOOL)isClientConnected;
+- (BOOL)isConnectedToServer;
+
+- (ITMTRemote *)sharedRemote;
+- (NSArray *)remoteServices;
+@end
--- /dev/null
+/*
+ * MenuTunes
+ * NetworkController
+ * Rendezvous network controller
+ *
+ * Original Author : Kent Sutherland <ksuther@ithinksw.com>
+ * Responsibility : Kent Sutherland <ksuther@ithinksw.com>
+ *
+ * Copyright (c) 2003 iThink Software.
+ * All Rights Reserved
+ *
+ */
+
+#import "NetworkController.h"
+#import "MainController.h"
+#import "netinet/in.h"
+#import "arpa/inet.h"
+#import <ITFoundation/ITDebug.h>
+#import <ITFoundation/ITFoundation.h>
+#import <ITMTRemote/ITMTRemote.h>
+
+static NetworkController *sharedController;
+
+@implementation NetworkController
+
++ (NetworkController *)sharedController
+{
+ return sharedController;
+}
+
+- (id)init
+{
+ if ( (self = [super init]) ) {
+ sharedController = self;
+ browser = [[NSNetServiceBrowser alloc] init];
+ [browser setDelegate:self];
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [self disconnect];
+ if (serverOn) {
+ [serverConnection invalidate];
+ [serverConnection release];
+ }
+ [clientProxy release];
+ [remoteServices release];
+ [browser release];
+ [service stop];
+ [service release];
+ [super dealloc];
+}
+
+- (void)startRemoteServerSearch
+{
+ [browser searchForServicesOfType:@"_mttp._tcp." inDomain:@""];
+ [remoteServices release];
+ remoteServices = [[NSMutableArray alloc] init];
+}
+
+- (void)stopRemoteServerSearch
+{
+ [browser stop];
+}
+
+- (void)setServerStatus:(BOOL)status
+{
+ if (!serverOn && status) {
+ NSString *name = [[NSUserDefaults standardUserDefaults] stringForKey:@"sharedPlayerName"];
+ //Turn on
+ NS_DURING
+ serverPort = [[NSSocketPort alloc] initWithTCPPort:SERVER_PORT];
+ serverConnection = [[NSConnection alloc] initWithReceivePort:serverPort
+ sendPort:serverPort];
+ [serverConnection setRootObject:[[MainController sharedController] currentRemote]];
+ [serverConnection registerName:@"ITMTPlayerHost"];
+ [serverConnection setDelegate:self];
+ NS_HANDLER
+ ITDebugLog(@"Error starting server!");
+ NS_ENDHANDLER
+ ITDebugLog(@"Started server.");
+ if (!name) {
+ name = @"MenuTunes Shared Player";
+ }
+ service = [[NSNetService alloc] initWithDomain:@""
+ type:@"_mttp._tcp."
+ name:name
+ port:SERVER_PORT];
+ [service publish];
+ serverOn = YES;
+ } else if (serverOn && !status && [serverConnection isValid]) {
+ //Turn off
+ [service stop];
+ [serverConnection registerName:nil];
+ [serverPort invalidate];
+ [serverConnection invalidate];
+ [serverConnection release];
+ ITDebugLog(@"Stopped server.");
+ serverOn = NO;
+ }
+}
+
+- (BOOL)connectToHost:(NSString *)host
+{
+ ITDebugLog(@"Connecting to host: %@", host);
+ NS_DURING
+ clientPort = [[NSSocketPort alloc] initRemoteWithTCPPort:SERVER_PORT
+ host:host];
+ clientConnection = [[NSConnection connectionWithReceivePort:nil sendPort:clientPort] retain];
+ clientProxy = [[clientConnection rootProxy] retain];
+ NS_HANDLER
+ ITDebugLog(@"Connection to host failed: %@", host);
+ return NO;
+ NS_ENDHANDLER
+ [clientConnection setReplyTimeout:5];
+ ITDebugLog(@"Connected to host: %@", host);
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(disconnect) name:NSConnectionDidDieNotification object:clientConnection];
+ connectedToServer = YES;
+ return YES;
+}
+
+- (BOOL)disconnect
+{
+ ITDebugLog(@"Disconnecting from host.");
+ connectedToServer = NO;
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [clientProxy release];
+ [clientConnection invalidate];
+ [clientConnection release];
+ return YES;
+}
+
+- (BOOL)isServerOn
+{
+ return serverOn;
+}
+
+- (BOOL)isClientConnected
+{
+ return clientConnected;
+}
+
+- (BOOL)isConnectedToServer
+{
+ return connectedToServer;
+}
+
+- (ITMTRemote *)sharedRemote
+{
+ return (ITMTRemote *)clientProxy;
+}
+
+- (NSArray *)remoteServices
+{
+ return remoteServices;
+}
+
+- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing
+{
+ [aNetService setDelegate:self];
+ [aNetService resolve];
+ ITDebugLog(@"Found service named %@.", [aNetService name]);
+ if (!moreComing) {
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTFoundNetService" object:nil];
+ }
+}
+
+- (void)netServiceDidResolveAddress:(NSNetService *)sender
+{
+ [remoteServices addObject:[NSDictionary dictionaryWithObjectsAndKeys:[sender name], @"name",
+ [NSString stringWithCString:inet_ntoa((*(struct sockaddr_in*)[[[sender addresses] objectAtIndex:0] bytes]).sin_addr)], @"ip",
+ nil, nil]];
+ ITDebugLog(@"Resolved service named %@.", [sender name]);
+ NSLog(@"found!");
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTFoundNetService" object:nil];
+}
+
+- (void)netServiceWillResolve:(NSNetService *)sender
+{
+ ITDebugLog(@"Resolving service named %@.", [sender name]);
+}
+
+- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict
+{
+ ITDebugLog(@"Error resolving service %@.", errorDict);
+}
+
+@end
IBOutlet NSPopUpButton *appearanceEffectPopup;
IBOutlet NSSlider *appearanceSpeedSlider;
IBOutlet NSButton *artistCheckbox;
+ IBOutlet NSTextField *hostTextField;
IBOutlet NSTableView *hotKeysTableView;
IBOutlet NSButton *launchAtLoginCheckbox;
IBOutlet NSButton *launchPlayerAtLaunchCheckbox;
+ IBOutlet NSView *manualView;
IBOutlet CustomMenuTableView *menuTableView;
IBOutlet NSButton *nameCheckbox;
IBOutlet NSButton *ratingCheckbox;
+ IBOutlet NSBox *selectPlayerBox;
+ IBOutlet NSPanel *selectPlayerSheet;
+ IBOutlet NSButton *selectSharedPlayerButton;
+ IBOutlet NSButton *shareMenuTunesCheckbox;
+ IBOutlet NSButton *sharePasswordCheckbox;
+ IBOutlet NSTextField *sharePasswordTextField;
+ IBOutlet NSTableView *sharingTableView;
IBOutlet NSButton *showOnChangeCheckbox;
IBOutlet NSTextField *songsInAdvance;
IBOutlet NSButton *trackNumberCheckbox;
IBOutlet NSButton *trackTimeCheckbox;
+ IBOutlet NSButton *useSharedMenuTunesCheckbox;
IBOutlet NSSlider *vanishDelaySlider;
IBOutlet NSPopUpButton *vanishEffectPopup;
IBOutlet NSSlider *vanishSpeedSlider;
IBOutlet NSWindow *window;
+ IBOutlet NSView *zeroConfView;
MainController *controller;
NSUserDefaults *df;
- (void)setController:(id)object;
- (IBAction)changeGeneralSetting:(id)sender;
+- (IBAction)changeSharingSetting:(id)sender;
- (IBAction)changeStatusWindowSetting:(id)sender;
- (IBAction)clearHotKey:(id)sender;
- (IBAction)editHotKey:(id)sender;
#import "PreferencesController.h"
#import "MainController.h"
+#import "NetworkController.h"
#import "StatusWindow.h"
#import "StatusWindowController.h"
#import "CustomMenuTableView.h"
[hotKeysTableView setDoubleAction:@selector(hotKeysTableViewDoubleClicked:)];
//Change the launch player checkbox to the proper name
- [launchPlayerAtLaunchCheckbox setTitle:[NSString stringWithFormat:@"Launch %@ when MenuTunes launches", [[controller currentRemote] playerSimpleName]]]; //This isn't localized...
+ NS_DURING
+ [launchPlayerAtLaunchCheckbox setTitle:[NSString stringWithFormat:@"Launch %@ when MenuTunes launches", [[controller currentRemote] playerSimpleName]]]; //This isn't localized...
+ NS_HANDLER
+ [controller networkError:localException];
+ NS_ENDHANDLER
}
[window center];
[df synchronize];
}
+- (IBAction)changeSharingSetting:(id)sender
+{
+ ITDebugLog(@"Changing sharing setting of tag %i.", [sender tag]);
+ if ( [sender tag] == 5010 ) {
+ BOOL state = SENDER_STATE;
+ [df setBool:state forKey:@"enableSharing"];
+ //Disable/enable the use of shared player options
+ [useSharedMenuTunesCheckbox setEnabled:!state];
+ [sharePasswordCheckbox setEnabled:!state];
+ [sharePasswordTextField setEnabled:!state];
+ [controller setServerStatus:state]; //Set server status
+ } else if ( [sender tag] == 5020 ) {
+ [df setBool:SENDER_STATE forKey:@"enableSharingPassword"];
+ } else if ( [sender tag] == 5030 ) {
+ [df setObject:[sender stringValue] forKey:@"sharingPassword"];
+ } else if ( [sender tag] == 5040 ) {
+ BOOL state = SENDER_STATE;
+ [df setBool:state forKey:@"useSharedPlayer"];
+ //Disable/enable the use of sharing options
+ [shareMenuTunesCheckbox setEnabled:!state];
+ [sharePasswordCheckbox setEnabled:!state];
+ [sharePasswordTextField setEnabled:!state];
+
+ if (state) {
+ [controller connectToServer];
+ } else {
+ [controller disconnectFromServer];
+ }
+ } else if ( [sender tag] == 5050 ) {
+ if ([sender clickedRow] > -1) {
+ //Set sharedPlayerHost
+ [df setObject:[[[[NetworkController sharedController] remoteServices] objectAtIndex:[sender clickedRow]] objectForKey:@"ip"] forKey:@"sharedPlayerHost"];
+ }
+ } else if ( [sender tag] == 5060 ) {
+ //Show selection sheet
+ [NSApp beginSheet:selectPlayerSheet modalForWindow:window modalDelegate:self didEndSelector:NULL contextInfo:nil];
+ } else if ( [sender tag] == 5100 ) {
+ //Change view
+ if ( ([sender indexOfItem:[sender selectedItem]] == 0) && ([selectPlayerBox contentView] != zeroConfView) ) {
+ NSRect frame = [selectPlayerSheet frame];
+ frame.origin.y -= 58;
+ frame.size.height = 273;
+ [selectPlayerSheet setFrame:frame display:YES animate:YES];
+ [selectPlayerBox setContentView:zeroConfView];
+ } else if ([selectPlayerBox contentView] != manualView) {
+ NSRect frame = [selectPlayerSheet frame];
+ frame.origin.y += 58;
+ frame.size.height = 215;
+ [selectPlayerSheet setFrame:frame display:YES animate:YES];
+ [selectPlayerBox setContentView:manualView];
+ }
+ } else if ( [sender tag] == 5110 ) {
+ //Cancel
+ [NSApp endSheet:selectPlayerSheet];
+ [selectPlayerSheet orderOut:nil];
+ if ([selectPlayerBox contentView] == manualView) {
+ [hostTextField setStringValue:[df stringForKey:@"sharedPlayerHost"]];
+ } else {
+ }
+ } else if ( [sender tag] == 5120 ) {
+ //OK, try to connect
+ [NSApp endSheet:selectPlayerSheet];
+ [selectPlayerSheet orderOut:nil];
+
+ if (![controller connectToServer]) {
+ NSRunAlertPanel(@"Connection error.", @"The MenuTunes server you attempted to connect to was not responding. MenuTunes will revert back to the local player.", @"OK", nil, nil);
+ } else {
+ [useSharedMenuTunesCheckbox setState:NSOnState];
+ }
+
+ if ([selectPlayerBox contentView] == manualView) {
+ [df setObject:[hostTextField stringValue] forKey:@"sharedPlayerHost"];
+ } else {
+ }
+ }
+ [df synchronize];
+}
+
- (IBAction)changeStatusWindowSetting:(id)sender
{
StatusWindow *sw = [StatusWindow sharedWindow];
[vanishSpeedSlider setFloatValue:-([df floatForKey:@"statusWindowVanishSpeed"])];
[vanishDelaySlider setFloatValue:[df floatForKey:@"statusWindowVanishDelay"]];
[showOnChangeCheckbox setState:([df boolForKey:@"showSongInfoOnChange"] ? NSOnState : NSOffState)];
+
+ // Setup the sharing controls
+ if ([df boolForKey:@"enableSharing"]) {
+ [shareMenuTunesCheckbox setState:NSOnState];
+ [useSharedMenuTunesCheckbox setEnabled:NO];
+ [selectSharedPlayerButton setEnabled:NO];
+ [hostTextField setEnabled:NO];
+ } else if ([df boolForKey:@"useSharedPlayer"]) {
+ [useSharedMenuTunesCheckbox setState:NSOnState];
+ [shareMenuTunesCheckbox setEnabled:NO];
+ [sharePasswordCheckbox setEnabled:NO];
+ [sharePasswordTextField setEnabled:NO];
+ }
+
+ [[NSNotificationCenter defaultCenter] addObserver:sharingTableView selector:@selector(reloadData) name:@"ITMTFoundNetService" object:nil];
+
+ [selectPlayerBox setContentView:zeroConfView];
+ [sharePasswordCheckbox setState:([df boolForKey:@"enableSharingPassword"] ? NSOnState : NSOffState)];
+ //[sharePasswordTextField setStringValue:@""]; //DO THIS LATER
+ if ([df stringForKey:@"sharedPlayerHost"]) {
+ [hostTextField setStringValue:[df stringForKey:@"sharedPlayerHost"]];
+ }
}
- (IBAction)changeMenus:(id)sender
return [myItems count];
} else if (aTableView == allTableView) {
return [availableItems count];
- } else {
+ } else if (aTableView == hotKeysTableView) {
return [hotKeysArray count];
+ } else {
+ return [[[NetworkController sharedController] remoteServices] count];
}
}
NSString *object = [myItems objectAtIndex:rowIndex];
if ([[aTableColumn identifier] isEqualToString:@"name"]) {
if ([object isEqualToString:@"showPlayer"]) {
- return [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"show", @"Show"), [[controller currentRemote] playerSimpleName]];
+ NSString *string;
+ NS_DURING
+ string = [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"show", @"Show"), [[controller currentRemote] playerSimpleName]];
+ NS_HANDLER
+ [controller networkError:localException];
+ NS_ENDHANDLER
+ return string;
}
return NSLocalizedString(object, @"ERROR");
} else {
NSString *object = [availableItems objectAtIndex:rowIndex];
if ([[aTableColumn identifier] isEqualToString:@"name"]) {
if ([object isEqualToString:@"showPlayer"]) {
- return [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"show", @"Show"), [[controller currentRemote] playerSimpleName]];
+ NSString *string;
+ NS_DURING
+ string = [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"show", @"Show"), [[controller currentRemote] playerSimpleName]];
+ NS_HANDLER
+ [controller networkError:localException];
+ NS_ENDHANDLER
+ return string;
}
return NSLocalizedString(object, @"ERROR");
} else {
return nil;
}
}
- } else {
+ } else if (aTableView == hotKeysTableView) {
if ([[aTableColumn identifier] isEqualToString:@"name"]) {
return [hotKeyNamesArray objectAtIndex:rowIndex];
} else {
return [[hotKeysDictionary objectForKey:[hotKeysArray objectAtIndex:rowIndex]] description];
}
+ } else {
+ if ([[aTableColumn identifier] isEqualToString:@"name"]) {
+ return [[[[NetworkController sharedController] remoteServices] objectAtIndex:rowIndex] objectForKey:@"name"];
+ } else {
+ return @"X";
+ }
}
}