blob: eac903b1487c078ccea3a84f257474fa6010985f [file] [log] [blame]
Alexander Afanasyev14b09482013-10-11 18:24:45 +02001/* -*- Mode: obj; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -07002/*
3 * @copyright See LICENCE for copyright and license information.
4 *
5 * @author Alexander Afanasyev <alexander.afanasyev@ucla.edu>
6 * @author Ilya Moiseenko <iliamo@ucla.edu>
7 */
8
Alexander Afanasyev2beff7f2013-09-27 17:50:36 -07009#include "config.h"
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070010#import "menu-delegate.h"
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070011#import "ndnd-status-operation.h"
Ilya Moiseenko0c9ab7c2013-10-29 15:08:23 -070012#import "tight-menu-item-view.h"
Ilya Moiseenko2dffcf52013-09-27 15:08:04 -070013
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070014@implementation MenuDelegate
15
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070016-(id)init
17{
18 if (![super init]) {
19 return nil;
20 }
21
Alexander Afanasyevb9024d12013-10-14 18:10:18 +030022 m_autoconfInProgress = false;
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070023 m_operationQueue = [[NSOperationQueue alloc] init];
24 return self;
25}
26
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070027- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
28{
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -070029 // Register the preference defaults early.
30 NSDictionary *appDefaults =
31 [NSDictionary dictionaryWithObjectsAndKeys:
32 [NSNumber numberWithBool:YES], @"allowSoftwareUpdates",
33 [NSNumber numberWithBool:YES], @"enableHubDiscovery",
34 [NSNumber numberWithBool:NO], @"shutdownNdndOnExit",
35 nil
36 ];
37 [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
38
39 // Other initialization...
40
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070041 m_daemonStarted = false;
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070042
43 NSBundle *bundle = [NSBundle bundleForClass:[self class]];
44 m_connectedIcon = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"FlatConnected" ofType:@"png"]];
45 m_disconnectedIcon = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"FlatDisconnected" ofType:@"png"]];
46 m_statusXslt = [NSData dataWithContentsOfFile:[bundle pathForResource:@"status" ofType:@"xslt"]];
Ilya Moiseenkob4aca052013-10-06 15:10:19 -070047 m_statusToFibXslt = [NSData dataWithContentsOfFile:[bundle pathForResource:@"status-to-fib" ofType:@"xslt"]];
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -070048
Alexander Afanasyevb9024d12013-10-14 18:10:18 +030049 [NSTimer scheduledTimerWithTimeInterval: 1.0
50 target: self
51 selector:@selector(onTick:)
52 userInfo: nil
53 repeats:YES];
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +020054 [self updateStatus];
Alexander Afanasyev17922872013-10-15 11:45:58 +030055
56 m_systemEvents = [[SystemEvents alloc] init];
57}
58
59- (void)applicationWillTerminate:(NSNotification *)aNotification
60{
61 [m_systemEvents disable];
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070062}
63
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070064-(void)awakeFromNib
65{
66 statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070067 [statusItem setMenu:statusMenu];
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070068 [statusItem setToolTip:@"NDN Control Center"];
69 [statusItem setEnabled:YES];
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070070 [statusItem setHighlightMode:YES];
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070071 //[statusItem setTarget:self];
72
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070073 [statusItem setTitle:@""];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070074 [statusItem setImage:m_disconnectedIcon];
Ilya Moiseenko01264322013-09-26 15:34:21 -070075
Ilya Moiseenko0c9ab7c2013-10-29 15:08:23 -070076 float menuItemHeight = 20;
77
78 NSRect viewRect = NSMakeRect(0, 0, /* width autoresizes */ 1, menuItemHeight);
79 connectionStatusView = [[TightMenuItemView alloc] initWithFrame:viewRect];
80 connectionStatusView.autoresizingMask = NSViewWidthSizable;
81
82 [connectionStatus setView:connectionStatusView];
Ilya Moiseenko01264322013-09-26 15:34:21 -070083 [connectionStatus setTarget:self];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070084
Ilya Moiseenko01264322013-09-26 15:34:21 -070085 [daemonStatus setView: daemonStatusView];
86 [daemonStatus setTarget:self];
Ilya Moiseenkoa10ef8d2013-09-25 17:23:05 -070087}
88
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070089-(IBAction)openDaemonStatus:(id)sender
90{
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070091}
92
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -070093-(IBAction)showExitConfirmationWindow:(id)sender
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070094{
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -070095 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"shutdownNdndOnExit"]) {
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070096 [m_operationQueue cancelAllOperations];
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +020097
98 [m_operationQueue addOperationWithBlock:^{
99 NSTask *task = [[NSTask alloc] init];
100 [task setLaunchPath: @NDND_STOP_COMMAND];
101 [task launch];
102 [task waitUntilExit];
103 }];
104
105 [m_operationQueue waitUntilAllOperationsAreFinished];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700106 [NSApp terminate:self];
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700107 }
108 else {
109 NSAlert *alert = [[NSAlert alloc] init];
110 [alert addButtonWithTitle:@"Yes"];
111 [alert addButtonWithTitle:@"No"];
112 [alert addButtonWithTitle:@"Cancel"];
113 [alert setMessageText:@"Shutdown NDN daemon as well?"];
114 [alert setInformativeText:@"All NDN operations will be become unavailable."];
115 [alert setAlertStyle:NSCriticalAlertStyle];
116 // [alert setShowsSuppressionButton: YES];
117
118 NSInteger res = [alert runModal];
119 if (res == NSAlertFirstButtonReturn) {
120 // "YES" stop ndnd
121 [m_operationQueue cancelAllOperations];
122
123 [m_operationQueue addOperationWithBlock:^{
124 NSTask *task = [[NSTask alloc] init];
125 [task setLaunchPath: @NDND_STOP_COMMAND];
126 [task launch];
127 [task waitUntilExit];
128 }];
129
130 [m_operationQueue waitUntilAllOperationsAreFinished];
131 [NSApp terminate:self];
132 } else if (res == NSAlertSecondButtonReturn) {
133 // "NO" terminate app but keep ndnd running
134 [m_operationQueue cancelAllOperations];
135 [NSApp terminate:self];
136 }
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700137 }
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -0700138}
139
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700140-(void)onTick:(NSTimer *)timer
141{
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +0200142 [self updateStatus];
143}
144
145-(void)updateStatus
146{
147 NSOperation *operation = [[NdndStatusOperation alloc] initWithDelegate:self];
148 [m_operationQueue addOperation:operation];
149}
150
151-(void)updateStatusWithDependency:(NSOperation*)dependency
152{
153 NSOperation *operation = [[NdndStatusOperation alloc] initWithDelegate:self];
154 [operation addDependency:dependency];
155
156 [m_operationQueue addOperation:dependency];
157 [m_operationQueue addOperation:operation];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700158}
159
160- (void)statusUpdated:(NSXMLDocument*)document
161{
162 if (!m_daemonStarted) {
163 m_daemonStarted = true;
Ilya Moiseenko0c9ab7c2013-10-29 15:08:23 -0700164 [connectionStatusView setStatus:@"Active"];
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700165
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700166 [statusItem setImage:m_connectedIcon];
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700167 }
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700168
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700169 NSXMLDocument *statusXml = [document objectByApplyingXSLT:m_statusXslt
170 arguments:nil
171 error:nil];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700172
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700173 NSXMLDocument *statusFibXml = [document objectByApplyingXSLT:m_statusToFibXslt
174 arguments:nil
175 error:nil];
176
177 m_statusString = [[NSAttributedString alloc]initWithHTML:[statusXml XMLData] documentAttributes:NULL];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700178 [daemonStatusHtml setAttributedStringValue:m_statusString];
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700179
180 [preferencesDelegate updateFibStatus:statusFibXml];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300181
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700182 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"enableHubDiscovery"]) {
183 NSArray *autoconf = [[statusFibXml rootElement] nodesForXPath:@"//fib/prefix[text()='ndn:/autoconf-route']" error:nil];
184 if ([autoconf count] == 0)
185 {
186 [self restartDaemon:nil];
187 }
188 }
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700189}
190
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700191- (void)statusUnavailable:(id)none
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -0700192{
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700193 // try start ndnd if it is not started yet
194 if (m_daemonStarted) {
195 m_daemonStarted = false;
196
Ilya Moiseenko0c9ab7c2013-10-29 15:08:23 -0700197 [connectionStatusView setStatus:@"Starting..."];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700198
199 [statusItem setImage:m_disconnectedIcon];
200 }
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700201
202 [daemonStatusHtml setStringValue:@""];
203 [preferencesDelegate updateFibStatus:nil];
204
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300205 m_autoconfInProgress = true;
206
207 NSOperation *startOp = [NSBlockOperation blockOperationWithBlock:^{
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700208 NSTask *task = [[NSTask alloc] init];
209 [task setLaunchPath: @NDND_START_COMMAND];
210 [task launch];
211 }];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300212
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700213 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"enableHubDiscovery"]) {
214 NSOperation *autoconfOp = [NSBlockOperation blockOperationWithBlock:^{
215 NSTask *task = [[NSTask alloc] init];
216 [task setLaunchPath: @NDND_AUTOCONFIG_COMMAND];
217 [task launch];
218 [task waitUntilExit];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300219
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700220 m_autoconfInProgress = false;
221 }];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300222
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700223 [autoconfOp addDependency:startOp];
224 [m_operationQueue addOperation:autoconfOp];
225 }
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300226
227 [m_operationQueue addOperation:startOp];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300228}
229
230-(void)restartDaemon:(id)none
231{
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700232 if (![[NSUserDefaults standardUserDefaults] boolForKey:@"enableHubDiscovery"])
233 return;
234
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300235 if (m_autoconfInProgress)
236 return;
237
Alexander Afanasyev17922872013-10-15 11:45:58 +0300238 NSLog (@"No automatically detected route configured, trying to get one");
239
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300240 m_autoconfInProgress = true;
241 [m_operationQueue addOperationWithBlock:^{
242 NSTask *task = [[NSTask alloc] init];
243 [task setLaunchPath: @NDND_AUTOCONFIG_COMMAND];
244 [task launch];
245 [task waitUntilExit];
246
247 m_autoconfInProgress = false;
248 }];
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -0700249}
250
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -0700251@end