From: Joseph Spiros Date: Fri, 6 Mar 2009 04:07:23 +0000 (-0500) Subject: Initial commit of PostTunes. X-Git-Url: http://git.ithinksw.org/~jspiros/PostTunes.git/commitdiff_plain/f7f7b37327b07cdffb4d1be0311498bd55ea6260?ds=sidebyside;pf=~jspiros Initial commit of PostTunes. --- f7f7b37327b07cdffb4d1be0311498bd55ea6260 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ab810ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pbxuser +*.mode1v3 +.DS_Store diff --git a/English.lproj/InfoPlist.strings b/English.lproj/InfoPlist.strings new file mode 100644 index 0000000..2a106c3 Binary files /dev/null and b/English.lproj/InfoPlist.strings differ diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib new file mode 100644 index 0000000..6574b1a --- /dev/null +++ b/English.lproj/MainMenu.xib @@ -0,0 +1,871 @@ + + + + 1050 + 9G55 + 672 + 949.43 + 353.00 + + YES + + + + YES + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + + YES + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + YES + + + PostTunes + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + PostTunes + + YES + + + About PostTunes + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + UHJlZmVyZW5jZXPigKY + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + Services + + YES + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide PostTunes + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit PostTunes + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + Help + + 1048576 + 2147483647 + + + submenuAction: + + Help + + YES + + + PostTunes Help + ? + 1048576 + 2147483647 + + + + + + + + _NSMainMenu + + + PostTunesAppDelegate + + + 27 + 2 + {{534, 588}, {372, 83}} + 1677721600 + PostTunes Preferences + NSPanel + + {100000, 83} + {372, 83} + + + 256 + + YES + + + 266 + {{96, 47}, {256, 19}} + + YES + + -1804468671 + 272761856 + + + LucidaGrande + 1.100000e+01 + 3100 + + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + textColor + + 3 + MAA + + + + + + + 266 + {{96, 20}, {256, 19}} + + YES + + -1804468671 + 272761856 + + + + YES + + + + + + + 268 + {{17, 49}, {74, 14}} + + YES + + 68288064 + 71435264 + Handler URL: + + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2OQA + + + + 6 + System + controlTextColor + + + + + + + 268 + {{17, 22}, {74, 14}} + + YES + + 68288064 + 71435264 + Secret Key: + + + + + + + + {372, 83} + + + {{0, 0}, {1680, 1028}} + {372, 99} + {100000, 99} + + + + YES + handlerURL + secretKey + + YES + + + + + YES + + + orderFrontStandardAboutPanel: + + + + 142 + + + + showHelp: + + + + 360 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + terminate: + + + + 369 + + + + unhideAllApplications: + + + + 370 + + + + delegate + + + + 374 + + + + makeKeyAndOrderFront: + + + + 385 + + + + preferencesWindow + + + + 386 + + + + value: values.handlerURL + + + + + + value: values.handlerURL + value + values.handlerURL + 2 + + + 389 + + + + value: values.secretKey + + + + + + value: values.secretKey + value + values.secretKey + 2 + + + 391 + + + + + YES + + 0 + + YES + + + + + + -2 + + + RmlsZSdzIE93bmVyA + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + YES + + + + + MainMenu + + + 56 + + + YES + + + + + + 103 + + + YES + + + + 1 + + + 106 + + + YES + + + + 2 + + + 111 + + + + + 57 + + + YES + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + 1111 + + + 144 + + + + + 129 + + + 121 + + + 143 + + + + + 236 + + + + + 131 + + + YES + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 373 + + + PostTunesAppDelegate + + + 375 + + + YES + + + + + + 376 + + + YES + + + + + + + + + 377 + + + YES + + + + + + 378 + + + + + 379 + + + YES + + + + + + 380 + + + + + 381 + + + YES + + + + + + 382 + + + + + 383 + + + YES + + + + + + 384 + + + + + 387 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 103.IBPluginDependency + 103.ImportedFromIB2 + 106.IBEditorWindowLastContentRect + 106.IBPluginDependency + 106.ImportedFromIB2 + 106.editorWindowContentRectSynchronizationRect + 111.IBPluginDependency + 111.ImportedFromIB2 + 129.IBPluginDependency + 129.ImportedFromIB2 + 130.IBPluginDependency + 130.ImportedFromIB2 + 130.editorWindowContentRectSynchronizationRect + 131.IBPluginDependency + 131.ImportedFromIB2 + 134.IBPluginDependency + 134.ImportedFromIB2 + 136.IBPluginDependency + 136.ImportedFromIB2 + 143.IBPluginDependency + 143.ImportedFromIB2 + 144.IBPluginDependency + 144.ImportedFromIB2 + 145.IBPluginDependency + 145.ImportedFromIB2 + 149.IBPluginDependency + 149.ImportedFromIB2 + 150.IBPluginDependency + 150.ImportedFromIB2 + 236.IBPluginDependency + 236.ImportedFromIB2 + 29.IBEditorWindowLastContentRect + 29.IBPluginDependency + 29.ImportedFromIB2 + 29.WindowOrigin + 29.editorWindowContentRectSynchronizationRect + 373.IBPluginDependency + 375.IBEditorWindowLastContentRect + 375.IBPluginDependency + 375.IBWindowTemplateEditedContentRect + 375.NSWindowTemplate.visibleAtLaunch + 375.windowTemplate.hasMaxSize + 375.windowTemplate.hasMinSize + 375.windowTemplate.maxSize + 375.windowTemplate.minSize + 376.IBPluginDependency + 377.IBPluginDependency + 378.IBPluginDependency + 379.IBPluginDependency + 380.IBPluginDependency + 381.IBPluginDependency + 382.IBPluginDependency + 383.IBPluginDependency + 384.IBPluginDependency + 56.IBPluginDependency + 56.ImportedFromIB2 + 57.IBEditorWindowLastContentRect + 57.IBPluginDependency + 57.ImportedFromIB2 + 57.editorWindowContentRectSynchronizationRect + 58.IBPluginDependency + 58.ImportedFromIB2 + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilderKit + com.apple.InterfaceBuilder.CocoaPlugin + + {{106, 930}, {180, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{596, 852}, {216, 23}} + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + {{436, 809}, {64, 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 + + {{0, 953}, {167, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + + {74, 862} + {{11, 836}, {478, 20}} + com.apple.InterfaceBuilder.CocoaPlugin + {{534, 588}, {372, 83}} + com.apple.InterfaceBuilder.CocoaPlugin + {{534, 588}, {372, 83}} + + + + {100000, 83} + {372, 83} + 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 + + {{12, 770}, {209, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + {{23, 794}, {245, 183}} + com.apple.InterfaceBuilder.CocoaPlugin + + + + + YES + + YES + + + YES + + + + + YES + + YES + + + YES + + + + 391 + + + + YES + + PostTunesAppDelegate + NSObject + + preferencesWindow + id + + + IBProjectSource + PostTunesAppDelegate.py + + + + + 0 + ../PostTunes.xcodeproj + 3 + + diff --git a/Info.plist b/Info.plist new file mode 100644 index 0000000..8b7cfac --- /dev/null +++ b/Info.plist @@ -0,0 +1,32 @@ + + + + + LSUIElement + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.ithinksw.posttunes + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/PostTunes.xcodeproj/project.pbxproj b/PostTunes.xcodeproj/project.pbxproj new file mode 100644 index 0000000..0ba341d --- /dev/null +++ b/PostTunes.xcodeproj/project.pbxproj @@ -0,0 +1,287 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 44; + objects = { + +/* Begin PBXBuildFile section */ + 77631A270C06C501005415CB /* Python.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77631A260C06C501005415CB /* Python.framework */; }; + 77631A3F0C0748CF005415CB /* main.py in Resources */ = {isa = PBXBuildFile; fileRef = 77631A3E0C0748CF005415CB /* main.py */; }; + 7790198F0C07548A00326F66 /* PostTunesAppDelegate.py in Resources */ = {isa = PBXBuildFile; fileRef = 7790198E0C07548A00326F66 /* PostTunesAppDelegate.py */; }; + 77C8C1F90C07829500965286 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 77C8C1F70C07829500965286 /* MainMenu.xib */; }; + 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; + 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 32CA4F630368D1EE00C91783 /* PostTunes_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PostTunes_Prefix.pch; sourceTree = ""; }; + 77631A260C06C501005415CB /* Python.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Python.framework; path = /System/Library/Frameworks/Python.framework; sourceTree = ""; }; + 77631A3E0C0748CF005415CB /* main.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = main.py; sourceTree = ""; }; + 7790198E0C07548A00326F66 /* PostTunesAppDelegate.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = PostTunesAppDelegate.py; sourceTree = ""; }; + 77C8C1F80C07829500965286 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = ""; }; + 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8D1107320486CEB800E47090 /* PostTunes.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PostTunes.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8D11072E0486CEB800E47090 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, + 77631A270C06C501005415CB /* Python.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000001 /* Classes */ = { + isa = PBXGroup; + children = ( + 7790198E0C07548A00326F66 /* PostTunesAppDelegate.py */, + ); + name = Classes; + sourceTree = ""; + }; + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 77631A260C06C501005415CB /* Python.framework */, + 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 29B97324FDCFA39411CA2CEA /* AppKit.framework */, + 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, + 29B97325FDCFA39411CA2CEA /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8D1107320486CEB800E47090 /* PostTunes.app */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* PostTunes */ = { + isa = PBXGroup; + children = ( + 080E96DDFE201D6D7F000001 /* Classes */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = PostTunes; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 32CA4F630368D1EE00C91783 /* PostTunes_Prefix.pch */, + 29B97316FDCFA39411CA2CEA /* main.m */, + 77631A3E0C0748CF005415CB /* main.py */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 77C8C1F70C07829500965286 /* MainMenu.xib */, + 8D1107310486CEB800E47090 /* Info.plist */, + 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8D1107260486CEB800E47090 /* PostTunes */ = { + isa = PBXNativeTarget; + buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "PostTunes" */; + buildPhases = ( + 8D1107290486CEB800E47090 /* Resources */, + 8D11072C0486CEB800E47090 /* Sources */, + 8D11072E0486CEB800E47090 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PostTunes; + productInstallPath = "$(HOME)/Applications"; + productName = PostTunes; + productReference = 8D1107320486CEB800E47090 /* PostTunes.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "PostTunes" */; + compatibilityVersion = "Xcode 3.0"; + hasScannedForEncodings = 1; + mainGroup = 29B97314FDCFA39411CA2CEA /* PostTunes */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8D1107260486CEB800E47090 /* PostTunes */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8D1107290486CEB800E47090 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, + 77631A3F0C0748CF005415CB /* main.py in Resources */, + 7790198F0C07548A00326F66 /* PostTunesAppDelegate.py in Resources */, + 77C8C1F90C07829500965286 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8D11072C0486CEB800E47090 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D11072D0486CEB800E47090 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 089C165DFE840E0CC02AAC07 /* English */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 77C8C1F70C07829500965286 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 77C8C1F80C07829500965286 /* English */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + C01FCF4B08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = PostTunes_Prefix.pch; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PRODUCT_NAME = PostTunes; + WRAPPER_EXTENSION = app; + ZERO_LINK = YES; + }; + name = Debug; + }; + C01FCF4C08A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = PostTunes_Prefix.pch; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + PRODUCT_NAME = PostTunes; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + ppc, + i386, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "PostTunes" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4B08A954540054247B /* Debug */, + C01FCF4C08A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "PostTunes" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/PostTunesAppDelegate.py b/PostTunesAppDelegate.py new file mode 100644 index 0000000..86dd7c6 --- /dev/null +++ b/PostTunesAppDelegate.py @@ -0,0 +1,96 @@ +# +# PostTunesAppDelegate.py +# PostTunes +# +# Created by Joseph Spiros on 3/5/09. +# Copyright iThink Software 2009. All rights reserved. +# + +import objc +from urllib import urlencode +from urllib2 import urlopen, URLError +from base64 import b64encode +from Foundation import * +from AppKit import * +from ScriptingBridge import * + +class PostTunesAppDelegate(NSObject): + preferencesWindow = objc.IBOutlet() + warnPreferences = objc.ivar(u"warnPreferences") + warnFailure = objc.ivar(u"warnFailure") + lastPersistentID = objc.ivar(u"lastPersistentID") + handlerURL = objc.ivar(u"handlerURL") + secretKey = objc.ivar(u"secretKey") + + def init(self): + self = super(PostTunesAppDelegate, self).init() + if not self: + return None + self.warnPreferences = True + self.warnFailure = True + self.lastPersistentID = None + self.handlerURL = None + self.secretKey = None + self.observeNote() + return self + + def observeNote(self): + NSDistributedNotificationCenter.defaultCenter().addObserver_selector_name_object_(self, "gotNotification:", "com.apple.iTunes.playerInfo", None) + + def gotNotification_(self, notification): + self.handlerURL = NSUserDefaults.standardUserDefaults().stringForKey_("handlerURL") + self.secretKey = NSUserDefaults.standardUserDefaults().stringForKey_("secretKey") + if notification: + noteInfo = notification.userInfo() + playerState = noteInfo["Player State"] + if "PersistentID" in noteInfo: + persistentID = noteInfo["PersistentID"] + if (persistentID != self.lastPersistentID) and ("Name" in noteInfo): + if playerState == "Playing": + if self.handlerURL: + # started playing a new track + # get the applescript track and make sure it's the same (compare name) + iTunes = SBApplication.applicationWithBundleIdentifier_("com.apple.iTunes") + iTunesTrack = iTunes.currentTrack() + if iTunesTrack.name() == noteInfo["Name"]: + self.trackChanged_iTunesTrack_(noteInfo, iTunesTrack) + self.lastPersistentID = persistentID + else: + NSLog(u"Track Not Posted: You have not provided PostTunes with the Handler URL to use.") + if self.warnPreferences: + alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_("Track Not Posted", "Open PostTunes Preferences", "Ignore", None, u"You have not provided PostTunes with the Handler URL to use.") + if alert.runModal() == NSAlertDefaultReturn: + self.preferencesWindow.makeKeyAndOrderFront_(self) + elif alert.runModal() == NSAlertAlternateReturn: + self.warnPreferences = False + + else: + self.lastPersistentID = None + # stopped playing + + def trackChanged_iTunesTrack_(self, noteInfo, iTunesTrack): + trackData = {"title": noteInfo["Name"]} + if self.secretKey: + trackData["key"] = self.secretKey + if "Artist" in noteInfo: + trackData["artist"] = noteInfo["Artist"] + if "Album" in noteInfo: + trackData["album"] = noteInfo["Album"] + if "Store URL" in noteInfo: + trackData["url"] = noteInfo["Store URL"] + iTunesArtworks = iTunesTrack.artworks() + if len(iTunesArtworks) >= 1: + artwork = iTunesArtworks[0] + artworkTIFF = artwork.data().TIFFRepresentation() + artworkPNG = NSBitmapImageRep.imageRepWithData_(artworkTIFF).representationUsingType_properties_(NSPNGFileType, None) + trackData["artpng"] = b64encode(artworkPNG.bytes()) + try: + urlopen(self.handlerURL, urlencode(trackData)) + except URLError: + NSLog(u"PostTunes encountered an error when attempting to submit a track to: %s" % self.handlerURL) + if self.warnFailure: + alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_("Track Not Posted", "Open PostTunes Preferences", "Ignore", None, (u"PostTunes encountered an error when attempting to submit a track to:\n%s" % self.handlerURL)) + if alert.runModal() == NSAlertDefaultReturn: + self.preferencesWindow.makeKeyAndOrderFront_(self) + elif alert.runModal() == NSAlertAlternateReturn: + self.warnFailure = False diff --git a/PostTunes_Prefix.pch b/PostTunes_Prefix.pch new file mode 100644 index 0000000..17f0265 --- /dev/null +++ b/PostTunes_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'PostTunes' target in the 'PostTunes' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/main.m b/main.m new file mode 100644 index 0000000..20781c6 --- /dev/null +++ b/main.m @@ -0,0 +1,49 @@ +// +// main.m +// PostTunes +// +// Created by Joseph Spiros on 3/5/09. +// Copyright iThink Software 2009. All rights reserved. +// + +#import +#import + +int main(int argc, char *argv[]) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSBundle *mainBundle = [NSBundle mainBundle]; + NSString *resourcePath = [mainBundle resourcePath]; + NSArray *pythonPathArray = [NSArray arrayWithObjects: resourcePath, [resourcePath stringByAppendingPathComponent:@"PyObjC"], nil]; + + setenv("PYTHONPATH", [[pythonPathArray componentsJoinedByString:@":"] UTF8String], 1); + + NSArray *possibleMainExtensions = [NSArray arrayWithObjects: @"py", @"pyc", @"pyo", nil]; + NSString *mainFilePath = nil; + + for (NSString *possibleMainExtension in possibleMainExtensions) { + mainFilePath = [mainBundle pathForResource: @"main" ofType: possibleMainExtension]; + if ( mainFilePath != nil ) break; + } + + if ( !mainFilePath ) { + [NSException raise: NSInternalInconsistencyException format: @"%s:%d main() Failed to find the Main.{py,pyc,pyo} file in the application wrapper's Resources directory.", __FILE__, __LINE__]; + } + + Py_SetProgramName("/usr/bin/python"); + Py_Initialize(); + PySys_SetArgv(argc, (char **)argv); + + const char *mainFilePathPtr = [mainFilePath UTF8String]; + FILE *mainFile = fopen(mainFilePathPtr, "r"); + int result = PyRun_SimpleFile(mainFile, (char *)[[mainFilePath lastPathComponent] UTF8String]); + + if ( result != 0 ) + [NSException raise: NSInternalInconsistencyException + format: @"%s:%d main() PyRun_SimpleFile failed with file '%@'. See console for errors.", __FILE__, __LINE__, mainFilePath]; + + [pool drain]; + + return result; +} diff --git a/main.py b/main.py new file mode 100644 index 0000000..b934753 --- /dev/null +++ b/main.py @@ -0,0 +1,20 @@ +# +# main.py +# PostTunes +# +# Created by Joseph Spiros on 3/5/09. +# Copyright iThink Software 2009. All rights reserved. +# + +#import modules required by application +import objc +import Foundation +import AppKit + +from PyObjCTools import AppHelper + +# import modules containing classes required to start application and load MainMenu.nib +import PostTunesAppDelegate + +# pass control to AppKit +AppHelper.runEventLoop()