diff --git a/QCIRCReceiver.xcodeproj/project.pbxproj b/QCIRCReceiver.xcodeproj/project.pbxproj index 083d0ab..1d7fefb 100644 --- a/QCIRCReceiver.xcodeproj/project.pbxproj +++ b/QCIRCReceiver.xcodeproj/project.pbxproj @@ -155,11 +155,12 @@ B611D9821CC39ED700D3BA8C /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0730; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = MacPietsApps.net; TargetAttributes = { B611D98A1CC39ED700D3BA8C = { CreatedOnToolsVersion = 7.3; + ProvisioningStyle = Automatic; }; B677B8111D4200BD00587500 = { CreatedOnToolsVersion = 7.3.1; @@ -168,10 +169,11 @@ }; buildConfigurationList = B611D9851CC39ED700D3BA8C /* Build configuration list for PBXProject "QCIRCReceiver" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = B611D9811CC39ED700D3BA8C; productRefGroup = B611D98C1CC39ED700D3BA8C /* Products */; @@ -228,18 +230,31 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = x86_64; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -272,18 +287,31 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = x86_64; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -309,10 +337,12 @@ isa = XCBuildConfiguration; baseConfigurationReference = B677B80A1D41FDF700587500 /* BuildNumber.xcconfig */; buildSettings = { - CODE_SIGN_IDENTITY = "Mac Developer"; + ARCHS = x86_64; + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = QCIRCReceiver/Info.plist; INSTALL_PATH = "$(HOME)/Library/Graphics/Quartz Composer Plug-Ins"; + MACOSX_DEPLOYMENT_TARGET = 10.15.2; PRODUCT_BUNDLE_IDENTIFIER = net.macpietsapps.QCIRCReceiver; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -324,11 +354,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = B677B80A1D41FDF700587500 /* BuildNumber.xcconfig */; buildSettings = { - CODE_SIGN_IDENTITY = "Mac Developer"; + ARCHS = x86_64; + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; INFOPLIST_FILE = QCIRCReceiver/Info.plist; INSTALL_PATH = "$(HOME)/Library/Graphics/Quartz Composer Plug-Ins"; + MACOSX_DEPLOYMENT_TARGET = 10.15.2; PRODUCT_BUNDLE_IDENTIFIER = net.macpietsapps.QCIRCReceiver; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -378,6 +410,7 @@ B677B8141D4200BD00587500 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/QCIRCReceiver.xcodeproj/xcshareddata/xcschemes/QCIRCReceiver.xcscheme b/QCIRCReceiver.xcodeproj/xcshareddata/xcschemes/QCIRCReceiver.xcscheme index c8a2387..5812acc 100644 --- a/QCIRCReceiver.xcodeproj/xcshareddata/xcschemes/QCIRCReceiver.xcscheme +++ b/QCIRCReceiver.xcodeproj/xcshareddata/xcschemes/QCIRCReceiver.xcscheme @@ -1,6 +1,6 @@ - - - - +typedef NS_ENUM(NSUInteger, IRCConnectionState) { + IRCConnectionStateDisconnected = 0, + IRCConnectionStateConnecting = 1, + IRCConnectionStateConnected = 2, + IRCConnectionStateReceivingData = 3, + IRCConnectionStateConnectionError = 99, + +}; + @class IRCMessage; @interface IRCConnection : NSObject @@ -54,5 +63,14 @@ typedef void (^IRCConnectionMessageCallback)(IRCMessage * _Nonnull message); */ @property (nonatomic, copy) IRCConnectionMessageCallback _Nullable messageCallback; +/*! + * @brief Stores the current connection state + */ +@property (nonatomic, assign, readonly) IRCConnectionState connectionState; + +/*! + * @brief Stores the last connection error + */ +@property (atomic, strong, readonly) NSString * _Nullable connectionError; @end diff --git a/QCIRCReceiver/IRCConnection.m b/QCIRCReceiver/IRCConnection.m index 50cc73a..2c11316 100644 --- a/QCIRCReceiver/IRCConnection.m +++ b/QCIRCReceiver/IRCConnection.m @@ -16,6 +16,9 @@ @interface IRCConnection () @property (nonatomic, strong) IRCAsyncSocket *socket; @property (nonatomic, strong) NSMutableArray *messageQueue; +@property (nonatomic, assign) IRCConnectionState connectionState; +@property (atomic, strong) NSString * _Nullable connectionError; + @end @implementation IRCConnection @@ -26,6 +29,8 @@ - (instancetype _Nonnull)initWithServer:(NSString * _Nonnull)server port:(NSInte if (self) { self.messageQueue = [NSMutableArray array]; + + self.connectionState = IRCConnectionStateDisconnected; IRCAsyncSocket *socket = [[IRCAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; @@ -33,10 +38,15 @@ - (instancetype _Nonnull)initWithServer:(NSString * _Nonnull)server port:(NSInte [socket connectToHost:server onPort:port error:&error]; if (error) { + self.connectionState = IRCConnectionStateConnectionError; + self.connectionError = error.localizedDescription; + NSLog(@"Error while connecting to server: %@", error); } else { + self.connectionState = IRCConnectionStateConnecting; + self.socket = socket; if (password) @@ -82,12 +92,16 @@ - (BOOL)connected - (void)socket:(IRCAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port { + self.connectionState = IRCConnectionStateConnected; + [self _workMessageQueue]; [sock readDataToData:IRCAsyncSocket.CRLFData withTimeout:-1 tag:0]; } - (void)socket:(IRCAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { + self.connectionState = IRCConnectionStateReceivingData; + //Parse message IRCMessage *message = [[IRCMessage alloc] initWithData:data]; @@ -109,6 +123,16 @@ - (void)socket:(IRCAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)t - (void)socketDidDisconnect:(IRCAsyncSocket *)sock withError:(NSError *)err { + if(err) + { + self.connectionState = IRCConnectionStateConnectionError; + self.connectionError = err.localizedDescription; + } + else + { + self.connectionState = IRCConnectionStateDisconnected; + } + self.socket = nil; [self.messageQueue removeAllObjects]; } diff --git a/QCIRCReceiver/QCIRCReceiverPlugIn.h b/QCIRCReceiver/QCIRCReceiverPlugIn.h index 17d2688..fe4a9e2 100644 --- a/QCIRCReceiver/QCIRCReceiverPlugIn.h +++ b/QCIRCReceiver/QCIRCReceiverPlugIn.h @@ -16,9 +16,13 @@ @property (copy) NSString *inputNickname; @property (copy) NSString *inputPassword; @property (copy) NSString *inputChannel; +@property BOOL inputReconnect; //Outputs @property (copy) NSArray *outputMessages; +@property NSUInteger outputConnectionState; +@property NSString *outputConnectionError; + @property BOOL outputConnected; @end diff --git a/QCIRCReceiver/QCIRCReceiverPlugIn.m b/QCIRCReceiver/QCIRCReceiverPlugIn.m index 7d866d7..4eba572 100644 --- a/QCIRCReceiver/QCIRCReceiverPlugIn.m +++ b/QCIRCReceiver/QCIRCReceiverPlugIn.m @@ -31,8 +31,8 @@ @interface QCIRCReceiverPlugIn () @implementation QCIRCReceiverPlugIn -@dynamic inputServer, inputPort, inputNickname, inputPassword, inputChannel; -@dynamic outputMessages, outputConnected; +@dynamic inputServer, inputPort, inputNickname, inputPassword, inputChannel, inputReconnect; +@dynamic outputMessages, outputConnected, outputConnectionState, outputConnectionError; + (NSDictionary *)attributes { @@ -45,7 +45,7 @@ + (NSDictionary *)attributesForPropertyPortWithKey:(NSString *)key if ([key isEqualToString:@"inputServer"]) { return @{QCPortAttributeNameKey: @"Server", - QCPortAttributeDefaultValueKey: @"irc.chat.twitch.tv"}; + QCPortAttributeDefaultValueKey: @""}; } else if ([key isEqualToString:@"inputPort"]) { @@ -65,7 +65,12 @@ + (NSDictionary *)attributesForPropertyPortWithKey:(NSString *)key else if ([key isEqualToString:@"inputChannel"]) { return @{QCPortAttributeNameKey: @"IRC Channel", - QCPortAttributeDefaultValueKey: @"#macpiets"}; + QCPortAttributeDefaultValueKey: @""}; + } + else if ([key isEqualToString:@"inputReconnect"]) + { + return @{QCPortAttributeNameKey: @"Reconnect", + QCPortAttributeDefaultValueKey: @(NO)}; } else if ([key isEqualToString:@"outputMessages"]) { @@ -75,7 +80,15 @@ + (NSDictionary *)attributesForPropertyPortWithKey:(NSString *)key { return @{QCPortAttributeNameKey: @"Connected"}; } - + else if ([key isEqualToString:@"outputConnectionState"]) + { + return @{QCPortAttributeNameKey: @"Connection State"}; + } + else if ([key isEqualToString:@"outputConnectionError"]) + { + return @{QCPortAttributeNameKey: @"Connection Error"}; + } + return nil; } @@ -111,7 +124,8 @@ - (BOOL)execute:(id )context atTime:(NSTimeInterval)time withAr ![self.oldServer isEqualToString:self.inputServer] || ![self.oldNickname isEqualToString:self.inputNickname] || ![self.oldChannel isEqualToString:self.inputChannel] || - ![self.oldPassword isEqualToString:self.inputPassword]) + ![self.oldPassword isEqualToString:self.inputPassword] || + self.inputReconnect) { [self disconnect]; [self connect]; @@ -128,6 +142,12 @@ - (BOOL)execute:(id )context atTime:(NSTimeInterval)time withAr self.outputMessages = @[]; } + if(self.connection) + { + self.outputConnectionState = self.connection.connectionState; + self.outputConnectionError = self.connection.connectionError; + } + return YES; } @@ -162,7 +182,6 @@ - (void)connect IRCConnection *connection = [[IRCConnection alloc] initWithServer:self.inputServer port:self.inputPort serverPassword:password]; connection.nickname = self.inputNickname; - [connection joinChannel:self.inputChannel]; connection.messageCallback = ^void(IRCMessage * _Nonnull message) { //Append message to array @@ -180,7 +199,9 @@ - (void)connect [self.messages removeObjectAtIndex:0]; } }; - + + [connection joinChannel:self.inputChannel]; + self.connection = connection; self.oldPort = self.inputPort; self.oldServer = self.inputServer;