Added Firmware Code and Mac App to make the Rotary Gecko a juke box. This is for my presentation at Security B-Sides Huntsville.

This commit is contained in:
GRMrGecko 2014-01-28 20:39:07 -06:00
parent a08f3f3def
commit 1f2230c2cb
21 changed files with 8002 additions and 4 deletions

View File

@ -11,6 +11,7 @@ SoftwareSerial btSerial(2,3); // RX,TX
int eventPin = 4; int eventPin = 4;
int eventValue = 1; int eventValue = 1;
int commandPin = 5; int commandPin = 5;
int commandToggle = 0;
int hookPin = 6; int hookPin = 6;
int hookValue = 1; int hookValue = 1;
@ -114,6 +115,7 @@ void setup() {
pinMode(eventPin, INPUT); pinMode(eventPin, INPUT);
pinMode(commandPin, OUTPUT); pinMode(commandPin, OUTPUT);
digitalWrite(commandPin, LOW); digitalWrite(commandPin, LOW);
commandToggle = 1;
pinMode(hookPin, INPUT_PULLUP); pinMode(hookPin, INPUT_PULLUP);
pinMode(startPosPin, INPUT_PULLUP); pinMode(startPosPin, INPUT_PULLUP);
@ -129,8 +131,9 @@ void setup() {
void loop() { void loop() {
if (btSerial.available()) if (btSerial.available())
Serial.write(btSerial.read()); Serial.write(btSerial.read());
if (Serial.available()) if (Serial.available()) {
btSerial.write(Serial.read()); btSerial.write(Serial.read());
}
// Gather information from the pins to work with. // Gather information from the pins to work with.
int event = digitalRead(eventPin); int event = digitalRead(eventPin);
@ -212,6 +215,16 @@ void loop() {
} else if (hook==0) { } else if (hook==0) {
if (dialedNumber==3) { if (dialedNumber==3) {
serialSendVerify("AP\r", "AOK"); 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) { } else if (hook==1 && state!=outgoingCall && state!=incomingCall && state!=activeCallInProgress && state!=threeWayWaiting && state!=threeWayHold && state!=threeWay && state!=incomingCallHold && state!=activeCall) {
phoneNumber[numberCount] = dialedNumber; phoneNumber[numberCount] = dialedNumber;

View File

@ -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 = "<group>"; };
2A7C81F1189815CF00094EF7 /* MGMSound.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMSound.m; sourceTree = "<group>"; };
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 = "<group>"; };
2AAEF929189365CB00E05D4F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
2AAEF92B189365CB00E05D4F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
2AAEF92D189365CB00E05D4F /* Rotary Player-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Rotary Player-Prefix.pch"; sourceTree = "<group>"; };
2AAEF92F189365CB00E05D4F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
2AAEF931189365CB00E05D4F /* MGMAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGMAppDelegate.h; sourceTree = "<group>"; };
2AAEF932189365CB00E05D4F /* MGMAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGMAppDelegate.m; sourceTree = "<group>"; };
2AAEF935189365CB00E05D4F /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = "<group>"; };
2AAEF93C1893660B00E05D4F /* MGMSerial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMSerial.h; sourceTree = "<group>"; };
2AAEF93D1893660B00E05D4F /* MGMSerial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMSerial.m; sourceTree = "<group>"; };
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 = "<group>";
};
2AAEF91D189365CB00E05D4F /* Products */ = {
isa = PBXGroup;
children = (
2AAEF91C189365CB00E05D4F /* Rotary Player.app */,
);
name = Products;
sourceTree = "<group>";
};
2AAEF91E189365CB00E05D4F /* Frameworks */ = {
isa = PBXGroup;
children = (
2AAEF93F189367CD00E05D4F /* IOKit.framework */,
2AAEF91F189365CB00E05D4F /* Cocoa.framework */,
2AAEF921189365CB00E05D4F /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "<group>";
};
2AAEF921189365CB00E05D4F /* Other Frameworks */ = {
isa = PBXGroup;
children = (
2AAEF922189365CB00E05D4F /* AppKit.framework */,
2AAEF923189365CB00E05D4F /* CoreData.framework */,
2AAEF924189365CB00E05D4F /* Foundation.framework */,
);
name = "Other Frameworks";
sourceTree = "<group>";
};
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 = "<group>";
};
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 = "<group>";
};
/* 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 = "<group>";
};
2AAEF92E189365CB00E05D4F /* Credits.rtf */ = {
isa = PBXVariantGroup;
children = (
2AAEF92F189365CB00E05D4F /* en */,
);
name = Credits.rtf;
sourceTree = "<group>";
};
2AAEF934189365CB00E05D4F /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
2AAEF935189365CB00E05D4F /* en */,
);
name = MainMenu.xib;
sourceTree = "<group>";
};
/* 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 */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Rotary Player.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
<false/>
<key>IDESourceControlProjectIdentifier</key>
<string>0E4BB332-BC42-417B-807A-34777077B658</string>
<key>IDESourceControlProjectName</key>
<string>Rotary Player</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>9A28687E-3864-4112-AB75-1624B265E471</key>
<string>ssh://github.com/GRMrGecko/Rotary-Gecko.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>Rotary Player/Rotary Player.xcodeproj/project.xcworkspace</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>9A28687E-3864-4112-AB75-1624B265E471</key>
<string>../../..</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>ssh://github.com/GRMrGecko/Rotary-Gecko.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>110</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>9A28687E-3864-4112-AB75-1624B265E471</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>9A28687E-3864-4112-AB75-1624B265E471</string>
<key>IDESourceControlWCCName</key>
<string>Rotary-Gecko</string>
</dict>
</array>
</dict>
</plist>

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0460"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2AAEF91B189365CB00E05D4F"
BuildableName = "Rotary Player.app"
BlueprintName = "Rotary Player"
ReferencedContainer = "container:Rotary Player.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2AAEF91B189365CB00E05D4F"
BuildableName = "Rotary Player.app"
BlueprintName = "Rotary Player"
ReferencedContainer = "container:Rotary Player.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2AAEF91B189365CB00E05D4F"
BuildableName = "Rotary Player.app"
BlueprintName = "Rotary Player"
ReferencedContainer = "container:Rotary Player.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2AAEF91B189365CB00E05D4F"
BuildableName = "Rotary Player.app"
BlueprintName = "Rotary Player"
ReferencedContainer = "container:Rotary Player.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>Rotary Player.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>2AAEF91B189365CB00E05D4F</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

View File

@ -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 <Cocoa/Cocoa.h>
@class MGMSound;
@interface MGMAppDelegate : NSObject <NSApplicationDelegate> {
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

View File

@ -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

View File

@ -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 <Cocoa/Cocoa.h>
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 <NSObject>
- (void)serial:(MGMSerialPort *)thePort read:(NSData *)theBytes;
@end
@interface MGMSerialPort : NSObject {
NSString *portPath;
NSString *portName;
NSString *portType;
long portSpeed;
int fileDescriptor;
id<MGMSerialPortDelegate> 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<MGMSerialPortDelegate>)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

View File

@ -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 <IOKit/serial/IOSerialKeys.h>
#import <IOKit/serial/ioss.h>
#include <sys/ioctl.h>
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<MGMSerialPortDelegate>)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

View File

@ -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 <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#else
#import <Cocoa/Cocoa.h>
#endif
@class MGMSound;
@protocol MGMSoundDelegate <NSObject>
- (void)soundDidFinishPlaying:(MGMSound *)theSound;
@end
@protocol NSSoundDelegate;
@interface MGMSound : NSObject
#if TARGET_OS_IPHONE
<AVAudioPlayerDelegate>
#else
<NSSoundDelegate>
#endif
{
#if TARGET_OS_IPHONE
AVAudioPlayer *sound;
#else
NSSound *sound;
#endif
id<MGMSoundDelegate> delegate;
BOOL loops;
}
- (id)initWithContentsOfFile:(NSString *)theFile;
- (id)initWithContentsOfURL:(NSURL *)theURL;
- (id)initWithData:(NSData *)theData;
- (void)setDelegate:(id)theDelegate;
- (id<MGMSoundDelegate>)delegate;
- (void)setLoops:(BOOL)shouldLoop;
- (BOOL)loops;
- (void)play;
- (void)pause;
- (void)stop;
- (BOOL)isPlaying;
@end

View File

@ -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<MGMSoundDelegate>)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

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.mrgeckosmedia.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2014 Mr. Gecko's Media. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@ -0,0 +1,7 @@
//
// Prefix header for all source files of the 'Rotary Player' target in the 'Rotary Player' project
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif

View File

@ -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\
}

View File

@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

File diff suppressed because it is too large Load Diff

View File

@ -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 <Cocoa/Cocoa.h>
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **)argv);
}

View File

@ -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.h>
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);
}
}

View File

@ -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. 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. 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.