Client-to-client messaging in cocoa? - cocoa

erm, now I trying to do a messaging between both client instead of client to server. So if I'm not wrong we can't startup service individually but how to see whether is setting up individually or both connect to same service?
My Code for startup the service:
-(void)startService {
// Start listening socket
NSError *error;
self.listeningSocket = [[[AsyncSocket alloc]initWithDelegate:self] autorelease];
if ( ![self.listeningSocket acceptOnPort:0 error:&error] ) {
NSLog(#"Failed to create listening socket");
return;
}
// Advertise service with bonjour
NSString *serviceName = [NSString stringWithFormat:#"Aho- %#",
[[NSProcessInfo processInfo] hostName]];
connectedService = [[NSNetService alloc] initWithDomain:#"" type:#"_cocoaforsci._tcp."
name:serviceName
port:1234];
connectedService.delegate = self;
[connectedService publish];
}
Any suggestion?

Based on your latest comment, I recommend this article (source is linked near the beginning):
Tutorial: Networking and Bonjour on iPhone
I believe most (if not all) of the article applies just as well to the Mac platform as it does to the iPhone platform.

Related

SFSpeechRecognizer on MacOS not available despite successful authorization

I am trying to get a clumsy Objective-C proof-of-concept example to run with SFSpeechRecognizer on Catalina transcribing a local audio file.
After some googling I have managed to get the authorization to work by adding an Info.plist with NSSpeechRecognitionUsageDescription and I get the authorization dialog and the correct SFSpeechRecognizerAuthorizationStatus (SFSpeechRecognizerAuthorizationStatusAuthorized).
However, my SFSpeechRecognizer instance still is unavailable. I suspect, I must be making a stupid mistake due to lack of basic Objective-C knowledge.
Any hints greatly appreciated.
Here's my code:
//
// main.m
// SpeechTestCatalina
//
#import <Foundation/Foundation.h>
#import <Speech/Speech.h>
void transcribeTestFile(){
NSLocale *locale =[[NSLocale alloc] initWithLocaleIdentifier:#"en-US"];
SFSpeechRecognizer *speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale];
NSLog(#"Locale %#, %#", speechRecognizer.locale.languageCode, speechRecognizer.locale.countryCode);
NSLog(#"Available %hhd", speechRecognizer.available);
NSLog(#"Auth status %ld", [SFSpeechRecognizer authorizationStatus]);
NSLog(#"Supports on device %hhd", speechRecognizer.supportsOnDeviceRecognition);
if(speechRecognizer.isAvailable && speechRecognizer.supportsOnDeviceRecognition){
NSString *audioFilePath = #"/Users/doe/speech-detection/speech_sample.wav";
NSURL *url = [[NSURL alloc] initFileURLWithPath:audioFilePath];
NSLog(#"Analyzing %# in language %#", url, locale.languageCode);
SFSpeechURLRecognitionRequest *urlRequest = [[SFSpeechURLRecognitionRequest alloc] initWithURL:url];
urlRequest.requiresOnDeviceRecognition = true;
urlRequest.shouldReportPartialResults = YES; // YES if animate writting
[speechRecognizer recognitionTaskWithRequest: urlRequest resultHandler: ^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error){
NSString *transcriptText = result.bestTranscription.formattedString;
if(!error){
NSLog(#"Transcript: %#", transcriptText);
} else {
NSLog(#"Error: %#", error);
}
}];
} else {
NSLog(#"speechRecognizer is not available on this device");
}
}
int main(int argc, const char * argv[]) {
#autoreleasepool {
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus authStatus) {
NSLog(#"Status: %ld", (long)authStatus);
switch (authStatus) {
case SFSpeechRecognizerAuthorizationStatusAuthorized:
//User gave access to speech recognition
NSLog(#"Authorized");
transcribeTestFile();
break;
case SFSpeechRecognizerAuthorizationStatusDenied:
//User denied access to speech recognition
NSLog(#"SFSpeechRecognizerAuthorizationStatusDenied");
break;
case SFSpeechRecognizerAuthorizationStatusRestricted:
//Speech recognition restricted on this device
NSLog(#"SFSpeechRecognizerAuthorizationStatusRestricted");
break;
case SFSpeechRecognizerAuthorizationStatusNotDetermined:
//Speech recognition not yet authorized
break;
default:
NSLog(#"Default");
break;
}
}];
NSLog(#"Sleeping");
[NSThread sleepForTimeInterval:20.0f];
}
return 0;
}
The output when I run it is:
2020-01-26 17:48:39.454809+0100 SpeechTestCatalina[3623:82404] Sleeping
2020-01-26 17:48:41.182459+0100 SpeechTestCatalina[3623:82811] Status: 3
2020-01-26 17:48:41.182562+0100 SpeechTestCatalina[3623:82811] Authorized
2020-01-26 17:48:41.186933+0100 SpeechTestCatalina[3623:82811] Locale en, US
2020-01-26 17:48:41.190973+0100 SpeechTestCatalina[3623:82811] Available 0
2020-01-26 17:48:41.191269+0100 SpeechTestCatalina[3623:82811] Auth status 3
2020-01-26 17:48:41.197965+0100 SpeechTestCatalina[3623:82811] Supports on device 0
2020-01-26 17:48:41.198065+0100 SpeechTestCatalina[3623:82811] speechRecognizer is not available on this device
Program ended with exit code: 0
You aren't getting the callback because your binary does not have a runloop. I'll take the response from this different question but with the same answer:
Callbacks in most Apple frameworks are delivered through your application's main run loop. If your command-line tool does not have a run loop, it cannot receive callbacks that are sent this way.
Without a runloop, the only way for the framework to invoke your callback would be to run it on another thread, which could lead to weird behaviour in an application that didn't expect that.
You can manually pump the runloop by inserting this code before the end of main:
NSRunLoop* runloop = [NSRunLoop currentRunLoop];
[runloop runUntilDate:[NSDate distantFuture]];
This will prevent your application from exiting; you'll need to update your logic to know when speech recognition is finished and restructure that with a while loop or something - but I assume the logic inside your "real" application is different than this toy sample.
The message:
AddInstanceForFactory: No factory registered for id F8BB1C28-BAE8-11D6-9C31-00039315CD46 HALC_ShellDriverPlugIn::Open: Can't get a pointer to the Open routine
that appears in your console a meaningless; it's some log statement leaking out of the system frameworks and you can disregard it.
Finally, for clarification on a couple other points:
"Enable Ask Siri" was required to be enabled in System Preferences > Siri for speech recognition to be available
There is a potential issue where the device may report that "on device recognition" is not available the first time you check, despite being supported for the chosen locale

Launch OS X Application Programmatically

How do I programmatically open an OS X app (.app) that is contained within the app I am building?
The preferred way of doing this on OS X is through the NSWorkspace class, which provides a couple of methods to launch applications. One of them, launchApplicationAtURL:options:configuration:error: allows you to specify a file URL to the application to launch. In addition of not having sandbox problems like the system() and Apple Event solution, it also gives you an easy way to manipulate how the application should be launched, eg. you can specify environment variables to be passed to the application.
Following Code snippet is used to launch an app programmatically:
NSString *path = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent];
path = [path stringByAppendingString:#"/MyApp.app"]; // App Path
NSWorkspace *ws=[NSWorkspace sharedWorkspace];
NSURL* url = [NSURL fileURLWithPath:path isDirectory:NO];
[ws launchApplicationAtURL:url
options:NSWorkspaceLaunchWithoutActivation
configuration:nil
error:nil];
You could use an Apple Script.
NSDictionary* errorDict;
NSAppleEventDescriptor* returnDescriptor = NULL;
NSAppleScript* scriptObject;
scriptObject = [[NSAppleScript alloc] initWithSource:#"try\n
run application \"Macintosh HD:Applications:_Sandbox-AppleScript0.app\"\n
on error number -609 # 'Connection is invalid' error that is spuriously reported # simply ignore\n
end try"];
if (returnDescriptor != NULL) {
// successful execution
if (kAENullEvent != [returnDescriptor descriptorType]) {
// script returned an AppleScript result
if (cAEList == [returnDescriptor descriptorType]) {
// result is a list of other descriptors
}
else {
// coerce the result to the appropriate ObjC type
}
}
}

SQLite error code:14, 'unable to open database file'

In my cocoa application, i am using core data to maintain all my datas. But some time ,i am getting the below given issue.
Issue:
CoreData: error: (14) I/O error for database at /Users/my-mac/Documents/FileT.sqlite. SQLite error code:14, 'unable to open database file'
Here i given the code reference for persistentStoreCoordinator :
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory]
stringByAppendingPathComponent: #"FileT.sqlite"]];
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:[self managedObjectModel]];
options = #{
NSMigratePersistentStoresAutomaticallyOption : #YES,
NSInferMappingModelAutomaticallyOption : #YES
};
if(![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil URL:storeUrl options:options error:&error]) {
/*Error for store creation should be handled in here*/
}
return _persistentStoreCoordinator;
}
Can anyone suggest what i am missing here?
Take a look at Technical Q&A 1809: New default journaling mode for Core Data SQLite stores in iOS 7 and OS X Mavericks
Your application may be moving or changing the WAL journal files or SQLite files, or may have made assumptions about the file structure that was valid for versions of Core Data that did not use WAL.
It's also possible that your SQLite database is being corrupted, and the error 14 is SQLite attempting to repair the file when Core Data opens it. This corruption can happen if the application was not shut down properly when a write was happening - and many other circumstances. Not shutting down properly is the most common case on Apple platforms though - for example, if Core Data is writing records and the OS kills the application because it's unresponsive. That can cause corruption.

Mavericks, SandBoxed, but deployment target to 10.8 and above using EKEventStore and calendar access

I've written this code below just to get it to compile but this will not work, because I need to have a deployment target of 10.8.
what is going on is I need access to EKEventStore , so when someone downloads this app, it runs fine in 10.8, but someone downloading in 10.9 would get errors, because the app doesn't have Privacy permission to the calendar. Since it is being compiled for 10.8, it has no access to the method requestAccessToEntityType:EKEntityTypeEvent..
how would one go about doing this?
on a related note, how do you compile code for 10.9, other code for 10.8, and call those different parts depending on the environment it is in? remembering this is for the Mac App Store, and if that is the way to go, be illustrative, as if you are talking to someone who has no idea how to begin to do this, because I don't..
thanks.
//------------------check authorization of calendars--------------
#if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) || (__IPHONE_OS_VERSION_MIN_REQUIRED)
if(!eventStore) eventStore = [[EKEventStore alloc] init];
[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) //.............put this back in...
{
if (granted)
{
NSLog(#"granted permission to eventstore!");
authorizedEventStore = YES;
authorizedCalendar();
}
else
{
NSLog(#"Not granted");
authorizedEventStore = NO;
notAuthorized();
}
}];
#else
NSLog(#"not able to request");
if(!eventStore) eventStore = [[EKEventStore alloc] initWithAccessToEntityTypes:EKEntityMaskEvent];
authorizedEventStore = YES;
authorizedCalendar();
#endif
//------------------end check authorization of calendars--------------
To have an App that runs on several OS versions:
Set your Base SDK to the latest version of the OS you support, in your case 10.9
Set the Deployment Target to the earliest OS you want your code to launch on
For all calls that don't exist in earlier versions of the OS, you must test before you call, either by using respondsToSelector: (for methods) or testing against nil (for functions and statics). You can if you like do a check for the OS version, but it's more robust to check the specific call.
see also:
How to conditionally use a new Cocoa API and
How do I include calls to methods only present in one operating system version when compiling for multiple versions?
To request access on OS X use:
EKEventStore *eventStore = nil;
if ([EKEventStore respondsToSelector:#selector(authorizationStatusForEntityType:)]) {
// 10.9 style
eventStore = [[EKEventStore alloc] init];
[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error)
{
// your completion
}];
} else {
// 10.8 style
eventStore = [[EKEventStore alloc] initWithAccessToEntityTypes:EKEntityMaskEvent ];
}

Saving an Apple Mail Message using ScriptBridge

I am trying to save a selected email from Apple Mail using ScriptBridge.
I have already created the Mail.h file and in my program I have successfully done other things with the Apple Mail ScriptBridge (like forwarding messages etc.)
Here is my current code. I get no error messages and the code is running fine; only the file never gets created.
I am using Xcode 4.6. on Mountain Lion 10.8.2. The deployment target of my app is 10.8.
- (void)saveEmail {
MailApplication *mailApp = [SBApplication applicationWithBundleIdentifier:#"com.apple.Mail"];
SBElementArray *viewers = [mailApp messageViewers];
for (MailMessageViewer *viewer in viewers) {
NSArray *selectedMessages = [viewer selectedMessages];
#try {
for (MailMessage *selectedMessage in selectedMessages) {
NSString *filePath = [NSString stringWithFormat:#"%#%#",#"/Users/patrick/Documents/",#"tmp.rtf"];
NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
[selectedMessage saveIn:fileUrl as:MailSaveableFileFormatNativeFormat];
}
}
#catch (NSException *exception) {
NSLog(#"Exception:%#", exception);
}
}
}
Have exactly the same problem. Seems saveIn isn't implemented in Mail.
I have a workaround with this code:
[message.source writeToURL:mailUrl
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
Where message is an instance of MailMessage
This seems to work correctly most of the time. But sometimes the attachments are empty in the saved mail. So if anyone has a better solution...

Resources