NSOutputStream not calling delegate's NSStreamEventHasSpaceAvailable - ios

I have implemented socket by using input and output streams. The external architecture takes care of sending one request at a time to write.
However if any request does not return no HasBytesAvailable I need to remove that request from queue and inform about request timeout.
For all other requests, I am able to send/receive data correctly, but if any one of the request time outs then after that HasSpaceAvailable never gets called.
My code is as follows :
#implementation CCCommandSocket
#synthesize connectionTimeoutTimer;
#synthesize requestTimeoutTimer;
/*
* init
*
* #params
* ipAddress :ip address of camera socket
* portNumber :port address of camera socket
*
* #return
* Object of type Socket, which will send connection request to ipAddress,portNumber
*
*/
- (id)init
{
self = [super init];
if (self)
{
ip = #"192.168.42.1";
port = 7878;
[self performSelectorOnMainThread:#selector(connectToCamera) withObject:nil waitUntilDone:YES];
bytesReceivedCondition = [[NSCondition alloc] init];
requestCompletedCondition = [[NSCondition alloc] init];
requestReadyToProcess = [[NSCondition alloc] init];
isBytesReceived = false;
isRequestCompleted = false;
isRequestReadyToProcess = false;
responseString = [[NSString alloc] init];
openBracesCount = 0;
mutex = [[NSLock alloc] init];
}
return self;
}
pragma mark-
pragma establish socket communication.
/*
* connectToCamera
*
*/
- (void) connectToCamera
{
NSString *urlStr = ip;
if (![urlStr isEqualToString:#""])
{
NSURL *website = [NSURL URLWithString:urlStr];
if (!website)
{
NSString* messageString = [NSString stringWithFormat:#"%# is not a valid URL",website];
CCLog(LOG_ERROR, messageString);
return;
}
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(urlStr), port, &readStream, &writeStream);
//cast the CFStreams to NSStreams
inputStream = (__bridge_transfer NSInputStream *)readStream;
outputStream = (__bridge_transfer NSOutputStream *)writeStream;
//set the delegate
[inputStream setDelegate:self];
[outputStream setDelegate:self];
//schedule the stream on a run loop
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
//open the stream
[inputStream open];
[outputStream open];
if(readStream==NULL)
{
CCLog(LOG_INFO, #"readstream NULL");
}
if(writeStream == NULL)
{
CCLog(LOG_INFO, #"writeStream NULL");
}
[self startConnectionTimeoutTimer];
}
}
pragma mark -
pragma getter methods
/*
* getIP
*
* #return
* Ip address to which socket is connected
*/
-(NSString *) getIP
{
return ip;
}
/*
* getPort
*
* #return
* Port number to which socket is connected
*/
-(int) getPort
{
return port;
}
pragma mark-
pragma Handle socket callbacks.
(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:stream];
[array addObject:[NSNumber numberWithInt:eventCode]];
[self performSelectorInBackground:#selector(myStream:) withObject:array];
}
(void)myStream:(NSMutableArray*) array
{
NSNumber *number = [array objectAtIndex:1];
int eventCode = [number intValue];
switch(eventCode)
{
case NSStreamEventErrorOccurred:
{
CCLog(LOG_ERROR, #"In Command Socket NSStreamEventErrorOccurred");
//[self disconnect];
//[[ErrorDetails getInstance] reportError:NSStreamEventErrorOccurred];
break;
}
//Read from stream
case NSStreamEventHasBytesAvailable:
{
CCLog(LOG_INFO, #"In Command Socket NSStreamEventHasBytesAvailable");
[self handleCommandPortDataReceived];
break;
}
//Write to stream
case NSStreamEventHasSpaceAvailable:
{
#synchronized(self)
{
[requestReadyToProcess lock];
while (isRequestReadyToProcess == false)
{
[requestReadyToProcess wait];
}
[requestReadyToProcess unlock];
CCLog(LOG_INFO,#"In Command Socket NSStreamEventHasSpaceAvailable");
#try
{
#synchronized(requestString)
{
if(requestString != nil)
{
if(outputStream != nil)
{
int dataSent;
uint8_t* data = (uint8_t *)[requestString cStringUsingEncoding:NSUTF8StringEncoding];
responseString = #"";
//[requestReadyToProcess lock];
isRequestReadyToProcess = false;
//[requestReadyToProcess signal];
dataSent = [outputStream write:data maxLength:strlen((char*)data)];
if(dataSent != -1)
{
NSString* message = [NSString stringWithFormat:#"Bytes written %d for request\n %#",dataSent, requestString];
CCLog(LOG_REQUEST, message);
requestString = nil;
isBytesReceived = false;
[bytesReceivedCondition lock];
while (isBytesReceived ==false)
{
[bytesReceivedCondition wait];
}
[requestCompletedCondition lock];
isRequestCompleted = true;
[requestCompletedCondition signal];
[requestCompletedCondition unlock];
[bytesReceivedCondition unlock];
}
else
{
CCLog(LOG_INFO, #"Command Socket : Request not sent (dataSent == -1)");
responseString = #"{ \"rval\": -104}";
CCLog(LOG_RESPONSE, responseString);
[self removeRequestFromQueue];
}
}
else
{
CCLog(LOG_INFO, #"in else :(outputStream != nil)");
}
}
}
}
#catch (NSException *e)
{
CCLog(LOG_WARNING, e.description);
}
}
break;
}
case NSStreamEventNone:
{
CCLog(LOG_INFO, #"In Command Socket NSStreamEventNone");
break;
}
case NSStreamEventOpenCompleted:
{
CCLog(LOG_INFO, #"In Command Socket NSStreamEventOpenCompleted");
[self stopConnectionTimeoutTimer];
break;
}
case NSStreamEventEndEncountered:
{
CCLog(LOG_INFO, #"Command Socket NSStreamEventEndEncountered");
[self disconnectWithNotification:YES];
break;
}
}
}
/*
* execute
*
* #param
* request :command to be sent over socket to camera
*
* #return
* responce :response received from camera
*
*/
-(NSString *) executeRequest :(NSString *)request
{
CCLog(LOG_INFO, #"Command Socket Executing request");
[self performSelectorOnMainThread:#selector(startRequestTimeoutTimer) withObject:nil waitUntilDone:NO];
isRequestCompleted = false;
requestString = request;
responseString = #"";
[requestReadyToProcess lock];
isRequestReadyToProcess = true;
[requestReadyToProcess signal];
[requestReadyToProcess unlock];
[requestCompletedCondition lock];
while (isRequestCompleted ==false)
{
[requestCompletedCondition wait];
}
CCLog(LOG_INFO, #"Command Socket Execute request : request completed");
[requestCompletedCondition unlock];
CCLog(LOG_RESPONSE, responseString);
return responseString;
}
pragma mark-
pragma Handle connection time out
// Call this when you initiate the connection
- (void)startConnectionTimeoutTimer
{
[self stopConnectionTimeoutTimer]; // Or make sure any existing timer is stopped before this method is called
NSTimeInterval interval = 10.0; // Measured in seconds, is a double
self.connectionTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:interval
target:self
selector:#selector(handleConnectionTimeout)
userInfo:nil
repeats:NO];
}
(void)handleConnectionTimeout
{
responseString = #"{ \"rval\": -103}";
CCLog(LOG_RESPONSE, responseString);
[self removeRequestFromQueue];
[self disconnectWithNotification:YES];
[self stopConnectionTimeoutTimer];
}
// Call this when you initiate the connection
- (void)startRequestTimeoutTimer
{
[self stopRequestTimeoutTimer]; // Or make sure any existing timer is stopped before this method is called
NSTimeInterval interval = 20.0; // Measured in seconds, is a double
self.requestTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:interval
target:self
selector:#selector(handleRequestTimeout)
userInfo:nil
repeats:NO];
}
(void)handleRequestTimeout
{
responseString = #"{ \"rval\": -103}";
CCLog(LOG_RESPONSE, responseString);
[self connectToCamera];
[self stopRequestTimeoutTimer];
[self removeRequestFromQueue];
}
// Call this when you successfully connect
- (void)stopRequestTimeoutTimer
{
if (requestTimeoutTimer)
{
[requestTimeoutTimer invalidate];
requestTimeoutTimer = nil;
}
}
-(void) disconnectWithNotification:(BOOL)showNotification
{
CCLog(LOG_INFO, #"Socket Disconnected");
[inputStream close];
[inputStream setDelegate:nil];
[inputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
inputStream = nil;
[outputStream close];
[outputStream setDelegate:nil];
[outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
outputStream = nil;
[[CCCore getInstance] disconnectWithNotification:showNotification];
}
// Call this when you successfully connect
- (void)stopConnectionTimeoutTimer
{
if (connectionTimeoutTimer)
{
[connectionTimeoutTimer invalidate];
connectionTimeoutTimer = nil;
}
if (requestTimeoutTimer)
{
[requestTimeoutTimer invalidate];
requestTimeoutTimer = nil;
}
}
-(void) handleCommandPortDataReceived
{
[mutex lock];
[self stopRequestTimeoutTimer];
#try
{
long size = 1024;
uint8_t buf[size];
unsigned int len = 0;
do
{
// read input stream into buffer
strcpy((char *)buf, "\0");
len = [inputStream read:buf maxLength:size];
//NSLog(#"Size = %ld Len = %d, Buf = %s",size, len, (char *)buf);
// Following code checks if we have received complete response by matching "{" and "}"
// from input stream. We continue to form response string unless braces are matched.
if (len > 0)
{
// Create nsdata from buffer
NSMutableData *_data = [[NSMutableData alloc] init];
[_data appendBytes:(const void *)buf length:len];
// create temporary string form nsdata
NSString* currentString = [[NSString alloc] initWithData:_data encoding:NSUTF8StringEncoding];
// check the occurances of { and } in current string
int currentOpeningBraceCount = [[currentString componentsSeparatedByString:#"{"] count] - 1;
int currentClosingBraceCount = [[currentString componentsSeparatedByString:#"}"] count] - 1;
openBracesCount = (openBracesCount + currentOpeningBraceCount) - currentClosingBraceCount;
responseString = [responseString stringByAppendingString:currentString];
// NSLog(#"Total:%d currentOpen:%d currentClose:%d\n\n",openBracesCount, currentOpeningBraceCount, currentClosingBraceCount);
// NSLog(#"Current String : %#\n\n",currentString);
// NSLog(#"Final String : %#",finalString);
// NSLog(#"+++++++++++++++++++++++++++++");
}
else
break;
} while (openBracesCount != 0);
NSRange range = [responseString rangeOfString:#"get_file_complete"];
if(range.location == NSNotFound)
{
//remove it from queue
[bytesReceivedCondition lock];
isBytesReceived = true;
[bytesReceivedCondition signal];
[bytesReceivedCondition unlock];
}
//responseString = #"";
}
#catch (NSException* e)
{
[self connectToCamera];
}
[mutex unlock];
}
-(void) removeRequestFromQueue
{
//remove it from queue
requestString = nil;
[requestReadyToProcess lock];
isRequestReadyToProcess = false;
[requestReadyToProcess unlock];
[requestCompletedCondition lock];
isRequestCompleted = true;
[requestCompletedCondition signal];
[requestCompletedCondition unlock];
}
#end

Which OS version are you trying this on?? I'm having the similar issue, in 10.7 and up it is all good, but on 10.6 and below I get the very same issue you are having I'm doing some debugging but so far have not come up with a good resolution yet.

Related

User Interaction causes a for loop to move onto the next object

I have an array of objects in which this for loop iterates through. Each object is an IP Address that I test for. However, once the for loop gets to a specific object that fails, the for loop takes roughly 15seconds to a minute to move onto the next object. However, if I interact with the display on my device by tapping, the for loop moves onto the next object. I find this odd because I do call [[UIApplication sharedApplication] beginIgnoringInteractionEvents];. So A) Why is the application still detecting touch events which affect the for loop. And B) I verified that the [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; does work because if I try to tap a barButtonItem nothing happens. So here's my question, how can user interaction that's ignored temporarily still cause a for loop to move onto the next object? I've verified that there's no issues with threading/GCD. I know this may be rough to understand without a code sample, however I want to know the principal behind a UI interaction event affecting a for loop.
UPDATE!
Code:
-(void)beginConnectivitySetupAndTests {
for (int i = 0; i<[extractedDataArray count]; i++) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSString *inStoreObject = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectType"];
NSString *objectTitle = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectTechnicalTitle"];
NSString *objectLastOctet = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectLastOctet"];
NSString *isInfrastructureObject = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectIsInfrastructureObject"];
NSString *needsAlternateSecondOctet = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectablityObjectNeedsAlternateSecondOctet"];
NSLog(#"Working with: %#",objectTitle);
if ([inStoreObject isEqualToString:#"InStoreObject"]) {
if ([needsAlternateSecondOctet isEqualToString:#"YES"]) {
// self.deviceIPAddress = nil;
NSLog(#"%#", self.deviceIPAddress);
NSMutableArray <NSString *> *octets = [self.deviceIPAddress componentsSeparatedByString:#"."];
NSString *firstOctetString = [octets objectAtIndex:0];
NSString *secondOctetString = [octets objectAtIndex:1];
NSString *thirdOctetString = [octets objectAtIndex:2];
int secondInt = secondOctetString.intValue;
if (secondInt >= 40 && secondInt <= 47) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +40];
}
else if (secondInt >= 52 && secondInt <= 53) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +100];
}
else if (secondInt >= 120 && secondInt <= 121) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +100];
}
else if (secondInt >= 122 && secondInt <= 123) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +40];
}
else if (secondInt >= 124 && secondInt <= 125) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +40];
}
else if (secondInt >= 126 && secondInt <= 127) {
[octets removeObjectAtIndex:1];
secondOctetString = [NSString stringWithFormat:#"%d", secondInt +40];
} else {
}
NSString *finalString = [NSString stringWithFormat:#"%#.%#.%#.%#", firstOctetString, secondOctetString, thirdOctetString, objectLastOctet];
[[extractedDataArray objectAtIndex:i] setValue:[NSString stringWithFormat:#"%#",finalString]forKey:#"ConnectabilityObjectFullIPAddress"];
finalIPAddress = finalString;
octets = nil;
} else {
NSMutableArray <NSString*> *octets = [self.deviceIPAddress componentsSeparatedByString:#"."];
NSString *firstOctetString = [octets objectAtIndex:0];
NSString *secondOctetString = [octets objectAtIndex:1];
NSString *thirdOctetString = [octets objectAtIndex:2];
[octets removeObjectAtIndex:3];
NSString *lastOctet = [NSString stringWithFormat:#"%#", objectLastOctet];
NSString *constructedIPAddress = [NSString stringWithFormat:#"%#.%#.%#.%#", firstOctetString, secondOctetString, thirdOctetString, lastOctet];
finalIPAddress = constructedIPAddress;
[[extractedDataArray objectAtIndex:i] setValue:[NSString stringWithFormat:#"%#",constructedIPAddress]forKey:#"ConnectabilityObjectFullIPAddress"];
NSLog(#"%# IP: %#", objectTitle, constructedIPAddress);
}
} else {
finalIPAddress = [[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectFullIPAddress"];
}
self.ping = [[SimplePing alloc] initWithHostName:finalIPAddress];
NSLog(#"pinging: %#",finalIPAddress);
self.ping.delegate = self;
[self.ping start];
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (self.ping != nil);
if (pingableObjectAddress) {
if (_deviceLatencyString == NULL) {
[[extractedDataArray objectAtIndex:i] setValue:[NSString stringWithFormat:#"Successful"] forKey:#"ConnectivityPingTestResultValue"];
} else {
[[extractedDataArray objectAtIndex:i] setValue:[NSString stringWithFormat:#"Successful: latency: %# ms",_deviceLatencyString] forKey:#"ConnectivityPingTestResultValue"];
}
pingableObjectAddress = nil;
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
portNumberValue = [[[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectPorts"] intValue];
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)finalIPAddress, portNumberValue, &readStream, &writeStream);
inputStream = (NSInputStream*)CFBridgingRelease(readStream);
outputStream = (NSOutputStream*)CFBridgingRelease(writeStream);
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
NSLog(#"Opening Port for %lu at IP Address %#", (unsigned long)portNumberValue, finalIPAddress);
NSString *response = #"Fly with me!";
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
if ([[extractedDataArray objectAtIndex:i] valueForKey:#"ConnectabilityObjectPorts"] != nil ) {
if (_connectedPortNumber != 0) {
NSLog(#"Port Connection %lu succeeded for %#", (unsigned long)portNumberValue, finalIPAddress);
[[extractedDataArray objectAtIndex:i] setValue:#"Successful" forKey:#"ConnectivityPortConnectResultValue"];
if (!isInfrastructureObject) {
_portConnectionSucceeded = _portConnectionSucceeded + 1;
NSLog(#"port connect is not for infrastructure object");
}
self.connectedPortNumber = 0;
} else {
if (!isInfrastructureObject) {
_portConnectionFailed = _portConnectionFailed + 1;
}
}
}
} else {
if (!isInfrastructureObject) {
pingFailed = pingFailed + 1;
}
}
NSLog(#"%lu",(unsigned long)i);
}
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
// does have a valid IP address
-(void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address {
[self.ping sendPingWithData:nil];
}
// device did send packet
-(void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber address:(nonnull NSString *)address {
// NSLog(#"Sending 64 bytes to %#: icmp_seq=%hu ttl=64", address, sequenceNumber);
pingTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:PING_TIMEOUT target:self selector:#selector(timerFired) userInfo:nil repeats:NO];
_dateRef = [NSDate date];
NSLog(#"Packet Sent to: %#", address);
}
// timeout timer, fires when a ping back is never recieved
-(void)timerFired {
NSLog(#"timeout timer fired");
[pingTimeoutTimer invalidate];
//self.pingableObjectAddress = nil;
self.pingTimeoutTimer = nil;
self.ping = nil;
}
// failed to send packet error handler
-(void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber error:(NSError *)error {
[self.pingTimeoutTimer invalidate];
pingTimeoutTimer = nil;
self.ping = nil;
if (error) {
NSLog(#"Ping Error: %#", error);
}
}
// device did recieve unexpected ping packet, handle this when this happens
-(void)simplePing:(SimplePing *)pinger didReceiveUnexpectedPacket:(NSData *)packet {}
// did recieve response packet
-(void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber address:(NSString *)address {
[pingTimeoutTimer invalidate];
NSDate *end = [NSDate date];
double latency = [end timeIntervalSinceDate:_dateRef] *1000;
self.deviceLatencyString = [NSString stringWithFormat:#"%.f", latency];
self.pingTimeoutTimer = nil;
// NSLog(#"64 bytes sent to %#: icmp_seq=%hu ttl=64 time = %f ms", address, sequenceNumber, _latency);
self.pingableObjectAddress = address;
// NSLog(#"%#", pingableObjectAddress);
NSLog(#"did recieve packet from: %#", address);
self.ping = nil;
}
// device failed to ping for failed reason
-(void)simplePing:(SimplePing *)pinger didFailWithError:(NSError *)error {
NSLog(#"Failed With Error %#", error);
assert(pinger == self.ping);
[self.ping stop];
self.ping = nil;
}

Adobe AIR iOS ANE NSStream delegate not called

I have successfully created connection to Apple MFi printer, but I'm failed to have NSOutputStream to write to the printer because delegate did not called.
Here is my LibPrint.h:-
#import <Foundation/Foundation.h>
#import <ExternalAccessory/ExternalAccessory.h>
#import "FlashRuntimeExtensions.h"
#interface LibPrint : NSObject <NSStreamDelegate>
- (void)printR;
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent;
#end
// C interface
FREObject fncPrintR(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]);
LibPrint.m:-
#import "LibPrint.h"
#interface LibPrint ()
#property (nonatomic, strong) EASession *easPrinter;
#property (nonatomic, strong) NSData *datPrintData;
#end
#implementation LibPrint
FREContext eventContext;
LibPrint *AirInAppRefToSelf;
#pragma mark - NSObject
-(id)init
{
self = [super init];
if (self)
{
AirInAppRefToSelf = self;
self.easPrinter = nil;
self.datPrintData = nil;
}
return self;
}
-(void)dealloc
{
self.easPrinter = nil;
self.datPrintData = nil;
AirInAppRefToSelf = nil;
}
#pragma mark - ANE setup
void LibPrintExtContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet)
{
*numFunctionsToTest = 1;
FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * *numFunctionsToTest);
func[0].name = (const uint8_t*) "printR";
func[0].functionData = NULL;
func[0].function = &fncPrintR;
*functionsToSet = func;
eventContext = ctx;
if ((LibPrint*) AirInAppRefToSelf == nil)
{
AirInAppRefToSelf = [[LibPrint alloc] init];
}
}
void LibPrintContextFinalizer(FREContext ctx) { }
void LibPrintExtensionInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet)
{
*extDataToSet = NULL;
*ctxInitializerToSet = &LibPrintExtContextInitializer;
*ctxFinalizerToSet = &LibPrintContextFinalizer;
}
void LibPrintFinalizer(void* extData) { }
#pragma mark - C interface
FREObject fncPrintR(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
FREObject result = NULL;
if ([AirInAppRefToSelf datPrintData] != nil) {
[AirInAppRefToSelf setDatPrintData:nil];
}
// Retrieve message
NSData *ldatPrintData = toNSDataByteArray(argv[0]);
[AirInAppRefToSelf setDatPrintData:ldatPrintData];
[(LibPrint*) AirInAppRefToSelf printR];
return result;
}
- (void)printR
{
BOOL lblnConnected = false;
BOOL lblnFound = false;
NSArray *accessories = [EAAccessoryManager sharedAccessoryManager].connectedAccessories;
for (EAAccessory *accessory in accessories)
{
if (accessory.connected)
{
lblnConnected = true;
for (NSString *protocol in accessory.protocolStrings)
{
if ([protocol isEqualToString:#"jp.star-m.starpro"])
{
lblnFound = true;
[self setEasPrinter:[[EASession alloc] initWithAccessory:accessory forProtocol:protocol]];
[[self easPrinter].outputStream setDelegate:self];
[[self easPrinter].outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[self easPrinter].outputStream open];
}
}
}
}
FREDispatchStatusEventAsync(eventContext, (uint8_t*)"DEBUG_DATA", (uint8_t*) [[NSString stringWithFormat: #"connected: %s", lblnConnected ? "true" : "false"] UTF8String]);
FREDispatchStatusEventAsync(eventContext, (uint8_t*)"DEBUG_DATA", (uint8_t*) [[NSString stringWithFormat: #"found: %s", lblnFound ? "true" : "false"] UTF8String]);
}
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
FREDispatchStatusEventAsync(eventContext, (uint8_t*)"DEBUG_DATA", (uint8_t*) [#"NSStreamDelegate" UTF8String]);
switch (streamEvent)
{
case NSStreamEventNone:
{
break;
}
case NSStreamEventOpenCompleted:
{
break;
}
case NSStreamEventHasBytesAvailable:
{
break;
}
case NSStreamEventHasSpaceAvailable:
{
FREDispatchStatusEventAsync(eventContext, (uint8_t*)"DEBUG_DATA", (uint8_t*) [#"NSStreamEventHasSpaceAvailable" UTF8String]);
NSInteger len = [[self easPrinter].outputStream write:[[self datPrintData] bytes] maxLength:[[self datPrintData] length]];
FREDispatchStatusEventAsync(eventContext, (uint8_t*)"DEBUG_DATA", (uint8_t*) [[NSString stringWithFormat: #"data len: %ld, returned len: %ld", [[self datPrintData] length], len] UTF8String]);
break;
}
case NSStreamEventErrorOccurred:
{
break;
}
case NSStreamEventEndEncountered:
{
break;
}
}
}
NSData *toNSDataByteArray(FREObject *ba)
{
FREByteArray byteArray;
FREAcquireByteArray(ba, &byteArray);
NSData *d = [NSData dataWithBytes:(void *)byteArray.bytes length:(NSUInteger)byteArray.length];
FREReleaseByteArray(ba);
return d;
}
#end
I have printer connected good, but the delegate method [- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent] never run. I guess maybe
the currentRunLoop issue, I tried to change it to mainRunLoop, but still no clue. Please help! Thx in advanced.
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
Instead of using [NSRunLoop currentRunLoop] I changed it to [NSRunLoop mainRunLoop].
set inputStrean in the same way:
[[self easPrinter].inputStream setDelegate:self];
[[self easPrinter].inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[[self easPrinter].inputStream open];

App runs if I activate breakpoints, fails otherwise

I have an app that uses sockets to send login information to a server and receives a response in form of a contact list. This is the main method for processing responses from server:
-(void) stream:(NSStream*)theStream handleEvent:(NSStreamEvent)streamEvent {
switch(streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(#"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
if(theStream == inputStream) {
uint8_t buffer[8196];
int len;
while([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if(len>0) {
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSUTF8StringEncoding];
if(output != nil) {
NSLog(#"server said: %#", output);
id jsonOutput = [self createJsonFromString:output];
if([[jsonOutput objectForKey:#"msg_type"] isEqualToString:#"LoginResponse"])
{
[self sendMessage:[self createAddressBookRequestJsonData]];
} else if ([[jsonOutput objectForKey:#"msg_type"] isEqualToString:#"GetAddressBookResponse"])
{
id contactList = [jsonOutput objectForKey:#"contact_list"];
for(id contactListItem in contactList)
{
XYZAddressBookEntry *newEntry = [[XYZAddressBookEntry alloc] init];
newEntry.firstName = [contactListItem objectForKey:#"FirstName"];
newEntry.lastName = [contactListItem objectForKey:#"LastName"];
newEntry.displayName = [contactListItem objectForKey:#"DisplayName"];
newEntry.softphoneNumber = [contactListItem objectForKey:#"SoftphoneNumber"];
newEntry.homeNumber = [contactListItem objectForKey:#"HomeNumber"];
newEntry.mobileNumber = [contactListItem objectForKey:#"MobileNumber"];
newEntry.businessNumber = [contactListItem objectForKey:#"BusinessNumber"];
newEntry.name = [contactListItem objectForKey:#"Name"];
newEntry.phoneAddress = [contactListItem objectForKey:#"PhoneAddress"];
[self.entryList addObject:newEntry];
}
[self.tableView reloadData];
}
}
}
}
}
break;
case NSStreamEventHasSpaceAvailable:
break;
case NSStreamEventEndEncountered:
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
break;
case NSStreamEventErrorOccurred:
NSLog(#"Can not connect to the host!");
break;
default:
NSLog(#"Unknown event:");
} }
I always get a correct output in my log, so everything goes smooth, but if I don't set a breakpoint right after NSLog(#"server said: %#", output), it will not enter the if else code block. What am I missing?
By the way, I'm a newbie to this, started using objective-c just 2 weeks ago.

Unable to establish a Socket connection through IOS

Im writing an IOS application for my first time. It is supposed to connect to a static IP device, and send certain "known" commands to it. But for some reason Im unable to establish a connection.
Bellow are the functions I use to establish my connection, and write data to the port.
-(void)connection//:(NSString *)serviceName forIpAddress:(NSString *)ipAddress forPort:(NSString *)portNo
{
if(input && output)
[self close];
NSString *urlString = [NSString stringWithFormat:#"%.%.%.%", "192.168.3.120"];
NSURL *website = [NSURL URLWithString:urlString];
if (!website) {
NSLog(#"%# is not a valid URL", website);
}
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)[website host], 43, &readStream, &writeStream);
CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
NSInputStream *input = (__bridge NSInputStream *)readStream;
NSOutputStream *output= (__bridge NSOutputStream *)writeStream;
}
- (void)open {
[input setDelegate:self];
[output setDelegate:self];
[input scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[output scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode]; [input open];
[output open];
}
-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
NSString *event;
switch (streamEvent)
{
case NSStreamEventNone:
event = #"NSStreamEventNone";
break;
case NSStreamEventOpenCompleted:
event = #"NSStreamEventOpenCompleted";
break;
case NSStreamEventHasBytesAvailable:
event = #"NSStreamEventHasBytesAvailable";
if (theStream == input)
{
uint8_t buffer[1024];
NSInteger len;
while ([input hasBytesAvailable])
{
len = [input read:buffer maxLength:1024];
if (len > 0)
{
NSMutableString *output = [[NSMutableString alloc]initWithBytes:buffer length:len encoding:NSUTF8StringEncoding]; NSLog(#"Received data--------------------%#", output);
}
}
}
break;
case NSStreamEventHasSpaceAvailable:
event = #"NSStreamEventHasSpaceAvailable";
break;
case NSStreamEventErrorOccurred:
event = #"NSStreamEventErrorOccurred";
//[self close];
break;
case NSStreamEventEndEncountered:
break; default:
event = #"NSStreamEventEndEncountered";
//[self close];
event = #"Unknown"; break;
}
NSLog(#"event------%#",event);
}
- (void)close
{
[input close];
[output close];
[input removeFromRunLoop:[NSRunLoop currentRunLoop]forMode:NSDefaultRunLoopMode];
[output removeFromRunLoop:[NSRunLoop currentRunLoop]forMode:NSDefaultRunLoopMode];
[input setDelegate:nil];
[output setDelegate:nil];
input = nil;
output = nil;
}
- (void)dataSending:(NSString*)data
{
if(output)
{
if(![output hasSpaceAvailable])
return;
NSData *_data=[data dataUsingEncoding:NSUTF8StringEncoding];
NSInteger data_len = [_data length];
uint8_t *readBytes = (uint8_t *)[_data bytes];
int byteIndex=0;
unsigned int len=0;
while (TRUE)
{
len = ((data_len - byteIndex >= 40960) ? 40960 : (data_len-byteIndex));
if(len==0)
break;
uint8_t buf[len];
(void)memcpy(buf, readBytes, len);
len = [output write:(const uint8_t *)buf maxLength:len];
byteIndex += len;
readBytes += len;
}
NSLog(#"Sent data----------------------%#",data);
}
}
I do call the mentioned functions through that code as a test, and nothing happens
- (IBAction)pumpchange:(id)sender {
[self connection];
[self open];
if ([self.pump backgroundImageForState:(UIControlStateNormal)]==[UIImage imageNamed:#"PumpOff.png"])
{
[self.pump setBackgroundImage:[UIImage imageNamed:#"PumpOn.png"] forState:(UIControlStateNormal)];
[self dataSending:#"pump_on"];
}
else //if ([self.pump backgroundImageForState:(UIControlStateNormal)]==[UIImage imageNamed:#"PumpOn.png"])
{
[self.pump setBackgroundImage:[UIImage imageNamed:#"PumpOff.png"] forState:(UIControlStateNormal)];
[self dataSending:#"pump_off"];
}
[self close];
}
Thanks in Advance
There seem to be some misunderstandings how format strings work, because
NSString *urlString = [NSString stringWithFormat:#"%.%.%.%", "192.168.3.120"];
just gives you the string #"...". Perhaps you meant
NSString *urlString = [NSString stringWithFormat:#"%d.%d.%d.%d", 192, 168, 3, 120];
or
NSString *urlString = [NSString stringWithFormat:#"%s", "192.168.3.120"];
But you don't need a format string at all:
NSString *urlString = #"192.168.3.120";

How to stop AudioQueue?

i am using text to speech, starting audio works fine, but i cant stop it. here is how i do start audio:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) {
[[self view] setNeedsDisplay];
[self synthesizeInBackground];
[queue waitUntilAllOperationsAreFinished];
[self setIsSpeaking: false];
[[self view] setNeedsDisplay];
});
synthesizeInBackground
- (void) synthesizeInBackground {
XLog(#"-----------------------------------entered");
queue = [[NSOperationQueue alloc] init];
XLog(#"queue: %#", queue);
operation = [[NSInvocationOperation alloc] initWithTarget:self selector:#selector(synthesize) object:nil];
XLog(#"operation: %#", operation);
[queue addOperation: operation];
}
synthesize
- (void)synthesize {
XLog(#"-----------------------------------entered");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
callback_userdata userdata;
NSError *error = nil;
self.paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
self.documentsDirectory = [self.paths objectAtIndex:0];
self.path = [self.documentsDirectory stringByAppendingPathComponent:#"readSearchresults.txt"];
IvonaStreamer *streamer = [[IvonaStreamer alloc] initWithVoice:voice withText:[NSString stringWithContentsOfFile:self.path encoding:NSUTF8StringEncoding error:&error] atSpeed:[NSNumber numberWithFloat:-1]];
//IvonaStreamer *streamer = [[IvonaStreamer alloc] initWithVoice:voice withText:#"Dies ist ein Testtext." atSpeed:[NSNumber numberWithFloat:-1]];
if (streamer == nil) {
XLog(#"Cannot start streamer");
[self setTtsError: #"Cannot start streamer"];
return;
}
userdata.speak = &(self->isSpeaking);
userdata.streamer = streamer;
#define NUM_BUFFERS 3
#define BUFFER_SIZE 22050
OSStatus err;
AudioQueueRef audioQueue;
//XLog(#"audioQueue: %d", audioQueue);
XLog(#"[voice getSampleRate]: %i", [voice getSampleRate]);
AudioStreamBasicDescription deviceFormat;
deviceFormat.mSampleRate = [voice getSampleRate];
deviceFormat.mFormatID = kAudioFormatLinearPCM;
deviceFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
deviceFormat.mBytesPerPacket = 2;
deviceFormat.mFramesPerPacket = 1;
deviceFormat.mBytesPerFrame = 2;
deviceFormat.mChannelsPerFrame = 1;
deviceFormat.mBitsPerChannel = 16;
deviceFormat.mReserved = 0;
XLog(#"deviceFormat.mSampleRate: %f", deviceFormat.mSampleRate);
/*
XLog(#"deviceFormat.mSampleRate: %f", deviceFormat.mSampleRate);
XLog(#"deviceFormat.mFormatID: %lu", deviceFormat.mFormatID);
XLog(#"deviceFormat.mFormatFlags: %lu", deviceFormat.mFormatFlags);
XLog(#"deviceFormat.mBytesPerPacket %lu", deviceFormat.mBytesPerPacket);
XLog(#"deviceFormat.mFramesPerPacket %lu", deviceFormat.mFramesPerPacket);
XLog(#"deviceFormat.mBytesPerFrame %lu", deviceFormat.mBytesPerFrame);
XLog(#"deviceFormat.mChannelsPerFrame %lu", deviceFormat.mChannelsPerFrame);
XLog(#"deviceFormat.mBitsPerChannel %lu", deviceFormat.mBitsPerChannel);
XLog(#"deviceFormat.mReserved %lu", deviceFormat.mReserved);
*/
err = AudioQueueNewOutput(&deviceFormat,
AudioQueueCallback,
&userdata,
CFRunLoopGetCurrent(),
kCFRunLoopCommonModes,
0,
&audioQueue);
if (err != noErr) {
XLog(#"Cannot create audio output");
[self setTtsError: #"Cannot create audio output"];
[streamer stop];
return;
}
AudioQueueAddPropertyListener(audioQueue, kAudioQueueProperty_IsRunning,
AudioQueuePropertyListener, NULL);
for (int i = 0; i < NUM_BUFFERS; i++) {
AudioQueueBufferRef buffer;
err = AudioQueueAllocateBuffer(audioQueue, BUFFER_SIZE, &buffer);
if (err != noErr) {
XLog(#"Cannot allocate audio buffer");
[self setTtsError: #"Cannot allocate audio buffer"];
[streamer stop];
return;
}
AudioQueueCallback(&userdata, audioQueue, buffer);
}
err = AudioQueueStart(audioQueue, NULL);
if (err != noErr) {
XLog(#"Cannot start audio");
[self setTtsError: #"Cannot start audio"];
[streamer stop];
return;
}
CFRunLoopRun();
[streamer stop];
[pool release];
}
AudioQueueCallback
void AudioQueueCallback(void *userData, AudioQueueRef audioQueue,
AudioQueueBufferRef buffer)
{
//XLog(#"-----------------------------------entered");
void *data = buffer->mAudioData;
UInt32 num_bytes = buffer->mAudioDataBytesCapacity;
//XLog(#"num_bytes: %lu", num_bytes);
UInt32 to_write = num_bytes / sizeof(short);
//XLog(#"to_write: %lu", to_write);
NSInteger num_samples;
//XLog(#"num_samples: %i", num_samples);
IvonaStreamer *streamer = ((callback_userdata*) userData)->streamer;
bool *enabled = ((callback_userdata*) userData)->speak;
//XLog(#"streamer.getWarnings: %#", streamer.getWarnings);
if(!*enabled) {
XLog(#"!*enabled");
AudioQueueStop(audioQueue, false);
}
num_samples = [streamer synthSamples:to_write toCArray:data];
//XLog(#"num_samples: %i", num_samples);
if (num_samples > 0) {
//XLog(#"num_samples > 0");
buffer->mAudioDataByteSize = num_samples * sizeof(short);
AudioQueueEnqueueBuffer(audioQueue, buffer, 0, NULL);
} else {
//XLog(#"! (num_samples > 0)");
AudioQueueStop(audioQueue, false);
}
}
AudioQueuePropertyListener
void AudioQueuePropertyListener(void *userData, AudioQueueRef audioQueue,
AudioQueuePropertyID id)
{
XLog(#"-----------------------------------entered");
UInt32 isRunning, size = sizeof(isRunning);
AudioQueueGetProperty(audioQueue, kAudioQueueProperty_IsRunning, &isRunning, &size);
if (isRunning == 0) {
XLog(#"isRunning == 0");
CFRunLoopStop(CFRunLoopGetCurrent());
}
if (isRunning != 0) {
XLog(#"nicht null#######");
}
}
I try to stop in other method(UIAlertView delegate method):
if (alertView.tag == 997) {
if (buttonIndex == 0) {
XLog(#"vorlesen abbrechen geklickt.");
[queue cancelAllOperations];
AudioQueueRef audioQueue;
//AudioQueueDispose(audioQueue, false);
AudioQueueStop(audioQueue, false);
}
i am cancelling all operations and calling AudioQueueDispose, also tried with AudioQueueStop, but nothing works here.
So my question is, HOW can i stop audio here?
AudioQueueStop should work and be sufficient. From Apples Documentation, AudioQueueReset is called from AudioQueueStop.
AudioQueueDispose is a bit too much if you want to start it again later.
I believe that you need to call AudioQueueReset before you call AudioQueueStop.
AudioQueueReset (audioQueue);
AudioQueueStop (audioQueue, YES);
AudioQueueDispose (audioQueue, YES);

Resources