forked from I2P_Developers/i2p.i2p
Adding codebase for the Objective-C++ part of the Mac OS X launcher/wrapper.
This commit is contained in:
114
launchers/macosx/obj-cpp/AppDelegate.h
Normal file
114
launchers/macosx/obj-cpp/AppDelegate.h
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#ifndef __APPDELEGATE_H__
|
||||||
|
#define __APPDELEGATE_H__
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
#include "StatusItemButton.h"
|
||||||
|
#include "JavaHelper.h"
|
||||||
|
|
||||||
|
extern JvmListSharedPtr gRawJvmList;
|
||||||
|
|
||||||
|
@interface MenuBarCtrl : NSObject <StatusItemButtonDelegate, NSMenuDelegate>
|
||||||
|
@property BOOL enableLogging;
|
||||||
|
@property BOOL enableVerboseLogging;
|
||||||
|
@property (strong) NSMenu *menu;
|
||||||
|
@property (strong) StatusItemButton* statusBarButton;
|
||||||
|
@property (strong) NSUserDefaults *userPreferences;
|
||||||
|
@property (strong, nonatomic) NSImage * image;
|
||||||
|
@property (strong, nonatomic) NSStatusItem *statusItem;
|
||||||
|
// Event handlers
|
||||||
|
- (void) statusItemButtonLeftClick: (StatusItemButton *) button;
|
||||||
|
- (void) statusItemButtonRightClick: (StatusItemButton *) button;
|
||||||
|
- (void) statusBarImageBtnClicked;
|
||||||
|
- (void) btnPressedAction:(id)sender;
|
||||||
|
- (void) menuWillOpen:(NSMenu *)menu;
|
||||||
|
|
||||||
|
- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem;
|
||||||
|
- (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem;
|
||||||
|
- (void) stopJavaRouterBtnHandler: (NSMenuItem *) menuItem;
|
||||||
|
- (void) quitWrapperBtnHandler: (NSMenuItem *) menuItem;
|
||||||
|
// Methods
|
||||||
|
- (MenuBarCtrl *) init;
|
||||||
|
- (void) dealloc;
|
||||||
|
- (NSMenu *) createStatusBarMenu;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@protocol MenuBarCtrlDelegate
|
||||||
|
- (void) menuBarCtrlStatusChanged: (BOOL) active;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface AppDelegate : NSObject <NSUserNotificationCenterDelegate, NSApplicationDelegate> {
|
||||||
|
@public
|
||||||
|
//NSImageView *imageCell;
|
||||||
|
}
|
||||||
|
@property (strong) MenuBarCtrl *menuBarCtrl;
|
||||||
|
@property (strong) NSUserDefaults *userPreferences;
|
||||||
|
@property BOOL enableLogging;
|
||||||
|
@property BOOL enableVerboseLogging;
|
||||||
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
|
||||||
|
- (void)applicationWillTerminate:(NSNotification *)aNotification;
|
||||||
|
- (void)setApplicationDefaultPreferences;
|
||||||
|
- (void)userChooseJavaHome;
|
||||||
|
- (AppDelegate *)initWithArgc:(int)argc argv:(const char **)argv;
|
||||||
|
- (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList;
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
@implementation CNSStatusBarCtrl
|
||||||
|
-(id)initWithSysTray:(I2PCtrlSysIcon *)sys
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
|
||||||
|
menu = 0;
|
||||||
|
systray = sys;
|
||||||
|
imageCell = [[NSImageView alloc] initWithParent:self];
|
||||||
|
[item setView: imageCell];
|
||||||
|
[item setHidden: NO];
|
||||||
|
CFShow(CFSTR("CNSStatusBarCtrl::initWithSysTray executed"));
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
-(NSStatusItem*)item {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
-(void)dealloc {
|
||||||
|
[[NSStatusBar systemStatusBar] removeStatusItem:item];
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:imageCell];
|
||||||
|
[imageCell release];
|
||||||
|
[item release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
class CSystemTrayIcon
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSystemTrayIcon(I2PCtrlSysIcon *sys)
|
||||||
|
{
|
||||||
|
item = [[CNSStatusBarCtrl alloc] initWithSysTray:sys];
|
||||||
|
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:item];
|
||||||
|
const int menuHeight = [[NSStatusBar systemStatusBar] thickness];
|
||||||
|
printf("menuHeight: %d\n", menuHeight);
|
||||||
|
[[[item item] view] setHidden: NO];
|
||||||
|
}
|
||||||
|
~CSystemTrayIcon()
|
||||||
|
{
|
||||||
|
[[[item item] view] setHidden: YES];
|
||||||
|
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil];
|
||||||
|
[item release];
|
||||||
|
}
|
||||||
|
CNSStatusBarCtrl *item;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
47
launchers/macosx/obj-cpp/Info.plist
Normal file
47
launchers/macosx/obj-cpp/Info.plist
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>I2PLauncher</string>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>Public Domain</string>
|
||||||
|
<key>CFBundleGetInfoString</key>
|
||||||
|
<string>0.9.35-experimental</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>i2p</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>net.i2p.launcher</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>I2P</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>0.0.1</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>I2P</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>0.0.1</string>
|
||||||
|
<key>NSAppleScriptEnabled</key>
|
||||||
|
<true/>
|
||||||
|
<key>CGDisableCoalescedUpdates</key>
|
||||||
|
<true/>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>10.5</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>I2P</string>
|
||||||
|
<key>LSMinimumSystemVersionByArchitecture</key>
|
||||||
|
<dict>
|
||||||
|
<key>i386</key>
|
||||||
|
<string>10.5.0</string>
|
||||||
|
<key>x86_64</key>
|
||||||
|
<string>10.6.0</string>
|
||||||
|
</dict>
|
||||||
|
<key>LSUIElement</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
BIN
launchers/macosx/obj-cpp/ItoopieTransparent.png
Normal file
BIN
launchers/macosx/obj-cpp/ItoopieTransparent.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
175
launchers/macosx/obj-cpp/JavaHelper.h
Normal file
175
launchers/macosx/obj-cpp/JavaHelper.h
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
#include <list>
|
||||||
|
#include <experimental/optional>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <Foundation/Foundation.h>
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <CoreFoundation/CFStream.h>
|
||||||
|
#include <CoreFoundation/CFPropertyList.h>
|
||||||
|
#include <CoreFoundation/CFDictionary.h>
|
||||||
|
#include <CoreFoundation/CFArray.h>
|
||||||
|
#include <CoreFoundation/CFString.h>
|
||||||
|
|
||||||
|
#include "strutil.hpp"
|
||||||
|
#include "subprocess.hpp"
|
||||||
|
|
||||||
|
using namespace subprocess;
|
||||||
|
|
||||||
|
|
||||||
|
#define DEF_MIN_JVM_VER "1.7+"
|
||||||
|
|
||||||
|
class JvmVersion
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string JVMName;
|
||||||
|
std::string JVMHomePath;
|
||||||
|
std::string JVMPlatformVersion;
|
||||||
|
|
||||||
|
inline const char * ToCString()
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "JvmVersion(name=" << JVMName.c_str() << ",version=";
|
||||||
|
ss << JVMPlatformVersion.c_str() << ",home=" << JVMHomePath.c_str() << ")";
|
||||||
|
std::string s = ss.str();
|
||||||
|
return s.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool HasContent()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
std::strlen(JVMName.c_str()) > 0 &&
|
||||||
|
std::strlen(JVMHomePath.c_str()) > 0 &&
|
||||||
|
std::strlen(JVMPlatformVersion.c_str()) > 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::shared_ptr<JvmVersion> JvmVersionPtr;
|
||||||
|
typedef std::shared_ptr<std::list<JvmVersionPtr> > JvmListPtr;
|
||||||
|
typedef std::shared_ptr<std::list<std::shared_ptr<JvmVersion> > > JvmListSharedPtr;
|
||||||
|
typedef void(^MenuBarControllerActionBlock)(BOOL active);
|
||||||
|
|
||||||
|
extern JvmListSharedPtr gRawJvmList;
|
||||||
|
|
||||||
|
class JvmHomeContext : public std::enable_shared_from_this<JvmHomeContext>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
inline void setJvm(JvmVersionPtr* current)
|
||||||
|
{
|
||||||
|
mCurrent = *current;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JvmListPtr getJvmList()
|
||||||
|
{
|
||||||
|
return gRawJvmList;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::shared_ptr<JvmHomeContext> getContext()
|
||||||
|
{
|
||||||
|
return shared_from_this();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string getJavaHome()
|
||||||
|
{
|
||||||
|
if (mCurrent)
|
||||||
|
{
|
||||||
|
return mCurrent->JVMHomePath;
|
||||||
|
}
|
||||||
|
return gRawJvmList->back()->JVMHomePath;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
JvmVersionPtr mCurrent;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void processJvmEntry (const void* key, const void* value, void* context) {
|
||||||
|
//CFShow(key);
|
||||||
|
//CFShow(value);
|
||||||
|
|
||||||
|
// The reason for using strprintf is to "force" a copy of the values,
|
||||||
|
// since local variables gets deleted once this function returns.
|
||||||
|
auto currentJvm = reinterpret_cast<JvmVersion*>(context);
|
||||||
|
if (CFEqual((CFStringRef)key,CFSTR("JVMName"))) {
|
||||||
|
auto strVal = extractString((CFStringRef)value);
|
||||||
|
currentJvm->JVMName = strprintf("%s",strVal.c_str());
|
||||||
|
}
|
||||||
|
if (CFEqual((CFStringRef)key,CFSTR("JVMHomePath"))) {
|
||||||
|
auto strVal = extractString((CFStringRef)value);
|
||||||
|
currentJvm->JVMHomePath = strprintf("%s",strVal.c_str());
|
||||||
|
}
|
||||||
|
if (CFEqual((CFStringRef)key,CFSTR("JVMPlatformVersion"))) {
|
||||||
|
auto strVal = extractString((CFStringRef)value);
|
||||||
|
currentJvm->JVMPlatformVersion = strprintf("%s",strVal.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void processJvmPlistEntries (const void* item, void* context) {
|
||||||
|
CFDictionaryRef dict = CFDictionaryCreateCopy(kCFAllocatorDefault, (CFDictionaryRef)item);
|
||||||
|
|
||||||
|
JvmVersionPtr currentJvmPtr = std::shared_ptr<JvmVersion>(new JvmVersion());
|
||||||
|
struct CFunctional
|
||||||
|
{
|
||||||
|
static void applier(const void* key, const void* value, void* context){
|
||||||
|
// The reason for using strprintf is to "force" a copy of the values,
|
||||||
|
// since local variables gets deleted once this function returns.
|
||||||
|
auto currentJvm = static_cast<JvmVersion*>(context);
|
||||||
|
if (CFEqual((CFStringRef)key,CFSTR("JVMName"))) {
|
||||||
|
auto d = extractString((CFStringRef)value);
|
||||||
|
currentJvm->JVMName = trim_copy(d);
|
||||||
|
}
|
||||||
|
if (CFEqual((CFStringRef)key,CFSTR("JVMHomePath"))) {
|
||||||
|
auto d = extractString((CFStringRef)value);
|
||||||
|
currentJvm->JVMHomePath = trim_copy(d);
|
||||||
|
}
|
||||||
|
if (CFEqual((CFStringRef)key,CFSTR("JVMPlatformVersion"))) {
|
||||||
|
auto d = extractString((CFStringRef)value);
|
||||||
|
currentJvm->JVMPlatformVersion = trim_copy(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CFDictionaryApplyFunction(dict, CFunctional::applier, (void*)currentJvmPtr.get());
|
||||||
|
|
||||||
|
if (currentJvmPtr->HasContent())
|
||||||
|
{
|
||||||
|
printf("Found JVM: %s\n\n", currentJvmPtr->ToCString());
|
||||||
|
gRawJvmList->push_back(currentJvmPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void listAllJavaInstallsAvailable()
|
||||||
|
{
|
||||||
|
auto javaHomeRes = check_output({"/usr/libexec/java_home","-v",DEF_MIN_JVM_VER,"-X"});
|
||||||
|
CFDataRef javaHomes = CFDataCreate(NULL, (const UInt8 *)javaHomeRes.buf.data(), strlen(javaHomeRes.buf.data()));
|
||||||
|
|
||||||
|
//CFErrorRef err;
|
||||||
|
CFPropertyListRef propertyList = CFPropertyListCreateWithData(kCFAllocatorDefault, javaHomes, kCFPropertyListImmutable, NULL, NULL);
|
||||||
|
/*if (err)
|
||||||
|
{
|
||||||
|
NSError *error = (__bridge NSError *)err;
|
||||||
|
NSLog(@"Failed to read property list: %@", error);
|
||||||
|
[NSApp presentError: error];
|
||||||
|
return nullptr;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
//auto typeId = CFCopyTypeIDDescription(CFGetTypeID(propertyList));
|
||||||
|
//auto test = CFCopyDescription(propertyList);
|
||||||
|
//std::cout << "test: " << [test UTF8String] << " Type: " << [typeId UTF8String] << " num: " << jCount << std::endl;
|
||||||
|
|
||||||
|
// Count number of entries in the property array list.
|
||||||
|
// This is used to set max CRange for CFArrayApplyFunction.
|
||||||
|
auto jCount = CFArrayGetCount((CFArrayRef)propertyList);
|
||||||
|
|
||||||
|
CFArrayApplyFunction((CFArrayRef)propertyList, CFRangeMake(0, jCount), processJvmPlistEntries, NULL);
|
||||||
|
//CFShow(propertyList);
|
||||||
|
}
|
30
launchers/macosx/obj-cpp/JavaRunner.cpp
Normal file
30
launchers/macosx/obj-cpp/JavaRunner.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include "JavaRunner.h"
|
||||||
|
|
||||||
|
#include <dispatch/dispatch.h>
|
||||||
|
#include <subprocess.hpp>
|
||||||
|
|
||||||
|
using namespace subprocess;
|
||||||
|
|
||||||
|
JavaRunner::JavaRunner(std::string javaBin, const fp_proc_t& execFn, const fp_t& cb)
|
||||||
|
: javaBinaryPath(javaBin), executingFn(execFn), exitCallbackFn(cb)
|
||||||
|
{
|
||||||
|
javaProcess = std::shared_ptr<Popen>(new Popen({javaBin.c_str(), "-version"}, defer_spawn{true}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void JavaRunner::execute()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
auto executingFn = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{
|
||||||
|
this->executingFn(this);
|
||||||
|
});
|
||||||
|
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), executingFn);
|
||||||
|
dispatch_block_wait(executingFn, DISPATCH_TIME_FOREVER);
|
||||||
|
|
||||||
|
// Here, the process is done executing.
|
||||||
|
|
||||||
|
printf("Finished executingFn - Runs callbackFn\n");
|
||||||
|
this->exitCallbackFn();
|
||||||
|
} catch (std::exception* ex) {
|
||||||
|
printf("ERROR: %s\n", ex->what());
|
||||||
|
}
|
||||||
|
}
|
44
launchers/macosx/obj-cpp/JavaRunner.h
Normal file
44
launchers/macosx/obj-cpp/JavaRunner.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <dispatch/dispatch.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <subprocess.hpp>
|
||||||
|
|
||||||
|
using namespace subprocess;
|
||||||
|
|
||||||
|
class JavaRunner;
|
||||||
|
|
||||||
|
struct CRouterState
|
||||||
|
{
|
||||||
|
enum State {
|
||||||
|
C_STOPPED = 0,
|
||||||
|
C_STARTED,
|
||||||
|
C_RUNNING
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::function<void(void)> fp_t;
|
||||||
|
typedef std::function<void(JavaRunner *ptr)> fp_proc_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* class JavaRunner
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
class JavaRunner
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// copy fn
|
||||||
|
JavaRunner(std::string javaBin, const fp_proc_t& executingFn, const fp_t& cb);
|
||||||
|
~JavaRunner() = default;
|
||||||
|
|
||||||
|
void execute();
|
||||||
|
std::shared_ptr<Popen> javaProcess;
|
||||||
|
std::string javaBinaryPath;
|
||||||
|
private:
|
||||||
|
const fp_proc_t& executingFn;
|
||||||
|
const fp_t& exitCallbackFn;
|
||||||
|
};
|
||||||
|
|
12
launchers/macosx/obj-cpp/Makefile
Normal file
12
launchers/macosx/obj-cpp/Makefile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
CXX=clang++
|
||||||
|
|
||||||
|
CXXFLAGS= -std=c++14 -g -Wall -mmacosx-version-min=10.10
|
||||||
|
INCLUDEDIRS=-I./include -I/usr/local/include -I/usr/include
|
||||||
|
SOURCES=main.mm StatusItemButton.mm CRunner.cpp
|
||||||
|
LDFLAGS=-framework CoreFoundation -framework Foundation -framework Cocoa
|
||||||
|
|
||||||
|
i2plauncher:
|
||||||
|
$(CXX) $(CXXFLAGS) $(INCLUDEDIRS) $(LDFLAGS) -o i2plauncher $(SOURCES)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f i2plauncher
|
11
launchers/macosx/obj-cpp/README.md
Normal file
11
launchers/macosx/obj-cpp/README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# The Objective-C++ part of the Mac OS X launcher
|
||||||
|
|
||||||
|
## Why?
|
||||||
|
|
||||||
|
Code signing, OS X integration.
|
||||||
|
|
||||||
|
## Howto build?
|
||||||
|
|
||||||
|
Preferred tool is [ninja](https://ninja-build.org/). A makefile is also available.
|
||||||
|
|
||||||
|
Build with: `ninja`
|
21
launchers/macosx/obj-cpp/StatusItemButton.h
Normal file
21
launchers/macosx/obj-cpp/StatusItemButton.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@class StatusItemButton;
|
||||||
|
|
||||||
|
@protocol StatusItemButtonDelegate <NSObject>
|
||||||
|
|
||||||
|
- (void) statusItemButtonLeftClick: (StatusItemButton *) button;
|
||||||
|
- (void) statusItemButtonRightClick: (StatusItemButton *) button;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface StatusItemButton : NSView
|
||||||
|
|
||||||
|
@property (strong, nonatomic) NSImage *image;
|
||||||
|
@property (unsafe_unretained) id<StatusItemButtonDelegate> delegate;
|
||||||
|
|
||||||
|
- (instancetype) initWithImage: (NSImage *) image;
|
||||||
|
|
||||||
|
@end
|
39
launchers/macosx/obj-cpp/StatusItemButton.mm
Normal file
39
launchers/macosx/obj-cpp/StatusItemButton.mm
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
#import "StatusItemButton.h"
|
||||||
|
|
||||||
|
@implementation StatusItemButton
|
||||||
|
|
||||||
|
- (instancetype) initWithImage: (NSImage *) image {
|
||||||
|
self = [super initWithFrame:NSMakeRect(0, 0, image.size.width, image.size.height)];
|
||||||
|
if (self) {
|
||||||
|
self.image = image;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setImage:(NSImage *)image {
|
||||||
|
_image = image;
|
||||||
|
[self setNeedsDisplay:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) drawRect: (NSRect) dirtyRect {
|
||||||
|
NSSize imageSize = self.image.size;
|
||||||
|
CGFloat x = (self.bounds.size.width - imageSize.width)/2;
|
||||||
|
CGFloat y = (self.bounds.size.height - imageSize.height) /2;
|
||||||
|
NSRect drawnRect = NSMakeRect(x, y, imageSize.width, imageSize.height);
|
||||||
|
|
||||||
|
[self.image drawInRect:drawnRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) mouseDown:(NSEvent *)theEvent {
|
||||||
|
[self.delegate statusItemButtonLeftClick:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) rightMouseDown:(NSEvent *)theEvent {
|
||||||
|
[self.delegate statusItemButtonRightClick:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
46
launchers/macosx/obj-cpp/build.ninja
Normal file
46
launchers/macosx/obj-cpp/build.ninja
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
cxx = clang++
|
||||||
|
cflags = -std=c++14 -g -Wall -I./include -I/usr/local/include -I/usr/include -Wno-unused-variable -mmacosx-version-min=10.10
|
||||||
|
ldflags = -framework CoreFoundation -framework Foundation -framework Cocoa -g -rdynamic
|
||||||
|
|
||||||
|
|
||||||
|
pool link_pool
|
||||||
|
depth = 4
|
||||||
|
|
||||||
|
rule cxx
|
||||||
|
command = $cxx $cflags -c $in -o $out
|
||||||
|
description = CC $out
|
||||||
|
|
||||||
|
rule link
|
||||||
|
command = $cxx $ldflags -o $out $in
|
||||||
|
description = LINK $out
|
||||||
|
pool = link_pool
|
||||||
|
|
||||||
|
rule ar
|
||||||
|
command = ar crsT $out $in
|
||||||
|
description = AR $out
|
||||||
|
|
||||||
|
rule cleanup
|
||||||
|
command = rm -fr *.o clauncher I2PLauncher.app
|
||||||
|
|
||||||
|
rule bundledir
|
||||||
|
command = mkdir -p I2PLauncher.app/Contents/{MacOS,Resources,Frameworks} && cp Info.plist I2PLauncher.app/Contents/Info.plist
|
||||||
|
|
||||||
|
rule copytobundledir
|
||||||
|
command = cp clauncher I2PLauncher.app/Contents/MacOS/I2PLauncher
|
||||||
|
|
||||||
|
rule copyimgtobundle
|
||||||
|
command = cp ItoopieTransparent.png I2PLauncher.app/Contents/Resources/ItoopieTransparent.png
|
||||||
|
|
||||||
|
build main.o: cxx main.mm
|
||||||
|
build StatusItemButton.o: cxx StatusItemButton.mm
|
||||||
|
build JavaRunner.o: cxx JavaRunner.cpp
|
||||||
|
|
||||||
|
build clean: cleanup
|
||||||
|
|
||||||
|
build bundle: bundledir
|
||||||
|
build copytobundle: copytobundledir | bundle clauncher
|
||||||
|
|
||||||
|
build clauncher: link main.o StatusItemButton.o JavaRunner.o
|
||||||
|
|
||||||
|
build appbundle: copyimgtobundle | clauncher bundle copytobundle
|
||||||
|
#build all: clauncher
|
105
launchers/macosx/obj-cpp/include/strutil.hpp
Normal file
105
launchers/macosx/obj-cpp/include/strutil.hpp
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#ifndef __STRUTIL_HPP__
|
||||||
|
#define __STRUTIL_HPP__
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cctype>
|
||||||
|
#include <locale>
|
||||||
|
#include <experimental/optional>
|
||||||
|
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <CoreFoundation/CFArray.h>
|
||||||
|
#include <CoreFoundation/CFString.h>
|
||||||
|
|
||||||
|
std::string strprintf(const char *fromat, ...)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
s.resize(128); // best guess
|
||||||
|
char *buff = const_cast<char *>(s.data());
|
||||||
|
|
||||||
|
va_list arglist;
|
||||||
|
va_start(arglist, fromat);
|
||||||
|
auto len = vsnprintf(buff, 128, fromat, arglist);
|
||||||
|
va_end(arglist);
|
||||||
|
|
||||||
|
if (len > 127)
|
||||||
|
{
|
||||||
|
va_start(arglist, fromat);
|
||||||
|
s.resize(len + 1); // leave room for null terminator
|
||||||
|
buff = const_cast<char *>(s.data());
|
||||||
|
len = vsnprintf(buff, len+1, fromat, arglist);
|
||||||
|
va_end(arglist);
|
||||||
|
}
|
||||||
|
s.resize(len);
|
||||||
|
return s; // move semantics FTW
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string extractString(CFStringRef value)
|
||||||
|
{
|
||||||
|
const char * data = CFStringGetCStringPtr(value, kCFStringEncodingUTF8);
|
||||||
|
if (data != NULL)
|
||||||
|
{
|
||||||
|
return std::string(data, strlen(data));
|
||||||
|
} else {
|
||||||
|
CFIndex strSize = CFStringGetLength(value)+1;
|
||||||
|
char * retry = (char *)malloc((int)strSize);
|
||||||
|
if (CFStringGetCString(value, retry, strSize, kCFStringEncodingUTF8)) {
|
||||||
|
return std::string(retry, strlen(retry));
|
||||||
|
}
|
||||||
|
return std::string("[null]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using std::experimental::optional;
|
||||||
|
|
||||||
|
// Use CFStringRef instead of NSString*, otherwise disable ARC
|
||||||
|
optional<CFStringRef> optionalString(bool val) {
|
||||||
|
optional<CFStringRef> myOptString;
|
||||||
|
if(val) {
|
||||||
|
// Cast to corresponding CoreFoundation object
|
||||||
|
myOptString = (CFStringRef)@"String";
|
||||||
|
}
|
||||||
|
return myOptString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// trim from start (in place)
|
||||||
|
static inline void ltrim(std::string &s) {
|
||||||
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
|
||||||
|
std::not1(std::ptr_fun<int, int>(std::isspace))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim from end (in place)
|
||||||
|
static inline void rtrim(std::string &s) {
|
||||||
|
s.erase(std::find_if(s.rbegin(), s.rend(),
|
||||||
|
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim from both ends (in place)
|
||||||
|
static inline void trim(std::string &s) {
|
||||||
|
ltrim(s);
|
||||||
|
rtrim(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim from start (copying)
|
||||||
|
static inline std::string ltrim_copy(std::string s) {
|
||||||
|
ltrim(s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim from end (copying)
|
||||||
|
static inline std::string rtrim_copy(std::string s) {
|
||||||
|
rtrim(s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim from both ends (copying)
|
||||||
|
static inline std::string trim_copy(std::string s) {
|
||||||
|
trim(s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
1630
launchers/macosx/obj-cpp/include/subprocess.hpp
Normal file
1630
launchers/macosx/obj-cpp/include/subprocess.hpp
Normal file
File diff suppressed because it is too large
Load Diff
348
launchers/macosx/obj-cpp/main.mm
Normal file
348
launchers/macosx/obj-cpp/main.mm
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <experimental/optional>
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <CoreFoundation/CFStream.h>
|
||||||
|
#include <CoreFoundation/CFPropertyList.h>
|
||||||
|
#include <CoreFoundation/CFDictionary.h>
|
||||||
|
#include <CoreFoundation/CFArray.h>
|
||||||
|
#include <CoreFoundation/CFString.h>
|
||||||
|
#include <CoreFoundation/CFPreferences.h>
|
||||||
|
|
||||||
|
#import <objc/Object.h>
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
#import <AppKit/NSApplication.h>
|
||||||
|
|
||||||
|
#include "AppDelegate.h"
|
||||||
|
#include "StatusItemButton.h"
|
||||||
|
#include "JavaRunner.h"
|
||||||
|
#include "JavaHelper.h"
|
||||||
|
|
||||||
|
#define DEF_I2P_VERSION "0.9.35"
|
||||||
|
#define APPDOMAIN "net.i2p.launcher"
|
||||||
|
#define NSAPPDOMAIN @APPDOMAIN
|
||||||
|
#define CFAPPDOMAIN CFSTR(APPDOMAIN)
|
||||||
|
|
||||||
|
#define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]);
|
||||||
|
|
||||||
|
JvmListSharedPtr gRawJvmList = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
@interface MenuBarCtrl () <StatusItemButtonDelegate, NSMenuDelegate>
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface AppDelegate () <NSUserNotificationCenterDelegate, NSApplicationDelegate>
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@implementation MenuBarCtrl
|
||||||
|
|
||||||
|
- (void) statusItemButtonLeftClick: (StatusItemButton *) button
|
||||||
|
{
|
||||||
|
CFShow(CFSTR("Left button clicked!"));
|
||||||
|
NSEvent *event = [NSApp currentEvent];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) statusItemButtonRightClick: (StatusItemButton *) button
|
||||||
|
{
|
||||||
|
CFShow(CFSTR("Right button clicked!"));
|
||||||
|
NSEvent *event = [NSApp currentEvent];
|
||||||
|
[self.statusItem popUpStatusItemMenu: self.menu];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)statusBarImageBtnClicked
|
||||||
|
{
|
||||||
|
[NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(btnPressedAction) userInfo:nil repeats:NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)btnPressedAction:(id)sender
|
||||||
|
{
|
||||||
|
NSLog(@"Button presseeeeeeed");
|
||||||
|
NSEvent *event = [NSApp currentEvent];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
||||||
|
{
|
||||||
|
NSLog(@"Clicked startJavaRouterBtnHandler");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
||||||
|
{
|
||||||
|
NSLog(@"Clicked restartJavaRouterBtnHandler");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) stopJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
||||||
|
{
|
||||||
|
NSLog(@"Clicked stopJavaRouterBtnHandler");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) quitWrapperBtnHandler: (NSMenuItem *) menuItem
|
||||||
|
{
|
||||||
|
NSLog(@"quitWrapper event handler called!");
|
||||||
|
[[NSApplication sharedApplication] terminate:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MenuBarCtrl *) init
|
||||||
|
{
|
||||||
|
self.menu = [self createStatusBarMenu];
|
||||||
|
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
|
||||||
|
|
||||||
|
self.image = [NSImage imageNamed:@"ItoopieTransparent.png"];
|
||||||
|
[self.image setTemplate:YES];
|
||||||
|
self.statusItem.image = self.image;
|
||||||
|
|
||||||
|
self.statusItem.highlightMode = NO;
|
||||||
|
self.statusItem.toolTip = @"I2P Router Controller";
|
||||||
|
|
||||||
|
self.statusBarButton = [[StatusItemButton alloc] initWithImage:self.image];
|
||||||
|
self.statusBarButton.menu = self.menu;
|
||||||
|
|
||||||
|
// Selecting action
|
||||||
|
//[self.statusBarButton setAction:@selector(statusBarImageBtnClicked)];
|
||||||
|
//[self.statusBarButton setTarget:self];
|
||||||
|
self.statusBarButton.delegate = self;
|
||||||
|
[self.statusItem popUpStatusItemMenu: self.menu];
|
||||||
|
|
||||||
|
[self.statusItem setView: self.statusBarButton];
|
||||||
|
NSLog(@"Initialized statusbar and such");
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) dealloc
|
||||||
|
{
|
||||||
|
[self.image release];
|
||||||
|
[self.menu release];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMenu *)createStatusBarMenu
|
||||||
|
{
|
||||||
|
NSMenu *menu = [[NSMenu alloc] init];
|
||||||
|
[menu setAutoenablesItems:NO];
|
||||||
|
NSMenuItem *startI2Pbtn =
|
||||||
|
[[NSMenuItem alloc] initWithTitle:@"Start I2P"
|
||||||
|
action:@selector(startJavaRouterBtnHandler:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[startI2Pbtn setTarget:self];
|
||||||
|
if ([self.userPreferences boolForKey:@"autoStartRouter"])
|
||||||
|
{
|
||||||
|
[startI2Pbtn setEnabled:NO];
|
||||||
|
} else {
|
||||||
|
[startI2Pbtn setEnabled:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMenuItem *restartI2Pbtn =
|
||||||
|
[[NSMenuItem alloc] initWithTitle:@"Restart I2P"
|
||||||
|
action:@selector(restartJavaRouterBtnHandler:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[restartI2Pbtn setTarget:self];
|
||||||
|
[restartI2Pbtn setEnabled:YES];
|
||||||
|
|
||||||
|
NSMenuItem *stopI2Pbtn =
|
||||||
|
[[NSMenuItem alloc] initWithTitle:@"Stop I2P"
|
||||||
|
action:@selector(stopJavaRouterBtnHandler:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[stopI2Pbtn setTarget:self];
|
||||||
|
[stopI2Pbtn setEnabled:YES];
|
||||||
|
|
||||||
|
NSMenuItem *quitWrapperBtn =
|
||||||
|
[[NSMenuItem alloc] initWithTitle:@"Quit I2P Wrapper"
|
||||||
|
action:@selector(quitWrapperBtnHandler:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[quitWrapperBtn setTarget:self];
|
||||||
|
[quitWrapperBtn setEnabled:YES];
|
||||||
|
|
||||||
|
|
||||||
|
[menu addItem:startI2Pbtn];
|
||||||
|
[menu addItem:stopI2Pbtn];
|
||||||
|
[menu addItem:restartI2Pbtn];
|
||||||
|
[menu addItem:quitWrapperBtn];
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@implementation AppDelegate
|
||||||
|
|
||||||
|
- (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList
|
||||||
|
{
|
||||||
|
NSString *appleScriptString = @"set jvmlist to {\"Newest\"";
|
||||||
|
for (auto item : *rawJvmList) {
|
||||||
|
auto str = strprintf(",\"%s\"", item->JVMName.c_str()).c_str();
|
||||||
|
NSString* tmp = [NSString stringWithUTF8String:str];
|
||||||
|
appleScriptString = [appleScriptString stringByAppendingString:tmp];
|
||||||
|
}
|
||||||
|
appleScriptString = [appleScriptString stringByAppendingString:@"}\nchoose from list jvmlist\n"];
|
||||||
|
NSAppleScript *theScript = [[NSAppleScript alloc] initWithSource:appleScriptString];
|
||||||
|
NSDictionary *theError = nil;
|
||||||
|
NSString* userResult = [[theScript executeAndReturnError: &theError] stringValue];
|
||||||
|
NSLog(@"User choosed %@.\n", userResult);
|
||||||
|
if (theError != nil)
|
||||||
|
{
|
||||||
|
NSLog(@"Error: %@.\n", theError);
|
||||||
|
}
|
||||||
|
return userResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)userChooseJavaHome {
|
||||||
|
listAllJavaInstallsAvailable();
|
||||||
|
std::shared_ptr<JvmHomeContext> appContext = std::shared_ptr<JvmHomeContext>( new JvmHomeContext() );
|
||||||
|
for (auto item : *appContext->getJvmList()) {
|
||||||
|
printf("JVM %s (Version: %s, Directory: %s)\n", item->JVMName.c_str(), item->JVMPlatformVersion.c_str(), item->JVMHomePath.c_str());
|
||||||
|
}
|
||||||
|
JvmListPtr rawJvmList = appContext->getJvmList();
|
||||||
|
NSString * userJavaHome = [self userSelectJavaHome: rawJvmList];
|
||||||
|
// TODO: Add logic so user can set preferred JVM
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setApplicationDefaultPreferences {
|
||||||
|
auto defaultJVMHome = check_output({"/usr/libexec/java_home","-v",DEF_MIN_JVM_VER});
|
||||||
|
auto tmpStdStr = std::string(defaultJVMHome.buf.data());
|
||||||
|
trim(tmpStdStr);
|
||||||
|
auto cfDefaultHome = CFStringCreateWithCString(NULL, const_cast<const char *>(tmpStdStr.c_str()), kCFStringEncodingUTF8);
|
||||||
|
[self.userPreferences registerDefaults:@{
|
||||||
|
@"javaHome" : (NSString *)cfDefaultHome,
|
||||||
|
@"lastI2PVersion" : (NSString *)CFSTR(DEF_I2P_VERSION),
|
||||||
|
@"enableLogging": @true,
|
||||||
|
@"enableVerboseLogging": @true,
|
||||||
|
@"autoStartRouter": @true
|
||||||
|
}];
|
||||||
|
if (self.enableVerboseLogging) NSLog(@"Default JVM home preference set to: %@", (NSString *)cfDefaultHome);
|
||||||
|
|
||||||
|
auto dict = [self.userPreferences dictionaryRepresentation];
|
||||||
|
[self.userPreferences setPersistentDomain:dict forName:NSAPPDOMAIN];
|
||||||
|
|
||||||
|
CFPreferencesSetMultiple((CFDictionaryRef)dict, NULL, CFAPPDOMAIN, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
|
||||||
|
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
|
||||||
|
//CFPreferencesSetAppValue(@"javaHome", (CFPropertyListRef)cfDefaultHome, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
|
||||||
|
|
||||||
|
if (self.enableVerboseLogging) NSLog(@"Default preferences stored!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||||
|
// Init application here
|
||||||
|
// Start with user preferences
|
||||||
|
self.userPreferences = [NSUserDefaults standardUserDefaults];
|
||||||
|
[self setApplicationDefaultPreferences];
|
||||||
|
self.enableLogging = [self.userPreferences boolForKey:@"enableLogging"];
|
||||||
|
self.enableVerboseLogging = [self.userPreferences boolForKey:@"enableVerboseLogging"];
|
||||||
|
|
||||||
|
gRawJvmList = std::make_shared<std::list<JvmVersionPtr> >(std::list<JvmVersionPtr>());
|
||||||
|
// In case we are unbundled, make us a proper UI application
|
||||||
|
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
|
||||||
|
[NSApp activateIgnoringOtherApps:YES];
|
||||||
|
//auto prefArray = CFPreferencesCopyKeyList(CFAPPDOMAIN, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
|
||||||
|
//CFShow(prefArray);
|
||||||
|
auto javaHomePref = [self.userPreferences stringForKey:@"javaHome"];
|
||||||
|
if (self.enableVerboseLogging) NSLog(@"Java home from preferences: %@", javaHomePref);
|
||||||
|
|
||||||
|
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
|
||||||
|
|
||||||
|
// This is the only GUI the user experience on a regular basis.
|
||||||
|
self.menuBarCtrl = [[MenuBarCtrl alloc] init];
|
||||||
|
|
||||||
|
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
|
||||||
|
if (self.enableVerboseLogging) NSLog(@"Appdomain is: %@", appDomain);
|
||||||
|
|
||||||
|
NSLog(@"We should have started the statusbar object by now...");
|
||||||
|
//[statusBarButton setAction:@selector(itemClicked:)];
|
||||||
|
//dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
//});
|
||||||
|
auto pref = self.userPreferences;
|
||||||
|
self.menuBarCtrl.userPreferences = self.userPreferences;
|
||||||
|
self.menuBarCtrl.enableLogging = self.enableLogging;
|
||||||
|
self.menuBarCtrl.enableVerboseLogging = self.enableVerboseLogging;
|
||||||
|
|
||||||
|
if (self.enableVerboseLogging) NSLog(@"processinfo %@", [[NSProcessInfo processInfo] arguments]);
|
||||||
|
|
||||||
|
auto getJavaHomeLambda = [&pref,&self]() -> std::string {
|
||||||
|
NSString* val = @"";
|
||||||
|
val = [pref stringForKey:@"javaHome"];
|
||||||
|
if (val == NULL) val = @"";
|
||||||
|
if (self.enableVerboseLogging) NSLog(@"Javahome: %@", val);
|
||||||
|
return std::string([val UTF8String]);;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
auto launchLambda = [&pref](JavaRunner *javaRun) {
|
||||||
|
javaRun->javaProcess->start_process();
|
||||||
|
auto pid = javaRun->javaProcess->pid();
|
||||||
|
std::cout << "I2P Router process id = " << pid << std::endl;
|
||||||
|
|
||||||
|
// Blocking
|
||||||
|
javaRun->javaProcess->wait();
|
||||||
|
};
|
||||||
|
auto callbackAfterExit = [=](){
|
||||||
|
printf("Callback after exit\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Get Java home
|
||||||
|
auto javaHome = getJavaHomeLambda();
|
||||||
|
trim(javaHome); // Trim to remove endline
|
||||||
|
auto javaBin = std::string(javaHome);
|
||||||
|
javaBin += "/bin/java"; // Append java binary to path.
|
||||||
|
//printf("hello world: %s\n", javaBin.c_str());
|
||||||
|
if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]);
|
||||||
|
|
||||||
|
auto r = new JavaRunner{ javaBin, launchLambda, callbackAfterExit };
|
||||||
|
r->execute();
|
||||||
|
} catch (std::exception &err) {
|
||||||
|
std::cerr << "Exception: " << err.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Exit sequence
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||||
|
// Tear down here
|
||||||
|
NSString *string = @"applicationWillTerminate executed";
|
||||||
|
NSLog(@"%@", string);
|
||||||
|
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* wrapper for main */
|
||||||
|
- (AppDelegate *)initWithArgc:(int)argc argv:(const char **)argv {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
NSApplication *app = [NSApplication sharedApplication];
|
||||||
|
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
app.delegate = [[AppDelegate alloc] initWithArgc:argc argv:argv];
|
||||||
|
[NSBundle loadNibNamed:@"I2Launcher" owner:NSApp];
|
||||||
|
|
||||||
|
[NSApp run];
|
||||||
|
// Handle any errors
|
||||||
|
//CFRelease(javaHomes);
|
||||||
|
//CFRelease(err);
|
||||||
|
[pool drain];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user