From 1f2230c2cbb4fd3c0debd7105a7fdbc0e07572c9 Mon Sep 17 00:00:00 2001 From: GRMrGecko Date: Tue, 28 Jan 2014 20:39:07 -0600 Subject: [PATCH] Added Firmware Code and Mac App to make the Rotary Gecko a juke box. This is for my presentation at Security B-Sides Huntsville. --- Code/Firmware/Firmware.ino | 15 +- .../Rotary Player.xcodeproj/project.pbxproj | 326 + .../contents.xcworkspacedata | 7 + .../xcshareddata/Rotary Player.xccheckout | 41 + .../UserInterfaceState.xcuserstate | Bin 0 -> 19455 bytes .../xcschemes/Rotary Player.xcscheme | 86 + .../xcschemes/xcschememanagement.plist | 22 + .../Rotary Player/MGMAppDelegate.h | 34 + .../Rotary Player/MGMAppDelegate.m | 144 + Code/Rotary_Player/Rotary Player/MGMSerial.h | 70 + Code/Rotary_Player/Rotary Player/MGMSerial.m | 348 + Code/Rotary_Player/Rotary Player/MGMSound.h | 65 + Code/Rotary_Player/Rotary Player/MGMSound.m | 109 + .../Rotary Player/Rotary Player-Info.plist | 34 + .../Rotary Player/Rotary Player-Prefix.pch | 7 + .../Rotary Player/en.lproj/Credits.rtf | 29 + .../Rotary Player/en.lproj/InfoPlist.strings | 2 + .../Rotary Player/en.lproj/MainMenu.xib | 6531 +++++++++++++++++ Code/Rotary_Player/Rotary Player/main.m | 14 + .../Rotary_Player_Firmware.ino | 116 + Readme.md | 6 +- 21 files changed, 8002 insertions(+), 4 deletions(-) create mode 100644 Code/Rotary_Player/Rotary Player.xcodeproj/project.pbxproj create mode 100644 Code/Rotary_Player/Rotary Player.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Code/Rotary_Player/Rotary Player.xcodeproj/project.xcworkspace/xcshareddata/Rotary Player.xccheckout create mode 100644 Code/Rotary_Player/Rotary Player.xcodeproj/project.xcworkspace/xcuserdata/grmrgecko.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 Code/Rotary_Player/Rotary Player.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/Rotary Player.xcscheme create mode 100644 Code/Rotary_Player/Rotary Player.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 Code/Rotary_Player/Rotary Player/MGMAppDelegate.h create mode 100644 Code/Rotary_Player/Rotary Player/MGMAppDelegate.m create mode 100644 Code/Rotary_Player/Rotary Player/MGMSerial.h create mode 100644 Code/Rotary_Player/Rotary Player/MGMSerial.m create mode 100644 Code/Rotary_Player/Rotary Player/MGMSound.h create mode 100644 Code/Rotary_Player/Rotary Player/MGMSound.m create mode 100644 Code/Rotary_Player/Rotary Player/Rotary Player-Info.plist create mode 100644 Code/Rotary_Player/Rotary Player/Rotary Player-Prefix.pch create mode 100644 Code/Rotary_Player/Rotary Player/en.lproj/Credits.rtf create mode 100644 Code/Rotary_Player/Rotary Player/en.lproj/InfoPlist.strings create mode 100644 Code/Rotary_Player/Rotary Player/en.lproj/MainMenu.xib create mode 100644 Code/Rotary_Player/Rotary Player/main.m create mode 100644 Code/Rotary_Player_Firmware/Rotary_Player_Firmware.ino diff --git a/Code/Firmware/Firmware.ino b/Code/Firmware/Firmware.ino index 278e3be..02b3e18 100644 --- a/Code/Firmware/Firmware.ino +++ b/Code/Firmware/Firmware.ino @@ -11,6 +11,7 @@ SoftwareSerial btSerial(2,3); // RX,TX int eventPin = 4; int eventValue = 1; int commandPin = 5; +int commandToggle = 0; int hookPin = 6; int hookValue = 1; @@ -114,6 +115,7 @@ void setup() { pinMode(eventPin, INPUT); pinMode(commandPin, OUTPUT); digitalWrite(commandPin, LOW); + commandToggle = 1; pinMode(hookPin, INPUT_PULLUP); pinMode(startPosPin, INPUT_PULLUP); @@ -129,8 +131,9 @@ void setup() { void loop() { if (btSerial.available()) Serial.write(btSerial.read()); - if (Serial.available()) + if (Serial.available()) { btSerial.write(Serial.read()); + } // Gather information from the pins to work with. int event = digitalRead(eventPin); @@ -212,6 +215,16 @@ void loop() { } else if (hook==0) { if (dialedNumber==3) { serialSendVerify("AP\r", "AOK"); + } else if (dialedNumber==9) { + if (commandToggle==1) { + Serial.print("Command Mode Off\n"); + digitalWrite(commandPin, HIGH); + commandToggle = 0; + } else { + Serial.print("Command Mode On\n"); + digitalWrite(commandPin, LOW); + commandToggle = 1; + } } } else if (hook==1 && state!=outgoingCall && state!=incomingCall && state!=activeCallInProgress && state!=threeWayWaiting && state!=threeWayHold && state!=threeWay && state!=incomingCallHold && state!=activeCall) { phoneNumber[numberCount] = dialedNumber; diff --git a/Code/Rotary_Player/Rotary Player.xcodeproj/project.pbxproj b/Code/Rotary_Player/Rotary Player.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e0ee86a --- /dev/null +++ b/Code/Rotary_Player/Rotary Player.xcodeproj/project.pbxproj @@ -0,0 +1,326 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 2A7C81F2189815CF00094EF7 /* MGMSound.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A7C81F1189815CF00094EF7 /* MGMSound.m */; }; + 2AAEF920189365CB00E05D4F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AAEF91F189365CB00E05D4F /* Cocoa.framework */; }; + 2AAEF92A189365CB00E05D4F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2AAEF928189365CB00E05D4F /* InfoPlist.strings */; }; + 2AAEF92C189365CB00E05D4F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AAEF92B189365CB00E05D4F /* main.m */; }; + 2AAEF930189365CB00E05D4F /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 2AAEF92E189365CB00E05D4F /* Credits.rtf */; }; + 2AAEF933189365CB00E05D4F /* MGMAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AAEF932189365CB00E05D4F /* MGMAppDelegate.m */; }; + 2AAEF936189365CB00E05D4F /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2AAEF934189365CB00E05D4F /* MainMenu.xib */; }; + 2AAEF93E1893660B00E05D4F /* MGMSerial.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AAEF93D1893660B00E05D4F /* MGMSerial.m */; }; + 2AAEF940189367CD00E05D4F /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AAEF93F189367CD00E05D4F /* IOKit.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 2A7C81F0189815CF00094EF7 /* MGMSound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMSound.h; sourceTree = ""; }; + 2A7C81F1189815CF00094EF7 /* MGMSound.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMSound.m; sourceTree = ""; }; + 2AAEF91C189365CB00E05D4F /* Rotary Player.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Rotary Player.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2AAEF91F189365CB00E05D4F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 2AAEF922189365CB00E05D4F /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 2AAEF923189365CB00E05D4F /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 2AAEF924189365CB00E05D4F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 2AAEF927189365CB00E05D4F /* Rotary Player-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Rotary Player-Info.plist"; sourceTree = ""; }; + 2AAEF929189365CB00E05D4F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 2AAEF92B189365CB00E05D4F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 2AAEF92D189365CB00E05D4F /* Rotary Player-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Rotary Player-Prefix.pch"; sourceTree = ""; }; + 2AAEF92F189365CB00E05D4F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; + 2AAEF931189365CB00E05D4F /* MGMAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGMAppDelegate.h; sourceTree = ""; }; + 2AAEF932189365CB00E05D4F /* MGMAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGMAppDelegate.m; sourceTree = ""; }; + 2AAEF935189365CB00E05D4F /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; + 2AAEF93C1893660B00E05D4F /* MGMSerial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMSerial.h; sourceTree = ""; }; + 2AAEF93D1893660B00E05D4F /* MGMSerial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMSerial.m; sourceTree = ""; }; + 2AAEF93F189367CD00E05D4F /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2AAEF919189365CB00E05D4F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2AAEF940189367CD00E05D4F /* IOKit.framework in Frameworks */, + 2AAEF920189365CB00E05D4F /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2AAEF913189365CB00E05D4F = { + isa = PBXGroup; + children = ( + 2AAEF925189365CB00E05D4F /* Rotary Player */, + 2AAEF91E189365CB00E05D4F /* Frameworks */, + 2AAEF91D189365CB00E05D4F /* Products */, + ); + sourceTree = ""; + }; + 2AAEF91D189365CB00E05D4F /* Products */ = { + isa = PBXGroup; + children = ( + 2AAEF91C189365CB00E05D4F /* Rotary Player.app */, + ); + name = Products; + sourceTree = ""; + }; + 2AAEF91E189365CB00E05D4F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2AAEF93F189367CD00E05D4F /* IOKit.framework */, + 2AAEF91F189365CB00E05D4F /* Cocoa.framework */, + 2AAEF921189365CB00E05D4F /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 2AAEF921189365CB00E05D4F /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 2AAEF922189365CB00E05D4F /* AppKit.framework */, + 2AAEF923189365CB00E05D4F /* CoreData.framework */, + 2AAEF924189365CB00E05D4F /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 2AAEF925189365CB00E05D4F /* Rotary Player */ = { + isa = PBXGroup; + children = ( + 2AAEF931189365CB00E05D4F /* MGMAppDelegate.h */, + 2AAEF932189365CB00E05D4F /* MGMAppDelegate.m */, + 2AAEF934189365CB00E05D4F /* MainMenu.xib */, + 2AAEF926189365CB00E05D4F /* Supporting Files */, + 2AAEF93C1893660B00E05D4F /* MGMSerial.h */, + 2AAEF93D1893660B00E05D4F /* MGMSerial.m */, + 2A7C81F0189815CF00094EF7 /* MGMSound.h */, + 2A7C81F1189815CF00094EF7 /* MGMSound.m */, + ); + path = "Rotary Player"; + sourceTree = ""; + }; + 2AAEF926189365CB00E05D4F /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 2AAEF927189365CB00E05D4F /* Rotary Player-Info.plist */, + 2AAEF928189365CB00E05D4F /* InfoPlist.strings */, + 2AAEF92B189365CB00E05D4F /* main.m */, + 2AAEF92D189365CB00E05D4F /* Rotary Player-Prefix.pch */, + 2AAEF92E189365CB00E05D4F /* Credits.rtf */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2AAEF91B189365CB00E05D4F /* Rotary Player */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2AAEF939189365CB00E05D4F /* Build configuration list for PBXNativeTarget "Rotary Player" */; + buildPhases = ( + 2AAEF918189365CB00E05D4F /* Sources */, + 2AAEF919189365CB00E05D4F /* Frameworks */, + 2AAEF91A189365CB00E05D4F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Rotary Player"; + productName = "Rotary Player"; + productReference = 2AAEF91C189365CB00E05D4F /* Rotary Player.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2AAEF914189365CB00E05D4F /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = MGM; + LastUpgradeCheck = 0460; + ORGANIZATIONNAME = "Mr. Gecko's Media"; + }; + buildConfigurationList = 2AAEF917189365CB00E05D4F /* Build configuration list for PBXProject "Rotary Player" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 2AAEF913189365CB00E05D4F; + productRefGroup = 2AAEF91D189365CB00E05D4F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2AAEF91B189365CB00E05D4F /* Rotary Player */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2AAEF91A189365CB00E05D4F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2AAEF92A189365CB00E05D4F /* InfoPlist.strings in Resources */, + 2AAEF930189365CB00E05D4F /* Credits.rtf in Resources */, + 2AAEF936189365CB00E05D4F /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2AAEF918189365CB00E05D4F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2AAEF92C189365CB00E05D4F /* main.m in Sources */, + 2AAEF933189365CB00E05D4F /* MGMAppDelegate.m in Sources */, + 2AAEF93E1893660B00E05D4F /* MGMSerial.m in Sources */, + 2A7C81F2189815CF00094EF7 /* MGMSound.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 2AAEF928189365CB00E05D4F /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 2AAEF929189365CB00E05D4F /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 2AAEF92E189365CB00E05D4F /* Credits.rtf */ = { + isa = PBXVariantGroup; + children = ( + 2AAEF92F189365CB00E05D4F /* en */, + ); + name = Credits.rtf; + sourceTree = ""; + }; + 2AAEF934189365CB00E05D4F /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 2AAEF935189365CB00E05D4F /* en */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 2AAEF937189365CB00E05D4F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 2AAEF938189365CB00E05D4F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + SDKROOT = macosx; + }; + name = Release; + }; + 2AAEF93A189365CB00E05D4F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Rotary Player/Rotary Player-Prefix.pch"; + INFOPLIST_FILE = "Rotary Player/Rotary Player-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 2AAEF93B189365CB00E05D4F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Rotary Player/Rotary Player-Prefix.pch"; + INFOPLIST_FILE = "Rotary Player/Rotary Player-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2AAEF917189365CB00E05D4F /* Build configuration list for PBXProject "Rotary Player" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2AAEF937189365CB00E05D4F /* Debug */, + 2AAEF938189365CB00E05D4F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2AAEF939189365CB00E05D4F /* Build configuration list for PBXNativeTarget "Rotary Player" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2AAEF93A189365CB00E05D4F /* Debug */, + 2AAEF93B189365CB00E05D4F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2AAEF914189365CB00E05D4F /* Project object */; +} diff --git a/Code/Rotary_Player/Rotary Player.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Code/Rotary_Player/Rotary Player.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..0d2f9e7 --- /dev/null +++ b/Code/Rotary_Player/Rotary Player.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Code/Rotary_Player/Rotary Player.xcodeproj/project.xcworkspace/xcshareddata/Rotary Player.xccheckout b/Code/Rotary_Player/Rotary Player.xcodeproj/project.xcworkspace/xcshareddata/Rotary Player.xccheckout new file mode 100644 index 0000000..f6bdfdc --- /dev/null +++ b/Code/Rotary_Player/Rotary Player.xcodeproj/project.xcworkspace/xcshareddata/Rotary Player.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 0E4BB332-BC42-417B-807A-34777077B658 + IDESourceControlProjectName + Rotary Player + IDESourceControlProjectOriginsDictionary + + 9A28687E-3864-4112-AB75-1624B265E471 + ssh://github.com/GRMrGecko/Rotary-Gecko.git + + IDESourceControlProjectPath + Rotary Player/Rotary Player.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 9A28687E-3864-4112-AB75-1624B265E471 + ../../.. + + IDESourceControlProjectURL + ssh://github.com/GRMrGecko/Rotary-Gecko.git + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 9A28687E-3864-4112-AB75-1624B265E471 + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 9A28687E-3864-4112-AB75-1624B265E471 + IDESourceControlWCCName + Rotary-Gecko + + + + diff --git a/Code/Rotary_Player/Rotary Player.xcodeproj/project.xcworkspace/xcuserdata/grmrgecko.xcuserdatad/UserInterfaceState.xcuserstate b/Code/Rotary_Player/Rotary Player.xcodeproj/project.xcworkspace/xcuserdata/grmrgecko.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..452ff0d30d2b560b72ff7e1ab226ce29949f7e37 GIT binary patch literal 19455 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 literal 0 HcmV?d00001 diff --git a/Code/Rotary_Player/Rotary Player.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/Rotary Player.xcscheme b/Code/Rotary_Player/Rotary Player.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/Rotary Player.xcscheme new file mode 100644 index 0000000..04a1eaa --- /dev/null +++ b/Code/Rotary_Player/Rotary Player.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/Rotary Player.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Code/Rotary_Player/Rotary Player.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/xcschememanagement.plist b/Code/Rotary_Player/Rotary Player.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..22ba823 --- /dev/null +++ b/Code/Rotary_Player/Rotary Player.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + Rotary Player.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 2AAEF91B189365CB00E05D4F + + primary + + + + + diff --git a/Code/Rotary_Player/Rotary Player/MGMAppDelegate.h b/Code/Rotary_Player/Rotary Player/MGMAppDelegate.h new file mode 100644 index 0000000..a50dbba --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/MGMAppDelegate.h @@ -0,0 +1,34 @@ +// +// MGMAppDelegate.h +// Rotary Player +// +// Created by Mr. Gecko's Media (James Coleman) on 1/28/14. +// No Copyright Claimed. Public Domain. +// + +#import + +@class MGMSound; + +@interface MGMAppDelegate : NSObject { + IBOutlet NSWindow *window; + IBOutlet NSTextField *statusField; + IBOutlet NSTextField *lastInfoField; + + IBOutlet NSTextField *song1Field; + IBOutlet NSTextField *song2Field; + IBOutlet NSTextField *song3Field; + IBOutlet NSTextField *song4Field; + IBOutlet NSTextField *song5Field; + IBOutlet NSTextField *song6Field; + IBOutlet NSTextField *song7Field; + IBOutlet NSTextField *song8Field; + IBOutlet NSTextField *song9Field; + + MGMSound *songPlaying; +} +- (IBAction)connect:(id)sender; +- (IBAction)disconnect:(id)sender; + +- (IBAction)chooseSong:(id)sender; +@end diff --git a/Code/Rotary_Player/Rotary Player/MGMAppDelegate.m b/Code/Rotary_Player/Rotary Player/MGMAppDelegate.m new file mode 100644 index 0000000..ec5d10c --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/MGMAppDelegate.m @@ -0,0 +1,144 @@ +// +// MGMAppDelegate.m +// Rotary Player +// +// Created by Mr. Gecko's Media (James Coleman) on 1/28/14. +// No Copyright Claimed. Public Domain. +// + +#import "MGMAppDelegate.h" + +#import "MGMSerial.h" +#import "MGMSound.h" + +NSString * const serialPort = @"/dev/cu.RotaryGecko-SPPDev"; +NSString * const MGMSong1 = @"song1"; +NSString * const MGMSong2 = @"song2"; +NSString * const MGMSong3 = @"song3"; +NSString * const MGMSong4 = @"song4"; +NSString * const MGMSong5 = @"song5"; +NSString * const MGMSong6 = @"song6"; +NSString * const MGMSong7 = @"song7"; +NSString * const MGMSong8 = @"song8"; +NSString * const MGMSong9 = @"song9"; + +@implementation MGMAppDelegate +- (void)awakeFromNib { + MGMSerialPorts *ports = [MGMSerialPorts sharedSerialPorts]; + NSLog(@"%@", [ports serialPorts]); + + NSUserDefaults *settings = [NSUserDefaults standardUserDefaults]; + if ([settings objectForKey:MGMSong1]!=nil) + [song1Field setStringValue:[[[settings objectForKey:MGMSong1] lastPathComponent] stringByDeletingPathExtension]]; + if ([settings objectForKey:MGMSong2]!=nil) + [song2Field setStringValue:[[[settings objectForKey:MGMSong2] lastPathComponent] stringByDeletingPathExtension]]; + if ([settings objectForKey:MGMSong3]!=nil) + [song3Field setStringValue:[[[settings objectForKey:MGMSong3] lastPathComponent] stringByDeletingPathExtension]]; + if ([settings objectForKey:MGMSong4]!=nil) + [song4Field setStringValue:[[[settings objectForKey:MGMSong4] lastPathComponent] stringByDeletingPathExtension]]; + if ([settings objectForKey:MGMSong5]!=nil) + [song5Field setStringValue:[[[settings objectForKey:MGMSong5] lastPathComponent] stringByDeletingPathExtension]]; + if ([settings objectForKey:MGMSong6]!=nil) + [song6Field setStringValue:[[[settings objectForKey:MGMSong6] lastPathComponent] stringByDeletingPathExtension]]; + if ([settings objectForKey:MGMSong7]!=nil) + [song7Field setStringValue:[[[settings objectForKey:MGMSong7] lastPathComponent] stringByDeletingPathExtension]]; + if ([settings objectForKey:MGMSong8]!=nil) + [song8Field setStringValue:[[[settings objectForKey:MGMSong8] lastPathComponent] stringByDeletingPathExtension]]; + if ([settings objectForKey:MGMSong9]!=nil) + [song9Field setStringValue:[[[settings objectForKey:MGMSong9] lastPathComponent] stringByDeletingPathExtension]]; +} +- (void)dealloc { + [super dealloc]; +} + +- (IBAction)connect:(id)sender { + MGMSerialPort *port = [[MGMSerialPorts sharedSerialPorts] portForPath:serialPort]; + [port setSpeed:9600]; + if ([port open]) { + [statusField setStringValue:@"Connected"]; + } else { + [statusField setStringValue:@"Unable to Connect"]; + } + [port setDelegate:self]; + NSLog(@"%@", port); + + [port readDataInBackgroundNewLine]; +} +- (IBAction)disconnect:(id)sender { + [[[MGMSerialPorts sharedSerialPorts] portForPath:serialPort] close]; + [statusField setStringValue:@"Disconnected"]; +} + + +- (void)serial:(MGMSerialPort *)thePort read:(NSData *)theBytes; { + NSString *info = [[[NSString alloc] initWithData:theBytes encoding:NSUTF8StringEncoding] autorelease]; + [lastInfoField setStringValue:info]; + NSUserDefaults *settings = [NSUserDefaults standardUserDefaults]; + if ([info hasPrefix:@"Dialed: "]) { + NSString *number = [info substringFromIndex:8]; + NSString *song = [NSString stringWithFormat:@"song%@", number]; + if ([settings objectForKey:song]!=nil) { + if (songPlaying!=nil) { + [songPlaying stop]; + [songPlaying release]; + } + songPlaying = [[MGMSound alloc] initWithContentsOfFile:[settings objectForKey:song]]; + [songPlaying setDelegate:self]; + [songPlaying play]; + } + NSLog(@"%@", info); + } else if ([info hasPrefix:@"Hook: "]) { + NSString *status = [info substringFromIndex:6]; + if ([status isEqual:@"0"] && songPlaying!=nil) { + [songPlaying stop]; + [songPlaying release]; + songPlaying = nil; + } + NSLog(@"%@", info); + } +} + +- (void)soundDidFinishPlaying:(MGMSound *)theSound { + [songPlaying release]; + songPlaying = nil; +} + +- (IBAction)chooseSong:(id)sender { + NSUserDefaults *settings = [NSUserDefaults standardUserDefaults]; + NSOpenPanel *panel = [NSOpenPanel openPanel]; + [panel setCanChooseDirectories:NO]; + [panel setCanChooseFiles:YES]; + long returnCode = [panel runModal]; + if (returnCode==NSOKButton) { + NSString *path = [[panel URL] path]; + if ([[sender identifier] isEqual:@"1"]) { + [song1Field setStringValue:[[path lastPathComponent] stringByDeletingPathExtension]]; + [settings setObject:path forKey:MGMSong1]; + } else if ([[sender identifier] isEqual:@"2"]) { + [song2Field setStringValue:[[path lastPathComponent] stringByDeletingPathExtension]]; + [settings setObject:path forKey:MGMSong2]; + } else if ([[sender identifier] isEqual:@"3"]) { + [song3Field setStringValue:[[path lastPathComponent] stringByDeletingPathExtension]]; + [settings setObject:path forKey:MGMSong3]; + } else if ([[sender identifier] isEqual:@"4"]) { + [song4Field setStringValue:[[path lastPathComponent] stringByDeletingPathExtension]]; + [settings setObject:path forKey:MGMSong4]; + } else if ([[sender identifier] isEqual:@"5"]) { + [song5Field setStringValue:[[path lastPathComponent] stringByDeletingPathExtension]]; + [settings setObject:path forKey:MGMSong5]; + } else if ([[sender identifier] isEqual:@"6"]) { + [song6Field setStringValue:[[path lastPathComponent] stringByDeletingPathExtension]]; + [settings setObject:path forKey:MGMSong6]; + } else if ([[sender identifier] isEqual:@"7"]) { + [song7Field setStringValue:[[path lastPathComponent] stringByDeletingPathExtension]]; + [settings setObject:path forKey:MGMSong7]; + } else if ([[sender identifier] isEqual:@"8"]) { + [song8Field setStringValue:[[path lastPathComponent] stringByDeletingPathExtension]]; + [settings setObject:path forKey:MGMSong8]; + } else if ([[sender identifier] isEqual:@"9"]) { + [song9Field setStringValue:[[path lastPathComponent] stringByDeletingPathExtension]]; + [settings setObject:path forKey:MGMSong9]; + } + } +} +@end diff --git a/Code/Rotary_Player/Rotary Player/MGMSerial.h b/Code/Rotary_Player/Rotary Player/MGMSerial.h new file mode 100644 index 0000000..8590b78 --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/MGMSerial.h @@ -0,0 +1,70 @@ +// +// MGMSerial.h +// Rotary Player +// +// Created by Mr. Gecko's Media (James Coleman) on 1/28/14. +// No Copyright Claimed. Public Domain. +// + +#import + +extern NSString * const MGMSerialPortsFoundNotification; +extern NSString * const MGMSerialPortsRemovedNotification; + +@class MGMSerialPort; + +@interface MGMSerialPorts : NSObject { + NSMutableArray *serialPorts; + + IONotificationPortRef notificationPort; + CFRunLoopSourceRef runLoop; +} ++ (id)sharedSerialPorts; + +- (NSArray *)serialPorts; +- (MGMSerialPort *)portForName:(NSString *)theName; +- (MGMSerialPort *)portForPath:(NSString *)thePath; +- (NSArray *)portsOfType:(NSString *)theType; +@end + +@protocol MGMSerialPortDelegate +- (void)serial:(MGMSerialPort *)thePort read:(NSData *)theBytes; +@end + +@interface MGMSerialPort : NSObject { + NSString *portPath; + NSString *portName; + NSString *portType; + long portSpeed; + int fileDescriptor; + + id delegate; + + NSLock *readLock; + BOOL stopBackgroundRead; + NSLock *closeLock; +} ++ (id)portWithPath:(NSString *)thePath name:(NSString *)theName type:(NSString *)theType speed:(int)theSpeed delegate:(id)theDelegate; +- (id)initWithPath:(NSString *)thePath name:(NSString *)theName type:(NSString *)theType speed:(int)theSpeed delegate:(id)theDelegate; + +- (NSString *)path; +- (NSString *)name; +- (NSString *)type; + +- (BOOL)isOpen; +- (BOOL)open; +- (void)close; + +- (long)speed; +- (BOOL)setSpeed:(long)theSpeed; + +- (id)delegate; +- (void)setDelegate:(id)theDelegate; + +- (BOOL)writeData:(NSData *)data; +- (BOOL)writeString:(NSString *)string usingEncoding:(NSStringEncoding)encoding; + +- (NSData *)readData:(int)theByteCount; +- (BOOL)readDataInBackgroundNewLine; +- (void)stopBackgroundRead; +@end diff --git a/Code/Rotary_Player/Rotary Player/MGMSerial.m b/Code/Rotary_Player/Rotary Player/MGMSerial.m new file mode 100644 index 0000000..e2242d5 --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/MGMSerial.m @@ -0,0 +1,348 @@ +// +// MGMSerial.m +// Rotary Player +// +// Created by Mr. Gecko's Media (James Coleman) on 1/28/14. +// No Copyright Claimed. Public Domain. +// + +#import "MGMSerial.h" +#import +#import +#include + +NSString * const MGMSerialPortsFoundNotification = @"MGMSerialPortsFoundNotification"; +NSString * const MGMSerialPortsRemovedNotification = @"MGMSerialPortsRemovedNotification"; + +int const MGMSerialPortMaxLine = 4096; + +@interface MGMSerialPorts (MGMPrivate) +- (MGMSerialPort *)nextPort:(io_iterator_t)iterator; +@end + +@interface MGMSerialPort (MGMPrivate) + +@end + + +void MGMSerialPortFound(void *refcon, io_iterator_t iterator) { + +} +void MGMSerialPortDidRemove(void *refcon, io_iterator_t iterator) { + +} + +static MGMSerialPorts *MGMSharedSerialPorts = nil; + +@implementation MGMSerialPorts ++ (id)sharedSerialPorts { + @synchronized(self) { + if (MGMSharedSerialPorts==nil) { + MGMSharedSerialPorts = [self new]; + } + } + return MGMSharedSerialPorts; +} +- (id)init { + if ((self = [super init])) { + serialPorts = [NSMutableArray new]; + + CFMutableDictionaryRef servicesMatch = IOServiceMatching(kIOSerialBSDServiceValue); + if (servicesMatch!=NULL) { + CFDictionarySetValue(servicesMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); + CFMutableDictionaryRef servicesMatchRemoved = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, servicesMatch); + + notificationPort = IONotificationPortCreate(kIOMasterPortDefault); + runLoop = IONotificationPortGetRunLoopSource(notificationPort); + CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoop, kCFRunLoopDefaultMode); + + + io_iterator_t found; + kern_return_t result = IOServiceAddMatchingNotification(notificationPort, kIOPublishNotification, servicesMatch, MGMSerialPortFound, self, &found); + if (result!=kIOReturnSuccess) + NSLog(@"Unable to register for serial add %d", result); + MGMSerialPort *port; + while ((port = [self nextPort:found])) { + [serialPorts addObject:port]; + } + IOObjectRelease(found); + + + result = IOServiceAddMatchingNotification(notificationPort, kIOTerminatedNotification, servicesMatchRemoved, MGMSerialPortDidRemove, self, &found); + if (result!=kIOReturnSuccess) { + NSLog(@"Unable to register for serial remove %d", result); + } else { + MGMSerialPort *port; + while ((port = [self nextPort:found])) { + [serialPorts removeObject:port]; + } + IOObjectRelease(found); + } + } + } + return self; +} +- (MGMSerialPort *)nextPort:(io_iterator_t)iterator { + io_object_t serialPort = IOIteratorNext(iterator); + if (serialPort != 0) { + NSString *portName = [(NSString *)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0) autorelease]; + NSString *portPath = [(NSString *)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0) autorelease]; + NSString *portType = [(NSString *)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIOSerialBSDTypeKey), kCFAllocatorDefault, 0) autorelease]; + IOObjectRelease(serialPort); + if (portName!=nil && portPath!=nil) { + MGMSerialPort *port = [self portForPath:portPath]; + if (port!=nil) { + return port; + } + return [MGMSerialPort portWithPath:portPath name:portName type:portType speed:0 delegate:nil]; + } + } + return nil; +} + +- (void)portsFound:(io_iterator_t)found { + NSMutableArray *addedPorts = [NSMutableArray array]; + MGMSerialPort *port; + while ((port = [self nextPort:found])) { + [serialPorts addObject:port]; + [addedPorts addObject:port]; + } + [[NSNotificationCenter defaultCenter] postNotificationName:MGMSerialPortsFoundNotification object:self userInfo:[NSDictionary dictionaryWithObject:addedPorts forKey:@"ports"]]; +} + +- (void)postsRemoved:(io_iterator_t)removed { + NSMutableArray *removedPorts = [NSMutableArray array]; + MGMSerialPort *port; + while ((port = [self nextPort:removed])) { + [port close]; + [removedPorts addObject:port]; + [serialPorts removeObject:port]; + } + [[NSNotificationCenter defaultCenter] postNotificationName:MGMSerialPortsRemovedNotification object:self userInfo:[NSDictionary dictionaryWithObject:removedPorts forKey:@"ports"]]; +} + +- (NSArray *)serialPorts { + return serialPorts; +} +- (MGMSerialPort *)portForName:(NSString *)portName { + for (int i=0; i<[serialPorts count]; i++) { + if ([[(MGMSerialPort *)[serialPorts objectAtIndex:i] name] isEqualToString:portName]) + return [serialPorts objectAtIndex:i]; + } + return nil; +} +- (MGMSerialPort *)portForPath:(NSString *)portPath { + for (int i=0; i<[serialPorts count]; i++) { + if ([[(MGMSerialPort *)[serialPorts objectAtIndex:i] path] isEqualToString:portPath]) + return [serialPorts objectAtIndex:i]; + } + return nil; +} +- (NSArray *)portsOfType:(NSString *)portType { + NSMutableArray *ports = [NSMutableArray array]; + for (int i=0; i<[serialPorts count]; i++) { + if ([[(MGMSerialPort *)[serialPorts objectAtIndex:i] type] isEqualToString:portType]) + [ports addObject:[serialPorts objectAtIndex:i]]; + } + return ports; +} +@end + +@implementation MGMSerialPort ++ (id)portWithPath:(NSString *)thePath name:(NSString *)theName type:(NSString *)theType speed:(int)theSpeed delegate:(id)theDelegate { + return [[[self alloc] initWithPath:thePath name:theName type:theType speed:theSpeed delegate:theDelegate] autorelease]; +} +- (id)initWithPath:(NSString *)thePath name:(NSString *)theName type:(NSString *)theType speed:(int)theSpeed delegate:(id)theDelegate { + if ((self = [super init])) { + portPath = [thePath copy]; + portName = [theName copy]; + portType = [theType copy]; + portSpeed = theSpeed; + + fileDescriptor = -1; + + readLock = [NSLock new]; + closeLock = [NSLock new]; + + delegate = [theDelegate retain]; + + stopBackgroundRead = YES; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p %@ %@>", NSStringFromClass([self class]), self, portPath, portName]; +} +- (NSString *)path { + return portPath; +} +- (NSString *)name { + return portName; +} +- (NSString *)type { + return portType; +} + +- (BOOL)isOpen { + return (fileDescriptor>=0); +} +- (BOOL)open { + if (fileDescriptor>=0) + return YES; + fileDescriptor = open([portPath fileSystemRepresentation], O_RDWR | O_NOCTTY | O_NONBLOCK); + + if (fileDescriptor<0) { + fileDescriptor = -1; + NSLog(@"Unable to open."); + return NO; + } else if (portSpeed!=0) { + speed_t newSpeed = portSpeed; + int errorCode = ioctl(fileDescriptor, IOSSIOSPEED, &newSpeed, 1); + if (errorCode==-1) { + if (fileDescriptor>=0) + close(fileDescriptor); + fileDescriptor = -1; + } + } + return YES; +} +- (void)close { + if (fileDescriptor>=0) { + stopBackgroundRead = YES; + [closeLock lock]; + + close(fileDescriptor); + fileDescriptor = -1; + + [closeLock unlock]; + } +} + +- (long)speed { + return portSpeed; +} +- (BOOL)setSpeed:(long)theSpeed { + if (fileDescriptor >= 0) { + speed_t newSpeed = theSpeed; + int errorCode = ioctl(fileDescriptor, IOSSIOSPEED, &newSpeed, 1); + if (errorCode == -1) { + return NO; + } else { + portSpeed = theSpeed; + } + } else { + portSpeed = theSpeed; + } + return YES; +} + +- (id)delegate { + return delegate; +} +- (void)setDelegate:(id)theDelegate { + [delegate autorelease]; + delegate = [theDelegate retain]; +} + +- (BOOL)writeData:(NSData *)data { + const char *dataBytes = (const char *)[data bytes]; + NSUInteger dataLenth = [data length]; + ssize_t bytesWritten = 0; + if (dataBytes!=NULL && dataLenth>0) { + bytesWritten = write(fileDescriptor, dataBytes, dataLenth); + if ((NSUInteger)bytesWritten==dataLenth) { + return YES; + } + } + return NO; +} +- (BOOL)writeString:(NSString *)string usingEncoding:(NSStringEncoding)encoding { + return [self writeData:[string dataUsingEncoding:encoding]]; +} + +- (NSData *)readData:(int)theByteCount { + [readLock lock]; + [closeLock lock]; + + NSData *data = nil; + void *buffer = malloc(theByteCount); + ssize_t bytesRead = 0; + fd_set *readFDs = NULL; + + if (fileDescriptor>=0) { + readFDs = (fd_set *)malloc(sizeof(fd_set)); + FD_ZERO(readFDs); + FD_SET(fileDescriptor, readFDs); + int result = select(fileDescriptor+1, readFDs, nil, nil, nil); + if (result>=1 && fileDescriptor>=0) + bytesRead = read(fileDescriptor, buffer, theByteCount); + free(readFDs); + readFDs = NULL; + if (bytesRead==0) { + [closeLock unlock]; + [readLock unlock]; + free(buffer); + return nil; + } + data = [NSData dataWithBytes:buffer length:bytesRead]; + } + + free(buffer); + + [closeLock unlock]; + [readLock unlock]; + return data; +} +- (BOOL)readDataInBackgroundNewLine { + if ([delegate respondsToSelector:@selector(serial:read:)] && stopBackgroundRead && fileDescriptor>=0) { + stopBackgroundRead = NO; + [NSThread detachNewThreadSelector:@selector(readDataBackgroundThread) toTarget:self withObject:nil]; + return YES; + } + return NO; +} +- (void)stopBackgroundRead { + stopBackgroundRead = YES; +} +- (void)readDataBackgroundThread { + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + + while (!stopBackgroundRead) { + NSMutableData *data = [NSMutableData new]; + + while (!stopBackgroundRead) { + NSData *readData = [self readData:1]; + if (readData!=nil) { + if (strcmp([readData bytes], "\n")==0 || strcmp([readData bytes], "\r")==0) { + if ([data length]<=0) + continue; + break; + } else { + if ([data length]>=MGMSerialPortMaxLine) + break; + [data appendData:readData]; + } + } + [pool drain]; + pool = [NSAutoreleasePool new]; + } + + if ([data length]>0 && !stopBackgroundRead) { + SEL readSelector = @selector(serial:read:); + NSMethodSignature *signature = [(NSObject *)delegate methodSignatureForSelector:readSelector]; + if (signature!=nil) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setSelector:readSelector]; + [invocation setArgument:&self atIndex:2]; + [invocation setArgument:&data atIndex:3]; + [invocation performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:delegate waitUntilDone:YES]; + } + } + + [data release]; + } + + [pool drain]; +} +@end diff --git a/Code/Rotary_Player/Rotary Player/MGMSound.h b/Code/Rotary_Player/Rotary Player/MGMSound.h new file mode 100644 index 0000000..cc6e616 --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/MGMSound.h @@ -0,0 +1,65 @@ +// +// MGMSound.h +// SoundNote +// +// Created by Mr. Gecko on 9/23/10. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission to use, copy, modify, and/or distribute this software for any purpose +// with or without fee is hereby granted, provided that the above copyright notice +// and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, +// OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +// ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#if TARGET_OS_IPHONE +#import +#import +#else +#import +#endif + +@class MGMSound; + +@protocol MGMSoundDelegate +- (void)soundDidFinishPlaying:(MGMSound *)theSound; +@end + +@protocol NSSoundDelegate; + +@interface MGMSound : NSObject +#if TARGET_OS_IPHONE + +#else + +#endif +{ +#if TARGET_OS_IPHONE + AVAudioPlayer *sound; +#else + NSSound *sound; +#endif + id delegate; + + BOOL loops; +} +- (id)initWithContentsOfFile:(NSString *)theFile; +- (id)initWithContentsOfURL:(NSURL *)theURL; +- (id)initWithData:(NSData *)theData; + +- (void)setDelegate:(id)theDelegate; +- (id)delegate; + +- (void)setLoops:(BOOL)shouldLoop; +- (BOOL)loops; + +- (void)play; +- (void)pause; +- (void)stop; +- (BOOL)isPlaying; +@end \ No newline at end of file diff --git a/Code/Rotary_Player/Rotary Player/MGMSound.m b/Code/Rotary_Player/Rotary Player/MGMSound.m new file mode 100644 index 0000000..fbf8a67 --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/MGMSound.m @@ -0,0 +1,109 @@ +// +// MGMSound.m +// SoundNote +// +// Created by Mr. Gecko on 9/23/10. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission to use, copy, modify, and/or distribute this software for any purpose +// with or without fee is hereby granted, provided that the above copyright notice +// and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, +// OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +// ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// + +#import "MGMSound.h" + +@implementation MGMSound +- (id)init { + if ((self = [super init])) { + loops = NO; + } + return self; +} +- (id)initWithContentsOfFile:(NSString *)theFile { + return [self initWithContentsOfURL:[NSURL fileURLWithPath:theFile]]; +} +- (id)initWithContentsOfURL:(NSURL *)theURL { + if ((self = [self init])) { +#if TARGET_OS_IPHONE + sound = [[AVAudioPlayer alloc] initWithContentsOfURL:theURL error:nil]; +#else + sound = [[NSSound alloc] initWithContentsOfURL:theURL byReference:YES]; +#endif + [sound setDelegate:self]; + } + return self; +} +- (id)initWithData:(NSData *)theData { + if ((self = [self init])) { +#if TARGET_OS_IPHONE + sound = [[AVAudioPlayer alloc] initWithData:theData error:nil]; +#else + sound = [[NSSound alloc] initWithData:theData]; +#endif + [sound setDelegate:self]; + } + return self; +} +- (void)dealloc { + [sound setDelegate:nil]; + [sound stop]; + [sound release]; + [super dealloc]; +} + +- (void)setDelegate:(id)theDelegate { + delegate = theDelegate; +} +- (id)delegate { + return delegate; +} + +#if TARGET_OS_IPHONE +- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { + if (loops) { + [sound stop]; + [sound play]; + } else { + if (delegate!=nil && [delegate respondsToSelector:@selector(soundDidFinishPlaying:)]) [delegate soundDidFinishPlaying:self]; + } +} +#else +- (void)sound:(NSSound *)theSound didFinishPlaying:(BOOL)finishedPlaying { + if (finishedPlaying) { + if (loops) { + [sound stop]; + [sound play]; + } else { + if (delegate!=nil && [delegate respondsToSelector:@selector(soundDidFinishPlaying:)]) [delegate soundDidFinishPlaying:self]; + } + } +} +#endif + +- (void)setLoops:(BOOL)shouldLoop { + loops = shouldLoop; +} +- (BOOL)loops { + return loops; +} + +- (void)play { + [sound performSelectorOnMainThread:@selector(play) withObject:nil waitUntilDone:YES]; +} +- (void)pause { + [sound pause]; +} +- (void)stop { + [sound stop]; +} +- (BOOL)isPlaying { + return [sound isPlaying]; +} +@end \ No newline at end of file diff --git a/Code/Rotary_Player/Rotary Player/Rotary Player-Info.plist b/Code/Rotary_Player/Rotary Player/Rotary Player-Info.plist new file mode 100644 index 0000000..a9d3fbe --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/Rotary Player-Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.mrgeckosmedia.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSHumanReadableCopyright + Copyright © 2014 Mr. Gecko's Media. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/Code/Rotary_Player/Rotary Player/Rotary Player-Prefix.pch b/Code/Rotary_Player/Rotary Player/Rotary Player-Prefix.pch new file mode 100644 index 0000000..d85b0aa --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/Rotary Player-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'Rotary Player' target in the 'Rotary Player' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/Code/Rotary_Player/Rotary Player/en.lproj/Credits.rtf b/Code/Rotary_Player/Rotary Player/en.lproj/Credits.rtf new file mode 100644 index 0000000..46576ef --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/en.lproj/Credits.rtf @@ -0,0 +1,29 @@ +{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw9840\paperh8400 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs24 \cf0 Engineering: +\b0 \ + Some people\ +\ + +\b Human Interface Design: +\b0 \ + Some other people\ +\ + +\b Testing: +\b0 \ + Hopefully not nobody\ +\ + +\b Documentation: +\b0 \ + Whoever\ +\ + +\b With special thanks to: +\b0 \ + Mom\ +} diff --git a/Code/Rotary_Player/Rotary Player/en.lproj/InfoPlist.strings b/Code/Rotary_Player/Rotary Player/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Code/Rotary_Player/Rotary Player/en.lproj/MainMenu.xib b/Code/Rotary_Player/Rotary Player/en.lproj/MainMenu.xib new file mode 100644 index 0000000..f724255 --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/en.lproj/MainMenu.xib @@ -0,0 +1,6531 @@ + + + + 1080 + 13B42 + 3084 + 1265 + 696.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 3084 + + + IBNSLayoutConstraint + NSButton + NSButtonCell + NSCustomObject + NSMenu + NSMenuItem + NSTextField + NSTextFieldCell + NSView + NSWindowTemplate + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + + + Rotary Player + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + + Rotary Player + + + + About Rotary Player + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + + Services + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide Rotary Player + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit Rotary Player + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + + File + + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + + Open Recent + + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save… + s + 1048576 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + + Edit + + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + + Find + + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find and Replace… + f + 1572864 + 2147483647 + + + 12 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + + Spelling and Grammar + + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + + Substitutions + + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + + Transformations + + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + + Speech + + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + + Format + + + + Font + + 2147483647 + + + submenuAction: + + + Font + + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + + Kern + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligatures + + 2147483647 + + + submenuAction: + + + Ligatures + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + + Baseline + + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + + Text + + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + + Writing Direction + + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + + View + + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + + Window + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + + Help + + + + Rotary Player Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + 15 + 2 + {{335, 390}, {480, 336}} + 1954021376 + Rotary Player + NSWindow + + + + + 256 + + + + 268 + {{14, 288}, {92, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Connect + + LucidaGrande + 13 + 1044 + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{356, 288}, {110, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Disconnect + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{106, 298}, {250, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Disconnected + + _NS:1535 + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + NO + 1 + + + + 268 + {{18, 21}, {444, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Last Info + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{118, 270}, {344, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Song + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{31, 262}, {87, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Choose + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{18, 270}, {13, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + 1 + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{118, 242}, {344, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Song + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{31, 234}, {87, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Choose + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{18, 242}, {13, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + 2 + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{118, 214}, {344, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Song + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{31, 206}, {87, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Choose + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{18, 214}, {13, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + 3 + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{118, 186}, {344, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Song + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{31, 178}, {87, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Choose + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{18, 186}, {13, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + 4 + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{118, 158}, {344, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Song + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{31, 150}, {87, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Choose + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{18, 158}, {13, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + 5 + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{118, 131}, {344, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Song + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{31, 122}, {87, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Choose + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{18, 131}, {13, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + 6 + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{118, 103}, {344, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Song + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{31, 95}, {87, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Choose + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{18, 103}, {13, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + 7 + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{118, 75}, {344, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Song + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{31, 67}, {87, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Choose + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{18, 75}, {13, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + 8 + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{118, 47}, {344, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + Song + + _NS:1535 + + + + + NO + 1 + + + + 268 + {{31, 39}, {87, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Choose + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{18, 47}, {13, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + 9 + + _NS:1535 + + + + + NO + 1 + + + {480, 336} + + + + + {{0, 0}, {1440, 878}} + {10000000000000, 10000000000000} + YES + + + MGMAppDelegate + + + NSFontManager + + + + + + + terminate: + + + + 449 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 495 + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + performFindPanelAction: + + + + 535 + + + + addFontTrait: + + + + 421 + + + + addFontTrait: + + + + 422 + + + + modifyFont: + + + + 423 + + + + orderFrontFontPanel: + + + + 424 + + + + modifyFont: + + + + 425 + + + + window + + + + 532 + + + + connect: + + + + 562 + + + + disconnect: + + + + 568 + + + + lastInfoField + + + + 589 + + + + statusField + + + + 590 + + + + song1Field + + + + 825 + + + + song2Field + + + + 826 + + + + song3Field + + + + 827 + + + + song4Field + + + + 828 + + + + song5Field + + + + 829 + + + + song6Field + + + + 830 + + + + song7Field + + + + 831 + + + + song8Field + + + + 832 + + + + song9Field + + + + 833 + + + + chooseSong: + + + + 834 + + + + chooseSong: + + + + 835 + + + + chooseSong: + + + + 836 + + + + chooseSong: + + + + 837 + + + + chooseSong: + + + + 838 + + + + chooseSong: + + + + 839 + + + + chooseSong: + + + + 840 + + + + chooseSong: + + + + 841 + + + + chooseSong: + + + + 842 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + + + + + + + 19 + + + + + + + + 56 + + + + + + + + 217 + + + + + + + + 83 + + + + + + + + 81 + + + + + + + + + + + + + + + + + 75 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + + + + + + 126 + + + + + 205 + + + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + + + + + + 216 + + + + + + + + 200 + + + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + + + + + + 296 + + + + + + + + + 297 + + + + + 298 + + + + + 211 + + + + + + + + 212 + + + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + + + + + + 349 + + + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 371 + + + + + + + + 372 + + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 3 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 4 + 0 + + 4 + 1 + + 21 + + 1000 + + 3 + 9 + 3 + + + + 3 + 0 + + 4 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 4 + 0 + + 4 + 1 + + 47 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 4 + 0 + + 4 + 1 + + 75 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 4 + 0 + + 4 + 1 + + 74 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 4 + 0 + + 4 + 1 + + 103 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 4 + 0 + + 4 + 1 + + 102 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 4 + 0 + + 4 + 1 + + 129 + + 1000 + + 3 + 9 + 3 + + + + 10 + 0 + + 10 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 3 + 1 + + 161 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 3 + 0 + + 3 + 1 + + 158 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 3 + 0 + + 3 + 1 + + 133 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 3 + 0 + + 3 + 1 + + 130 + + 1000 + + 3 + 9 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 3 + 0 + + 3 + 1 + + 105 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 3 + 1 + + 102 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 3 + 0 + + 3 + 1 + + 77 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 3 + 0 + + 3 + 1 + + 74 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 3 + 0 + + 4 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 3 + 0 + + 4 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 3 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 375 + + + + + + + + 376 + + + + + + + + + 377 + + + + + + + + 388 + + + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + + + + + + 398 + + + + + + + + 399 + + + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 420 + + + + + 450 + + + + + + + + 451 + + + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + + + + + + 491 + + + + + + + + 492 + + + + + 494 + + + + + 496 + + + + + + + + 497 + + + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 534 + + + + + 544 + + + + + + 7 + 0 + + 0 + 1 + + 80 + + 1000 + + 3 + 9 + 1 + + + + + + 545 + + + + + 547 + + + + + 548 + + + + + + 7 + 0 + + 0 + 1 + + 98 + + 1000 + + 3 + 9 + 1 + + + + + + 549 + + + + + 554 + + + + + 566 + + + + + 569 + + + + + 570 + + + + + + + + 571 + + + + + 574 + + + + + 575 + + + + + 576 + + + + + 578 + + + + + 579 + + + + + + + + 580 + + + + + 584 + + + + + 586 + + + + + 591 + + + + + + + + 592 + + + + + 595 + + + + + + 7 + 0 + + 0 + 1 + + 75 + + 1000 + + 3 + 9 + 1 + + + + + + 596 + + + + + 606 + + + + + 625 + + + + + + 7 + 0 + + 0 + 1 + + 9 + + 1000 + + 3 + 9 + 1 + + + + + + 626 + + + + + 648 + + + + + 649 + + + + + 651 + + + + + 652 + + + + + 653 + + + + + 654 + + + + + 656 + + + + + 657 + + + + + 658 + + + + + 659 + + + + + + + + 660 + + + + + + + + 661 + + + + + + + + 663 + + + + + 665 + + + + + 666 + + + + + 667 + + + + + 671 + + + + + 674 + + + + + 676 + + + + + 677 + + + + + 678 + + + + + 675 + + + + + 680 + + + + + + + + 681 + + + + + + + + 682 + + + + + + + + 683 + + + + + 684 + + + + + 685 + + + + + 686 + + + + + 687 + + + + + 688 + + + + + 689 + + + + + 690 + + + + + 691 + + + + + 692 + + + + + 693 + + + + + + + + 694 + + + + + + + + 695 + + + + + + + + 696 + + + + + 697 + + + + + 698 + + + + + 699 + + + + + 700 + + + + + 701 + + + + + 702 + + + + + 703 + + + + + 704 + + + + + 705 + + + + + 706 + + + + + + + + 707 + + + + + + + + 708 + + + + + + + + 709 + + + + + 710 + + + + + 711 + + + + + 712 + + + + + 713 + + + + + 714 + + + + + 715 + + + + + 716 + + + + + 717 + + + + + 719 + + + + + + + + 720 + + + + + + + + 721 + + + + + + + + 722 + + + + + 723 + + + + + 724 + + + + + 726 + + + + + 731 + + + + + 732 + + + + + + + + 733 + + + + + + + + 734 + + + + + + + + 735 + + + + + 736 + + + + + 737 + + + + + 739 + + + + + 740 + + + + + 743 + + + + + 744 + + + + + 745 + + + + + + + + 746 + + + + + + + + 747 + + + + + + + + 748 + + + + + 749 + + + + + 750 + + + + + 751 + + + + + 752 + + + + + 756 + + + + + 757 + + + + + 758 + + + + + + + + 759 + + + + + + + + 760 + + + + + + + + 761 + + + + + 762 + + + + + 763 + + + + + 764 + + + + + 766 + + + + + 768 + + + + + 769 + + + + + 773 + + + + + 718 + + + + + 770 + + + + + 753 + + + + + 727 + + + + + 738 + + + + + 789 + + + + + 790 + + + + + 816 + + + + + 818 + + + + + 819 + + + + + 820 + + + + + 821 + + + + + 822 + + + + + 823 + + + + + 824 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{380, 496}, {480, 360}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + 1 + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + 2 + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + 3 + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + 4 + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + 5 + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + 6 + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + 7 + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + 8 + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + 9 + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 842 + + + + + MGMAppDelegate + NSObject + + id + id + id + + + + chooseSong: + id + + + connect: + id + + + disconnect: + id + + + + NSTextField + NSTextField + NSTextField + NSTextField + NSTextField + NSTextField + NSTextField + NSTextField + NSTextField + NSTextField + NSTextField + NSWindow + + + + lastInfoField + NSTextField + + + song1Field + NSTextField + + + song2Field + NSTextField + + + song3Field + NSTextField + + + song4Field + NSTextField + + + song5Field + NSTextField + + + song6Field + NSTextField + + + song7Field + NSTextField + + + song8Field + NSTextField + + + song9Field + NSTextField + + + statusField + NSTextField + + + window + NSWindow + + + + IBProjectSource + ./Classes/MGMAppDelegate.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + {11, 11} + {10, 3} + + YES + + diff --git a/Code/Rotary_Player/Rotary Player/main.m b/Code/Rotary_Player/Rotary Player/main.m new file mode 100644 index 0000000..608d842 --- /dev/null +++ b/Code/Rotary_Player/Rotary Player/main.m @@ -0,0 +1,14 @@ +// +// main.m +// Rotary Player +// +// Created by James Coleman on 1/24/14. +// Copyright (c) 2014 Mr. Gecko's Media. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **)argv); +} diff --git a/Code/Rotary_Player_Firmware/Rotary_Player_Firmware.ino b/Code/Rotary_Player_Firmware/Rotary_Player_Firmware.ino new file mode 100644 index 0000000..3c2a738 --- /dev/null +++ b/Code/Rotary_Player_Firmware/Rotary_Player_Firmware.ino @@ -0,0 +1,116 @@ +// +// Rotary_Player_Firmware.ino +// +// Created by Mr. Gecko's Media (James Coleman) on 1/28/14. +// No Copyright Claimed. Public Domain. +// + +#include + +SoftwareSerial btSerial(2,3); // RX,TX +int eventPin = 4; +int eventValue = 1; +int commandPin = 5; + +int hookPin = 6; +int hookValue = 1; +int startPosPin = 7; +int startPosValue = 1; +int rotaryPin = 8; +int rotaryValue = 1; +int dialedNumber = 0; + +int speakerShutOffPin = 9; +int speakerShutOffToggle = 0; + +void setup() { + // Setup Serial Interfaces. + Serial.begin(9600); + btSerial.begin(9600); + + // Setup Pins. + pinMode(eventPin, INPUT); + pinMode(commandPin, OUTPUT); + digitalWrite(commandPin, HIGH); + + pinMode(hookPin, INPUT_PULLUP); + pinMode(startPosPin, INPUT_PULLUP); + pinMode(rotaryPin, INPUT_PULLUP); + pinMode(speakerShutOffPin, OUTPUT); + + // Allow for RN-52 to play startup tone. + digitalWrite(speakerShutOffPin, HIGH); + delay(1000); + digitalWrite(speakerShutOffPin, LOW); +} + +void loop() { + if (btSerial.available()) + Serial.write(btSerial.read()); + if (Serial.available()) { + btSerial.write(Serial.read()); + } + + // Gather information from the pins to work with. + int hook = digitalRead(hookPin); + int hookChanged = (hookValue!=hook); + hookValue = hook; + + int startPos = digitalRead(startPosPin); + int startPosChanged = (startPosValue!=startPos); + startPosValue = startPos; + + int rotary = digitalRead(rotaryPin); + int rotaryChanged = (rotaryValue!=rotary); + rotaryValue = rotary; + + // Debug Code. + if (hookChanged) { + Serial.print("Hook: "); + Serial.print(hook); + Serial.print("\n"); + btSerial.print("Hook: "); + btSerial.print(hook); + btSerial.print("\n"); + } + if (startPosChanged) { + Serial.print("Start Position: "); + Serial.print(startPos); + Serial.print("\n"); + } + if (rotaryChanged) { + Serial.print("Rotary: "); + Serial.print(rotary); + Serial.print("\n"); + } + + if (startPosChanged) { + if (startPos==0) { + dialedNumber = 0; + } else { + if (dialedNumber!=0) { + if (dialedNumber>=10) + dialedNumber = 0; + Serial.print("Dialed: "); + Serial.print(dialedNumber); + Serial.print("\n"); + btSerial.print("Dialed: "); + btSerial.print(dialedNumber); + btSerial.print("\n"); + if (dialedNumber==0) { + if (speakerShutOffToggle==0) { + speakerShutOffToggle = 1; + digitalWrite(speakerShutOffPin, HIGH); + } else { + speakerShutOffToggle = 0; + digitalWrite(speakerShutOffPin, LOW); + } + } + } + } + } + if (startPos==0 && rotaryChanged && rotary==0) { + dialedNumber++; + delay(50); + } +} diff --git a/Readme.md b/Readme.md index a59899c..d8c47b0 100644 --- a/Readme.md +++ b/Readme.md @@ -2,8 +2,8 @@ Rtoary Gecko is my work to convert a Rotary Phone into a Bluetooth Phone. You can dial numbers, and answer phone calls with your cell phone as the man in the middle that provides cell service. -The documents stored here are the major documents needed to make a Rotary Phone Bluetooth. To read my quest to build this Phone, visit my blog at http://mrgecko.org. To get videos/photos and documentation to the hardware which I collected, you can visit my bitcasa share at http://l.bitcasa.com/P8xOdiBa. +The documents stored here are the major documents needed to make a Rotary Phone Bluetooth. To read my quest to build this Phone, visit my blog at http://mrgecko.org. To get videos/photos and documentation to the hardware which I collected, you can visit my bitcasa share at http://l.bitcasa.com/P3r9r6d1. -As I do with every code I write, I make it fairly easy to understand with my naming conventions, so there are no comments to explain things, you should be able to just read it and know what it does. +As I do with every code I write, I make it fairly easy to understand with my naming conventions, so there are not many comments to explain things, you should be able to just read it and know what it does. -I would like to give a big thank you to crashcartpro in ##gen (freenode) and myself/others in #sparkfun (freenode). They all helped me out considerbly with understanding this stuff and completing this phone. \ No newline at end of file +I would like to give a big thank you to crashcartpro in ##gen (freenode) and myself/others in #sparkfun (freenode). They all helped me out considerably with understanding this stuff and completing this phone. \ No newline at end of file