diff --git a/Kyapchar.xcodeproj/project.pbxproj b/Kyapchar.xcodeproj/project.pbxproj index 0c7dfe4..fe2f800 100644 --- a/Kyapchar.xcodeproj/project.pbxproj +++ b/Kyapchar.xcodeproj/project.pbxproj @@ -7,23 +7,25 @@ objects = { /* Begin PBXBuildFile section */ - 08DE4F871DA00B9000D969DA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08DE4F861DA00B9000D969DA /* AppDelegate.swift */; }; - 08DE4F891DA00B9000D969DA /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08DE4F881DA00B9000D969DA /* ViewController.swift */; }; - 08DE4F8B1DA00B9000D969DA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 08DE4F8A1DA00B9000D969DA /* Assets.xcassets */; }; - 08DE4F8E1DA00B9000D969DA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 08DE4F8C1DA00B9000D969DA /* Main.storyboard */; }; + 086724DC1DC86E07007033BB /* Recorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 086724DB1DC86E07007033BB /* Recorder.swift */; }; + 089CD7551DC7B742005067DB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 089CD7541DC7B742005067DB /* AppDelegate.swift */; }; + 089CD7571DC7B742005067DB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 089CD7561DC7B742005067DB /* Assets.xcassets */; }; + 089CD75A1DC7B742005067DB /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 089CD7581DC7B742005067DB /* MainMenu.xib */; }; + 089CD7641DC85A3C005067DB /* MenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 089CD7631DC85A3C005067DB /* MenuController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 08DE4F831DA00B9000D969DA /* Kyapchar.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Kyapchar.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 08DE4F861DA00B9000D969DA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 08DE4F881DA00B9000D969DA /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 08DE4F8A1DA00B9000D969DA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 08DE4F8D1DA00B9000D969DA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 08DE4F8F1DA00B9000D969DA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 086724DB1DC86E07007033BB /* Recorder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Recorder.swift; sourceTree = ""; }; + 089CD7511DC7B742005067DB /* Kyapchar.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Kyapchar.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 089CD7541DC7B742005067DB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 089CD7561DC7B742005067DB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 089CD7591DC7B742005067DB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 089CD75B1DC7B742005067DB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 089CD7631DC85A3C005067DB /* MenuController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 08DE4F801DA00B9000D969DA /* Frameworks */ = { + 089CD74E1DC7B742005067DB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -33,30 +35,31 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 08DE4F7A1DA00B9000D969DA = { + 089CD7481DC7B742005067DB = { isa = PBXGroup; children = ( - 08DE4F851DA00B9000D969DA /* Kyapchar */, - 08DE4F841DA00B9000D969DA /* Products */, + 089CD7531DC7B742005067DB /* Kyapchar */, + 089CD7521DC7B742005067DB /* Products */, ); sourceTree = ""; }; - 08DE4F841DA00B9000D969DA /* Products */ = { + 089CD7521DC7B742005067DB /* Products */ = { isa = PBXGroup; children = ( - 08DE4F831DA00B9000D969DA /* Kyapchar.app */, + 089CD7511DC7B742005067DB /* Kyapchar.app */, ); name = Products; sourceTree = ""; }; - 08DE4F851DA00B9000D969DA /* Kyapchar */ = { + 089CD7531DC7B742005067DB /* Kyapchar */ = { isa = PBXGroup; children = ( - 08DE4F861DA00B9000D969DA /* AppDelegate.swift */, - 08DE4F881DA00B9000D969DA /* ViewController.swift */, - 08DE4F8A1DA00B9000D969DA /* Assets.xcassets */, - 08DE4F8C1DA00B9000D969DA /* Main.storyboard */, - 08DE4F8F1DA00B9000D969DA /* Info.plist */, + 089CD7631DC85A3C005067DB /* MenuController.swift */, + 086724DB1DC86E07007033BB /* Recorder.swift */, + 089CD7541DC7B742005067DB /* AppDelegate.swift */, + 089CD7561DC7B742005067DB /* Assets.xcassets */, + 089CD7581DC7B742005067DB /* MainMenu.xib */, + 089CD75B1DC7B742005067DB /* Info.plist */, ); path = Kyapchar; sourceTree = ""; @@ -64,13 +67,13 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 08DE4F821DA00B9000D969DA /* Kyapchar */ = { + 089CD7501DC7B742005067DB /* Kyapchar */ = { isa = PBXNativeTarget; - buildConfigurationList = 08DE4F921DA00B9000D969DA /* Build configuration list for PBXNativeTarget "Kyapchar" */; + buildConfigurationList = 089CD75E1DC7B742005067DB /* Build configuration list for PBXNativeTarget "Kyapchar" */; buildPhases = ( - 08DE4F7F1DA00B9000D969DA /* Sources */, - 08DE4F801DA00B9000D969DA /* Frameworks */, - 08DE4F811DA00B9000D969DA /* Resources */, + 089CD74D1DC7B742005067DB /* Sources */, + 089CD74E1DC7B742005067DB /* Frameworks */, + 089CD74F1DC7B742005067DB /* Resources */, ); buildRules = ( ); @@ -78,25 +81,25 @@ ); name = Kyapchar; productName = Kyapchar; - productReference = 08DE4F831DA00B9000D969DA /* Kyapchar.app */; + productReference = 089CD7511DC7B742005067DB /* Kyapchar.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 08DE4F7B1DA00B9000D969DA /* Project object */ = { + 089CD7491DC7B742005067DB /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 0730; ORGANIZATIONNAME = "Vishal Telangre"; TargetAttributes = { - 08DE4F821DA00B9000D969DA = { + 089CD7501DC7B742005067DB = { CreatedOnToolsVersion = 7.3.1; }; }; }; - buildConfigurationList = 08DE4F7E1DA00B9000D969DA /* Build configuration list for PBXProject "Kyapchar" */; + buildConfigurationList = 089CD74C1DC7B742005067DB /* Build configuration list for PBXProject "Kyapchar" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -104,53 +107,54 @@ en, Base, ); - mainGroup = 08DE4F7A1DA00B9000D969DA; - productRefGroup = 08DE4F841DA00B9000D969DA /* Products */; + mainGroup = 089CD7481DC7B742005067DB; + productRefGroup = 089CD7521DC7B742005067DB /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 08DE4F821DA00B9000D969DA /* Kyapchar */, + 089CD7501DC7B742005067DB /* Kyapchar */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 08DE4F811DA00B9000D969DA /* Resources */ = { + 089CD74F1DC7B742005067DB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 08DE4F8B1DA00B9000D969DA /* Assets.xcassets in Resources */, - 08DE4F8E1DA00B9000D969DA /* Main.storyboard in Resources */, + 089CD7571DC7B742005067DB /* Assets.xcassets in Resources */, + 089CD75A1DC7B742005067DB /* MainMenu.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 08DE4F7F1DA00B9000D969DA /* Sources */ = { + 089CD74D1DC7B742005067DB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 08DE4F891DA00B9000D969DA /* ViewController.swift in Sources */, - 08DE4F871DA00B9000D969DA /* AppDelegate.swift in Sources */, + 086724DC1DC86E07007033BB /* Recorder.swift in Sources */, + 089CD7551DC7B742005067DB /* AppDelegate.swift in Sources */, + 089CD7641DC85A3C005067DB /* MenuController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ - 08DE4F8C1DA00B9000D969DA /* Main.storyboard */ = { + 089CD7581DC7B742005067DB /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( - 08DE4F8D1DA00B9000D969DA /* Base */, + 089CD7591DC7B742005067DB /* Base */, ); - name = Main.storyboard; + name = MainMenu.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - 08DE4F901DA00B9000D969DA /* Debug */ = { + 089CD75C1DC7B742005067DB /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -195,7 +199,7 @@ }; name = Debug; }; - 08DE4F911DA00B9000D969DA /* Release */ = { + 089CD75D1DC7B742005067DB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -232,7 +236,7 @@ }; name = Release; }; - 08DE4F931DA00B9000D969DA /* Debug */ = { + 089CD75F1DC7B742005067DB /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; @@ -244,7 +248,7 @@ }; name = Debug; }; - 08DE4F941DA00B9000D969DA /* Release */ = { + 089CD7601DC7B742005067DB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; @@ -259,25 +263,25 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 08DE4F7E1DA00B9000D969DA /* Build configuration list for PBXProject "Kyapchar" */ = { + 089CD74C1DC7B742005067DB /* Build configuration list for PBXProject "Kyapchar" */ = { isa = XCConfigurationList; buildConfigurations = ( - 08DE4F901DA00B9000D969DA /* Debug */, - 08DE4F911DA00B9000D969DA /* Release */, + 089CD75C1DC7B742005067DB /* Debug */, + 089CD75D1DC7B742005067DB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 08DE4F921DA00B9000D969DA /* Build configuration list for PBXNativeTarget "Kyapchar" */ = { + 089CD75E1DC7B742005067DB /* Build configuration list for PBXNativeTarget "Kyapchar" */ = { isa = XCConfigurationList; buildConfigurations = ( - 08DE4F931DA00B9000D969DA /* Debug */, - 08DE4F941DA00B9000D969DA /* Release */, + 089CD75F1DC7B742005067DB /* Debug */, + 089CD7601DC7B742005067DB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 08DE4F7B1DA00B9000D969DA /* Project object */; + rootObject = 089CD7491DC7B742005067DB /* Project object */; } diff --git a/Kyapchar.xcodeproj/xcuserdata/vishaltelangre.xcuserdatad/xcschemes/Kyapchar.xcscheme b/Kyapchar.xcodeproj/xcuserdata/vishaltelangre.xcuserdatad/xcschemes/Kyapchar.xcscheme index b279b64..1d8a934 100644 --- a/Kyapchar.xcodeproj/xcuserdata/vishaltelangre.xcuserdatad/xcschemes/Kyapchar.xcscheme +++ b/Kyapchar.xcodeproj/xcuserdata/vishaltelangre.xcuserdatad/xcschemes/Kyapchar.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> @@ -32,7 +32,7 @@ @@ -55,7 +55,7 @@ runnableDebuggingMode = "0"> @@ -74,7 +74,7 @@ runnableDebuggingMode = "0"> diff --git a/Kyapchar.xcodeproj/xcuserdata/vishaltelangre.xcuserdatad/xcschemes/xcschememanagement.plist b/Kyapchar.xcodeproj/xcuserdata/vishaltelangre.xcuserdatad/xcschemes/xcschememanagement.plist index e605c25..5723e3b 100644 --- a/Kyapchar.xcodeproj/xcuserdata/vishaltelangre.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Kyapchar.xcodeproj/xcuserdata/vishaltelangre.xcuserdatad/xcschemes/xcschememanagement.plist @@ -12,7 +12,7 @@ SuppressBuildableAutocreation - 08DE4F821DA00B9000D969DA + 089CD7501DC7B742005067DB primary diff --git a/Kyapchar/AppDelegate.swift b/Kyapchar/AppDelegate.swift index eb2cf24..5f0d3a6 100644 --- a/Kyapchar/AppDelegate.swift +++ b/Kyapchar/AppDelegate.swift @@ -2,7 +2,7 @@ // AppDelegate.swift // Kyapchar // -// Created by Vishal Telangre on 10/1/16. +// Created by Vishal Telangre on 10/31/16. // Copyright © 2016 Vishal Telangre. All rights reserved. // @@ -10,9 +10,7 @@ import Cocoa @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { - - - + func applicationDidFinishLaunching(aNotification: NSNotification) { // Insert code here to initialize your application } @@ -21,6 +19,5 @@ class AppDelegate: NSObject, NSApplicationDelegate { // Insert code here to tear down your application } - } diff --git a/Kyapchar/Assets.xcassets/pause.imageset/Contents.json b/Kyapchar/Assets.xcassets/pause.imageset/Contents.json index 9172c83..f135be3 100644 --- a/Kyapchar/Assets.xcassets/pause.imageset/Contents.json +++ b/Kyapchar/Assets.xcassets/pause.imageset/Contents.json @@ -1,21 +1,20 @@ { "images" : [ { - "idiom" : "universal", + "idiom" : "mac", "scale" : "1x" }, { - "idiom" : "universal", + "idiom" : "mac", "filename" : "pause.png", "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" } } \ No newline at end of file diff --git a/Kyapchar/Assets.xcassets/pause.imageset/pause.png b/Kyapchar/Assets.xcassets/pause.imageset/pause.png index c47dfb3..349d51d 100644 Binary files a/Kyapchar/Assets.xcassets/pause.imageset/pause.png and b/Kyapchar/Assets.xcassets/pause.imageset/pause.png differ diff --git a/Kyapchar/Assets.xcassets/record.imageset/Contents.json b/Kyapchar/Assets.xcassets/record.imageset/Contents.json index 1a9c49e..1b94665 100644 --- a/Kyapchar/Assets.xcassets/record.imageset/Contents.json +++ b/Kyapchar/Assets.xcassets/record.imageset/Contents.json @@ -1,21 +1,20 @@ { "images" : [ { - "idiom" : "universal", + "idiom" : "mac", "scale" : "1x" }, { - "idiom" : "universal", + "idiom" : "mac", "filename" : "record.png", "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" } } \ No newline at end of file diff --git a/Kyapchar/Assets.xcassets/record.imageset/record.png b/Kyapchar/Assets.xcassets/record.imageset/record.png index 8964569..03e3e49 100644 Binary files a/Kyapchar/Assets.xcassets/record.imageset/record.png and b/Kyapchar/Assets.xcassets/record.imageset/record.png differ diff --git a/Kyapchar/Assets.xcassets/resume.imageset/Contents.json b/Kyapchar/Assets.xcassets/resume.imageset/Contents.json index 5327430..19cc21f 100644 --- a/Kyapchar/Assets.xcassets/resume.imageset/Contents.json +++ b/Kyapchar/Assets.xcassets/resume.imageset/Contents.json @@ -1,21 +1,20 @@ { "images" : [ { - "idiom" : "universal", + "idiom" : "mac", "scale" : "1x" }, { - "idiom" : "universal", + "idiom" : "mac", "filename" : "resume.png", "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" } } \ No newline at end of file diff --git a/Kyapchar/Assets.xcassets/resume.imageset/resume.png b/Kyapchar/Assets.xcassets/resume.imageset/resume.png index 7c30eb5..4011347 100644 Binary files a/Kyapchar/Assets.xcassets/resume.imageset/resume.png and b/Kyapchar/Assets.xcassets/resume.imageset/resume.png differ diff --git a/Kyapchar/Assets.xcassets/stop.imageset/Contents.json b/Kyapchar/Assets.xcassets/stop.imageset/Contents.json index 2a8a7fa..76814df 100644 --- a/Kyapchar/Assets.xcassets/stop.imageset/Contents.json +++ b/Kyapchar/Assets.xcassets/stop.imageset/Contents.json @@ -1,21 +1,20 @@ { "images" : [ { - "idiom" : "universal", + "idiom" : "mac", "scale" : "1x" }, { - "idiom" : "universal", + "idiom" : "mac", "filename" : "stop.png", "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" } } \ No newline at end of file diff --git a/Kyapchar/Assets.xcassets/stop.imageset/stop.png b/Kyapchar/Assets.xcassets/stop.imageset/stop.png index e290e86..e3c6d89 100644 Binary files a/Kyapchar/Assets.xcassets/stop.imageset/stop.png and b/Kyapchar/Assets.xcassets/stop.imageset/stop.png differ diff --git a/Kyapchar/Base.lproj/Main.storyboard b/Kyapchar/Base.lproj/Main.storyboard deleted file mode 100644 index 68c308b..0000000 --- a/Kyapchar/Base.lproj/Main.storyboard +++ /dev/null @@ -1,532 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Kyapchar/Base.lproj/MainMenu.xib b/Kyapchar/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..10d0780 --- /dev/null +++ b/Kyapchar/Base.lproj/MainMenu.xib @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Kyapchar/Info.plist b/Kyapchar/Info.plist index d344332..b47c35a 100644 --- a/Kyapchar/Info.plist +++ b/Kyapchar/Info.plist @@ -17,17 +17,21 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.0.2 + 0.0.3 CFBundleSignature ???? CFBundleVersion 1 + LSApplicationCategoryType + public.app-category.utilities LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) + LSUIElement + NSHumanReadableCopyright Copyright © 2016 Vishal Telangre. All rights reserved. - NSMainStoryboardFile - Main + NSMainNibFile + MainMenu NSPrincipalClass NSApplication diff --git a/Kyapchar/MenuController.swift b/Kyapchar/MenuController.swift new file mode 100644 index 0000000..f5afa6e --- /dev/null +++ b/Kyapchar/MenuController.swift @@ -0,0 +1,90 @@ +// +// MenuController.swift +// Kyapchar +// +// Created by Vishal Telangre on 11/1/16. +// Copyright © 2016 Vishal Telangre. All rights reserved. +// + +import Cocoa + +class MenuController: NSObject { + + @IBOutlet weak var barMenu: NSMenu! + @IBOutlet weak var recordStopItem: NSMenuItem! + @IBOutlet weak var pauseResumeItem: NSMenuItem! + + let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSSquareStatusItemLength) + + var recorder: Recorder! + + @IBAction func onRecordStopItemClick(sender: NSMenuItem) { + if recorder.recording { + recorder.stop() + recordStopItem.enabled = false + recordStopItem.title = "Please wait..." + } else { + recorder.start() + } + } + + @IBAction func onPauseResumeItemClick(sender: NSMenuItem) { + if recorder.paused { + recorder.resume() + } else { + recorder.pause() + } + } + + @IBAction func onQuitItemClick(sender: NSMenuItem) { + NSApplication.sharedApplication().terminate(self) + } + + override func awakeFromNib() { + statusItem.button?.image = NSImage(named: "record") + + pauseResumeItem.enabled = false + + statusItem.menu = barMenu + recorder = Recorder(delegate: self) + } + +} + +extension MenuController: RecorderDelegate { + + func recordingDidStart(recordingInfo: RecordingInfo?) { + recordStopItem.title = "Stop" + statusItem.button?.image = NSImage(named: "stop") + + pauseResumeItem.enabled = true + pauseResumeItem.title = "Pause" + } + + func recordingDidStop(recordingInfo: RecordingInfo?) { + recordStopItem.enabled = true + recordStopItem.title = "Record" + statusItem.button?.image = NSImage(named: "record") + + pauseResumeItem.enabled = false + pauseResumeItem.title = "Pause" + + recorder = nil + recorder = Recorder(delegate: self) + + if recordingInfo?.location != nil { + NSWorkspace.sharedWorkspace().activateFileViewerSelectingURLs([recordingInfo!.location]) + } + } + + func recordingDidResume(recordingInfo: RecordingInfo?) { + pauseResumeItem.title = "Pause" + statusItem.button?.image = NSImage(named: "stop") + } + + func recordingDidPause(recordingInfo: RecordingInfo?) { + pauseResumeItem.title = "Resume" + statusItem.button?.image = NSImage(named: "pause") + } + +} \ No newline at end of file diff --git a/Kyapchar/ViewController.swift b/Kyapchar/Recorder.swift similarity index 62% rename from Kyapchar/ViewController.swift rename to Kyapchar/Recorder.swift index db50530..b36987c 100644 --- a/Kyapchar/ViewController.swift +++ b/Kyapchar/Recorder.swift @@ -1,74 +1,54 @@ // -// ViewController.swift +// Recorder.swift // Kyapchar // -// Created by Vishal Telangre on 10/1/16. +// Created by Vishal Telangre on 11/1/16. // Copyright © 2016 Vishal Telangre. All rights reserved. // -import Cocoa +import Foundation import AVFoundation -import AppKit -class ViewController: NSViewController { +struct RecordingInfo { + var location: NSURL + var duration: Int + var size: Float +} + +protocol RecorderDelegate { + func recordingDidStart(recordingInfo: RecordingInfo?) + func recordingDidStop(recordingInfo: RecordingInfo?) + func recordingDidResume(recordingInfo: RecordingInfo?) + func recordingDidPause(recordingInfo: RecordingInfo?) +} + +class Recorder: NSObject { + + var delegate: RecorderDelegate? + var session: AVCaptureSession! var output: AVCaptureMovieFileOutput! var audioRecorder: AVAudioRecorder! var castedVideoURL = NSURL() var micAudioURL = NSURL() var finalVideoURL = NSURL() - var storedFileInfo: [[String]] = [] + var recordingInfo: RecordingInfo! + var recording = false + var paused = false let micAudioRecordSettings = [AVSampleRateKey : NSNumber(float: Float(44100.0)), - AVFormatIDKey : NSNumber(int: Int32(kAudioFormatMPEG4AAC)), - AVNumberOfChannelsKey : NSNumber(int: 1), - AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Medium.rawValue))] + AVFormatIDKey : NSNumber(int: Int32(kAudioFormatMPEG4AAC)), + AVNumberOfChannelsKey : NSNumber(int: 1), + AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Medium.rawValue))] - @IBOutlet weak var recordButton: NSButton! - @IBOutlet weak var debugInfoLabel: NSTextField! - @IBOutlet weak var pauseResumeButton: NSButton! - @IBOutlet weak var storedFileInfoTableView: NSTableView! - - @IBAction func onRecordClick(sender: NSButton) { - if (sender.state == NSOffState) { - sender.image = NSImage(named: "record") - sender.toolTip = "Start Recording" - pauseResumeButton.hidden = true - stopRecording() - } else { - sender.image = NSImage(named: "stop") - sender.toolTip = "Stop Recording" - pauseResumeButton.hidden = false - debugInfoLabel.stringValue = "" - startRecording() - } + init(delegate: RecorderDelegate) { + self.delegate = delegate } - @IBAction func onPauseResumeClick(sender: NSButton) { - if output.recordingPaused { - output.resumeRecording() - audioRecorder.record() - } else { - output.pauseRecording() - audioRecorder.pause() - } - } - - override func viewDidLoad() { - super.viewDidLoad() - pauseResumeButton.hidden = true - pauseResumeButton.image = NSImage(named: "pause") - pauseResumeButton.toolTip = "Pause Recording" - - storedFileInfoTableView.setDataSource(self) - } - - func startRecording() { - storedFileInfo = [] + func start() { session = AVCaptureSession() output = AVCaptureMovieFileOutput() (castedVideoURL, micAudioURL, finalVideoURL) = filePaths() - storedFileInfoTableView.reloadData() let input = AVCaptureScreenInput(displayID: CGMainDisplayID()) let screen = NSScreen.mainScreen()! @@ -78,6 +58,7 @@ class ViewController: NSViewController { audioRecorder = try AVAudioRecorder(URL: micAudioURL, settings: micAudioRecordSettings) } catch { print("Cannot initialize AVAudioRecorder: \(error)") + return } audioRecorder?.meteringEnabled = true @@ -99,14 +80,31 @@ class ViewController: NSViewController { session?.startRunning() output!.startRecordingToOutputFileURL(castedVideoURL, recordingDelegate: self) - audioRecorder.record() + + recording = true + delegate?.recordingDidStart(nil) } - func stopRecording() { + func stop() { if output != nil { + recording = false output?.stopRecording() - audioRecorder?.stop() - debugInfoLabel.stringValue = "Please wait..." + } + } + + func pause() { + if output.recording { + output.pauseRecording() + paused = true + delegate?.recordingDidPause(nil) + } + } + + func resume() { + if output.recordingPaused { + output.resumeRecording() + paused = false + delegate?.recordingDidResume(nil) } } @@ -124,6 +122,7 @@ class ViewController: NSViewController { try compositionAudioTrack.insertTimeRange(micAudioTimeRange, ofTrack: track, atTime: kCMTimeZero) } catch { print("Error while adding micAudioAsset to compositionAudioTrack: \(error)") + self.delegate?.recordingDidStop(nil) } do { @@ -131,6 +130,7 @@ class ViewController: NSViewController { try compositionVideoTrack.insertTimeRange(castedVideoTimeRange, ofTrack: track, atTime: kCMTimeZero) } catch { print("Error while adding castedVideoAsset to compositionVideoTrack: \(error)") + self.delegate?.recordingDidStop(nil) } let assetExportSession = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) @@ -139,24 +139,24 @@ class ViewController: NSViewController { assetExportSession?.exportAsynchronouslyWithCompletionHandler({ dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), { if assetExportSession?.status == AVAssetExportSessionStatus.Completed { - let duration: Int = Int(CMTimeGetSeconds((assetExportSession?.asset.duration)!)) - var fileSize : Float = 0.0 + var size: Float = 0.0 do { let attr : NSDictionary? = try NSFileManager.defaultManager().attributesOfItemAtPath(self.finalVideoURL.path!) if let _attr = attr { - fileSize = Float(_attr.fileSize()/(1024*1024)); + size = Float(_attr.fileSize()/(1024*1024)); } } catch { print("Error while fetching final video file size: \(error)") } - self.storedFileInfo = [["Duration", "\(self.formatDuration(duration)) Seconds"], - ["Location", self.finalVideoURL.absoluteString.stringByReplacingOccurrencesOfString("file://" + NSHomeDirectory(), withString: "~")], - ["Size", "\(String(format: "%.2f", fileSize)) MB"]] + let duration = Int(CMTimeGetSeconds((assetExportSession?.asset.duration)!)) + let location = self.finalVideoURL + self.recordingInfo = RecordingInfo(location: location, duration: duration, size: size) + } else { print("Export failed") - self.storedFileInfo = [["Error", "Export Failed"]] + self.recordingInfo = nil } do { @@ -165,11 +165,8 @@ class ViewController: NSViewController { } catch { print("Error while deleting temporary files: \(error)") } - - dispatch_async(dispatch_get_main_queue(), { - self.debugInfoLabel.stringValue = "" - self.storedFileInfoTableView.reloadData() - }) + + self.delegate?.recordingDidStop(self.recordingInfo) }) }) } @@ -185,44 +182,32 @@ class ViewController: NSViewController { let tempVideoFilePath = NSURL(fileURLWithPath: "/tmp/\(filename).mp4") let tempMicAudioFilePath = NSURL(fileURLWithPath: "/tmp/\(filename).m4a") - print("Paths: tempVideoFilePath: \(tempVideoFilePath), tempMicAudioFilePath: \(tempMicAudioFilePath), finalVideoPath: \(finalVideoPath)") - return (tempVideoFilePath, tempMicAudioFilePath, finalVideoPath) } - - func formatDuration(seconds: Int) -> String { - let hrs: Int = Int(seconds / 3600) - let mins: Int = Int((seconds % 3600) / 60) - let secs: Int = Int((seconds % 3600) % 60) - - return String(format: "%02d:%02d:%02d", hrs, mins, secs) - } } -extension ViewController: AVCaptureFileOutputRecordingDelegate { +extension Recorder: AVCaptureFileOutputRecordingDelegate { func captureOutput(captureOutput: AVCaptureFileOutput!, didPauseRecordingToOutputFileAtURL fileURL: NSURL!, fromConnections connections: [AnyObject]!) { - pauseResumeButton.image = NSImage(named: "resume") - pauseResumeButton.toolTip = "Resume Recording" + audioRecorder.pause() } func captureOutput(captureOutput: AVCaptureFileOutput!, didResumeRecordingToOutputFileAtURL fileURL: NSURL!, fromConnections connections: [AnyObject]!) { - pauseResumeButton.image = NSImage(named: "pause") - pauseResumeButton.toolTip = "Pause Recording" - - NSApp.mainWindow?.miniaturize(self) + audioRecorder.record() } func captureOutput(captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAtURL fileURL: NSURL!, fromConnections connections: [AnyObject]!) { - NSApp.mainWindow?.miniaturize(self) + audioRecorder.record() } func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!) { if (error != nil) { debugPrint(error) + return } dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) { self.session?.stopRunning() + self.audioRecorder?.stop() self.generateFinalVideo() @@ -232,19 +217,3 @@ extension ViewController: AVCaptureFileOutputRecordingDelegate { } } } - -extension ViewController: NSTableViewDataSource { - func numberOfRowsInTableView(tableView: NSTableView) -> Int { - return storedFileInfo.count - } - - func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int) -> AnyObject? { - let item = storedFileInfo[row] - - if tableColumn?.identifier == "key" { - return item[0] - } else { - return item[1] - } - } -} \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 068a681..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2016 Vishal Telangre - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md index d3cb9e9..d377b64 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,14 @@ # Kyapchar -Simple screen and microphone audio recorder for Mac - -## Preview +![kyapchar](https://cloud.githubusercontent.com/assets/876195/19885931/51c02120-a047-11e6-9dc2-6a6e68e8520b.png) -Watch this demo screencast captured using Kyapchar (v0.0.1) - https://youtu.be/B4RfdJCZ6yU. - -![monosnap 2016-10-22 21-22-17](https://cloud.githubusercontent.com/assets/876195/19620567/e80b1d9e-989d-11e6-9757-4868b7fdba96.png) -![kyapchar 2016-10-22 21-21-16](https://cloud.githubusercontent.com/assets/876195/19620566/e80986c8-989d-11e6-85f2-2662aad6bfb6.png) +Simple screen and microphone audio recorder for Mac +## Preview -## Notice +Preview is a GIF image, which could take some time to load. Please be patient! -This software is in its very early development stage. It is not very well tested. Therefore it may cause unexpected problems. -So be cautious while using it. +![preview.gif](https://cloud.githubusercontent.com/assets/876195/19885741/4364de82-a046-11e6-90e2-810c71f37477.gif) ## Download @@ -23,12 +18,9 @@ Download and install it from [releases](https://github.com/vishaltelangre/Kyapch Open `Kyapchar.xcodeproj` with XCode, and hit `Command (⌘)-R` keys to build and run it locally. -## Credits - -Icons made by [Pixel Buddha](http://www.flaticon.com/authors/pixel-buddha "Pixel Buddha") from [www.flaticon.com](http://www.flaticon.com "Flaticon") is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/ "Creative Commons BY 3.0"). - ## Copyright and License Copyright (c) 2016, Vishal Telangre. All Rights Reserved. This project is licenced under the [MIT License](LICENSE). +