From 4576f4663d3038bef2935b14f7e86602f1ee0a93 Mon Sep 17 00:00:00 2001 From: Nicolas HOAREAU Date: Wed, 23 Mar 2016 00:20:08 +0100 Subject: [PATCH] Add SoundManager to play sound and infinite loop (double click on cell to stop sound) --- QuickSound.xcodeproj/project.pbxproj | 12 ++++ QuickSound/PopoverViewController.swift | 24 +++---- QuickSound/SoundManager.swift | 89 ++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 QuickSound/SoundManager.swift diff --git a/QuickSound.xcodeproj/project.pbxproj b/QuickSound.xcodeproj/project.pbxproj index 564e102..5c2c5f5 100644 --- a/QuickSound.xcodeproj/project.pbxproj +++ b/QuickSound.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 2228E3051CA1B1CE0041056A /* Sound+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2228E3031CA1B1CE0041056A /* Sound+CoreDataProperties.swift */; }; 2228E3061CA1B1CE0041056A /* Sound.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2228E3041CA1B1CE0041056A /* Sound.swift */; }; 2228E3081CA1B3380041056A /* DataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2228E3071CA1B3380041056A /* DataManager.swift */; }; + 3717907A1CA1FADC00A622A5 /* SoundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371790791CA1FADC00A622A5 /* SoundManager.swift */; }; 92BE1D781C9C4B9B004F13BB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92BE1D771C9C4B9B004F13BB /* AppDelegate.swift */; }; 92BE1D7A1C9C4B9B004F13BB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 92BE1D791C9C4B9B004F13BB /* Assets.xcassets */; }; 92BE1D861C9C4CA5004F13BB /* StatusItemController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92BE1D851C9C4CA5004F13BB /* StatusItemController.swift */; }; @@ -28,6 +29,7 @@ 2228E3031CA1B1CE0041056A /* Sound+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Sound+CoreDataProperties.swift"; sourceTree = ""; }; 2228E3041CA1B1CE0041056A /* Sound.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sound.swift; sourceTree = ""; }; 2228E3071CA1B3380041056A /* DataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataManager.swift; sourceTree = ""; }; + 371790791CA1FADC00A622A5 /* SoundManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoundManager.swift; sourceTree = ""; }; 92BE1D741C9C4B9B004F13BB /* QuickSound.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = QuickSound.app; sourceTree = BUILT_PRODUCTS_DIR; }; 92BE1D771C9C4B9B004F13BB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 92BE1D791C9C4B9B004F13BB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -51,6 +53,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 371790781CA1FABF00A622A5 /* Manager */ = { + isa = PBXGroup; + children = ( + 371790791CA1FADC00A622A5 /* SoundManager.swift */, + ); + name = Manager; + sourceTree = ""; + }; 92BE1D6B1C9C4B9B004F13BB = { isa = PBXGroup; children = ( @@ -71,6 +81,7 @@ isa = PBXGroup; children = ( 92BE1D771C9C4B9B004F13BB /* AppDelegate.swift */, + 371790781CA1FABF00A622A5 /* Manager */, 92BE1D8C1C9C5079004F13BB /* Status Item */, 92BE1D8B1C9C506E004F13BB /* Popover */, E96D54071C9CAC08006286EB /* Model */, @@ -225,6 +236,7 @@ E942CF291CA1FBF8004FBCD2 /* Utils.swift in Sources */, 92BE1D891C9C506B004F13BB /* PopoverViewController.swift in Sources */, 2228E3061CA1B1CE0041056A /* Sound.swift in Sources */, + 3717907A1CA1FADC00A622A5 /* SoundManager.swift in Sources */, 92BE1D781C9C4B9B004F13BB /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/QuickSound/PopoverViewController.swift b/QuickSound/PopoverViewController.swift index 296b8ea..78bf6be 100644 --- a/QuickSound/PopoverViewController.swift +++ b/QuickSound/PopoverViewController.swift @@ -14,8 +14,7 @@ class PopoverViewController: NSViewController { @IBOutlet var soundsArrayController: NSArrayController! @IBOutlet weak var tableView: NSTableView! - private var soundPlayer:[NSSound] = [] - + private let soundManager:SoundManager = SoundManager() // MARK: - Lifecycle @@ -32,7 +31,7 @@ class PopoverViewController: NSViewController { super.viewWillDisappear() // Deselect table view - self.tableView.deselectAll(nil) + self.tableView.deselectAll(nil) } @@ -44,18 +43,13 @@ class PopoverViewController: NSViewController { guard let soundObject = arrangedObjects[tableView.clickedRow] as? Sound else { return } // Play sound - if let soundURL = NSURL(string: soundObject.filePath!) { - let sound = NSSound(contentsOfURL: soundURL, byReference: true) - let successOrNil = sound?.play() - - // Show alert - if successOrNil == nil || !successOrNil! { - let alert = NSAlert() - alert.messageText = "Impossible de lire le son" - alert.informativeText = "Le fichier est invalide ou introuvable." - alert.alertStyle = .CriticalAlertStyle - alert.runModal() - } + let repeatEnabled = soundObject.repeatEnabled!.boolValue + let filePath = soundObject.filePath! + + if repeatEnabled && self.soundManager.soundIsPlaying(filePath) { + self.soundManager.stopSound(atPath: filePath) + } else { + self.soundManager.playSound(atPath: filePath, repeatSound: repeatEnabled) } } diff --git a/QuickSound/SoundManager.swift b/QuickSound/SoundManager.swift new file mode 100644 index 0000000..94d224a --- /dev/null +++ b/QuickSound/SoundManager.swift @@ -0,0 +1,89 @@ +// +// SoundManager.swift +// QuickSound +// +// Created by Nicolas HOAREAU on 22/03/2016. +// Copyright © 2016 Thomas Di Meco. All rights reserved. +// + +import Foundation +import Cocoa + +class SoundManager:NSObject, NSSoundDelegate { + + private var sounds:[NSSound] = [] + + /** + Use this method to play a sound + + - parameter atPath: the path of the sound + - parameter repeatSound: a boolean to indicate if you want repeat the sound + */ + func playSound(atPath path: String, repeatSound: Bool) { + + if let soundURL = NSURL(string: path) { + let sound = NSSound(contentsOfURL: soundURL, byReference: true) + + sound?.loops = repeatSound + sound?.setName(path) + + let successOrNil = sound?.play() + + // Show alert + if successOrNil == nil || !successOrNil! { + let alert = NSAlert() + alert.messageText = "Impossible de lire le son" + alert.informativeText = "Le fichier est invalide ou introuvable." + alert.alertStyle = .CriticalAlertStyle + alert.runModal() + } else if repeatSound { + self.sounds.append(sound!) + } + } + } + + /** + Use this method to stop a sound + + - parameter atPath: the path of the sound + + - returns: A boolean to indicate if sound is stopped + */ + func stopSound(atPath path: String) -> Bool { + + return self.removeSound(path) + } + + /** + Use this method to know if a sound if playing + + - parameter name: the name of the sound + + - returns: A boolean to indicate if sound is playing + */ + func soundIsPlaying(name: String) -> Bool { + for sound: NSSound in self.sounds { + if sound.name == name { + return true + } + } + return false + } + + // MARK: - Private + + private func removeSound(name: String) -> Bool { + var stopped = false + let soundsArray = NSArray(array:self.sounds) + + for (index, value) in soundsArray.enumerate() { + let sound = value as! NSSound + if sound.name == name { + stopped = sound.stop() + self.sounds.removeAtIndex(index) + } + } + return stopped + } + +} \ No newline at end of file