Skip to content

Commit

Permalink
Ringtone playback example
Browse files Browse the repository at this point in the history
  • Loading branch information
bobiechen-twilio committed Dec 9, 2016
1 parent eaa1638 commit 2f73a80
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 15 deletions.
Binary file added Ringtones/disconnect.wav
Binary file not shown.
Binary file added Ringtones/incoming.wav
Binary file not shown.
Binary file added Ringtones/outgoing.wav
Binary file not shown.
20 changes: 20 additions & 0 deletions SwiftVoiceQuickstart.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
24BA343E1D874AC800B0B4F7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 24BA343D1D874AC800B0B4F7 /* Assets.xcassets */; };
24BA34411D874AC800B0B4F7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 24BA343F1D874AC800B0B4F7 /* LaunchScreen.storyboard */; };
24BA34491D874BBD00B0B4F7 /* TwilioLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = 24BA34481D874BBD00B0B4F7 /* TwilioLogo.png */; };
8F1A92811DF9001C00609990 /* disconnect.wav in Resources */ = {isa = PBXBuildFile; fileRef = 8F1A927E1DF9001C00609990 /* disconnect.wav */; };
8F1A92821DF9001C00609990 /* incoming.wav in Resources */ = {isa = PBXBuildFile; fileRef = 8F1A927F1DF9001C00609990 /* incoming.wav */; };
8F1A92831DF9001C00609990 /* outgoing.wav in Resources */ = {isa = PBXBuildFile; fileRef = 8F1A92801DF9001C00609990 /* outgoing.wav */; };
C05310421E9FD588963E3AB5 /* Pods_SwiftVoiceQuickstart.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E10ADF666A5E46DC31C56BB /* Pods_SwiftVoiceQuickstart.framework */; };
/* End PBXBuildFile section */

Expand All @@ -28,6 +31,9 @@
24BA344A1D874D2B00B0B4F7 /* SwiftVoiceQuickstart.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SwiftVoiceQuickstart.entitlements; sourceTree = "<group>"; };
5745F8037F1069D741DA8D6D /* Pods-SwiftVoiceQuickstart.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftVoiceQuickstart.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftVoiceQuickstart/Pods-SwiftVoiceQuickstart.debug.xcconfig"; sourceTree = "<group>"; };
7C4D4C9846E9421C7C38ED87 /* Pods-SwiftVoiceQuickstart.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftVoiceQuickstart.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftVoiceQuickstart/Pods-SwiftVoiceQuickstart.release.xcconfig"; sourceTree = "<group>"; };
8F1A927E1DF9001C00609990 /* disconnect.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = disconnect.wav; sourceTree = "<group>"; };
8F1A927F1DF9001C00609990 /* incoming.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = incoming.wav; sourceTree = "<group>"; };
8F1A92801DF9001C00609990 /* outgoing.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = outgoing.wav; sourceTree = "<group>"; };
9E10ADF666A5E46DC31C56BB /* Pods_SwiftVoiceQuickstart.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftVoiceQuickstart.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

Expand All @@ -47,6 +53,7 @@
isa = PBXGroup;
children = (
24BA34351D874AC800B0B4F7 /* SwiftVoiceQuickstart */,
8F1A927D1DF9001C00609990 /* Ringtones */,
24BA34341D874AC800B0B4F7 /* Products */,
55E4DD2B129E858377D08E95 /* Pods */,
45B8A87752EE385BD0514D8C /* Frameworks */,
Expand Down Expand Up @@ -93,6 +100,16 @@
name = Pods;
sourceTree = "<group>";
};
8F1A927D1DF9001C00609990 /* Ringtones */ = {
isa = PBXGroup;
children = (
8F1A927E1DF9001C00609990 /* disconnect.wav */,
8F1A927F1DF9001C00609990 /* incoming.wav */,
8F1A92801DF9001C00609990 /* outgoing.wav */,
);
path = Ringtones;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -164,9 +181,12 @@
buildActionMask = 2147483647;
files = (
24BA34411D874AC800B0B4F7 /* LaunchScreen.storyboard in Resources */,
8F1A92831DF9001C00609990 /* outgoing.wav in Resources */,
24BA343E1D874AC800B0B4F7 /* Assets.xcassets in Resources */,
24BA34491D874BBD00B0B4F7 /* TwilioLogo.png in Resources */,
24BA343C1D874AC800B0B4F7 /* Main.storyboard in Resources */,
8F1A92821DF9001C00609990 /* incoming.wav in Resources */,
8F1A92811DF9001C00609990 /* disconnect.wav in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
108 changes: 93 additions & 15 deletions SwiftVoiceQuickstart/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import TwilioVoiceClient
let baseURLString = <#URL TO YOUR ACCESS TOKEN SERVER#>
let accessTokenEndpoint = "/accessToken"

class ViewController: UIViewController, PKPushRegistryDelegate, TVONotificationDelegate, TVOIncomingCallDelegate, TVOOutgoingCallDelegate {
class ViewController: UIViewController, PKPushRegistryDelegate, TVONotificationDelegate, TVOIncomingCallDelegate, TVOOutgoingCallDelegate, AVAudioPlayerDelegate {

@IBOutlet weak var placeCallButton: UIButton!
@IBOutlet weak var iconView: UIImageView!
Expand All @@ -27,6 +27,9 @@ class ViewController: UIViewController, PKPushRegistryDelegate, TVONotificationD

var incomingCall:TVOIncomingCall?
var outgoingCall:TVOOutgoingCall?

var ringtonePlayer:AVAudioPlayer?
var ringtonePlaybackCallback: (() -> ())?

required init?(coder aDecoder: NSCoder) {
isSpinning = false
Expand Down Expand Up @@ -65,15 +68,19 @@ class ViewController: UIViewController, PKPushRegistryDelegate, TVONotificationD
return
}

outgoingCall = VoiceClient.sharedInstance().call(accessToken, params: [:], delegate: self)

if (outgoingCall == nil) {
NSLog("Failed to start outgoing call")
return
}

toggleUIState(isEnabled: false)
startSpin()
playOutgoingRingtone(completion: { [weak self] in
if let strongSelf = self {
strongSelf.outgoingCall = VoiceClient.sharedInstance().call(accessToken, params: [:], delegate: strongSelf)

if (strongSelf.outgoingCall == nil) {
NSLog("Failed to start outgoing call")
return
} else {
strongSelf.toggleUIState(isEnabled: false)
strongSelf.startSpin()
}
}
})
}


Expand Down Expand Up @@ -151,24 +158,27 @@ class ViewController: UIViewController, PKPushRegistryDelegate, TVONotificationD
let from = incomingCall.from
let alertMessage = "From: \(from)"

playIncomingRingtone()

let incomingAlertController = UIAlertController(title: "Incoming",
message: alertMessage,
preferredStyle: .alert)

let rejectAction = UIAlertAction(title: "Reject", style: .default) { [weak self] (action) in
incomingCall.reject()

if let strongSelf = self {
self?.stopIncomingRingtone(completion: {_ in
incomingCall.reject()
})
strongSelf.incomingAlertController = nil
strongSelf.toggleUIState(isEnabled: true)
}
}
incomingAlertController.addAction(rejectAction)

let ignoreAction = UIAlertAction(title: "Ignore", style: .default) { [weak self] (action) in
incomingCall.ignore()

if let strongSelf = self {
strongSelf.stopIncomingRingtone(completion: nil)
incomingCall.ignore()
strongSelf.incomingAlertController = nil
strongSelf.toggleUIState(isEnabled: true)
}
Expand All @@ -177,7 +187,9 @@ class ViewController: UIViewController, PKPushRegistryDelegate, TVONotificationD

let acceptAction = UIAlertAction(title: "Accept", style: .default) { [weak self] (action) in
if let strongSelf = self {
incomingCall.accept(with: strongSelf)
strongSelf.stopIncomingRingtone(completion: {_ in
incomingCall.accept(with: strongSelf)
})

strongSelf.incomingAlertController = nil
strongSelf.startSpin()
Expand Down Expand Up @@ -206,6 +218,9 @@ class ViewController: UIViewController, PKPushRegistryDelegate, TVONotificationD
return;
}

self.stopIncomingRingtone(completion: nil)
playDisconnectSound()

if (incomingAlertController != nil) {
dismiss(animated: true) { [weak self] in
if let strongSelf = self {
Expand Down Expand Up @@ -238,6 +253,8 @@ class ViewController: UIViewController, PKPushRegistryDelegate, TVONotificationD
func incomingCallDidDisconnect(_ incomingCall: TVOIncomingCall) {
NSLog("incomingCallDidDisconnect:")

playDisconnectSound()

self.incomingCall = nil
toggleUIState(isEnabled: true)
}
Expand Down Expand Up @@ -265,6 +282,8 @@ class ViewController: UIViewController, PKPushRegistryDelegate, TVONotificationD
func outgoingCallDidDisconnect(_ outgoingCall: TVOOutgoingCall) {
NSLog("outgoingCallDidDisconnect:")

playDisconnectSound()

self.outgoingCall = nil
toggleUIState(isEnabled: true)
}
Expand All @@ -286,6 +305,65 @@ class ViewController: UIViewController, PKPushRegistryDelegate, TVONotificationD
NSLog(error.localizedDescription)
}
}


// MARK: Ringtone player & AVAudioPlayerDelegate
func playOutgoingRingtone(completion: @escaping () -> ()) {
self.ringtonePlaybackCallback = completion

let ringtonePath = URL(fileURLWithPath: Bundle.main.path(forResource: "outgoing", ofType: "wav")!)
do {
self.ringtonePlayer = try AVAudioPlayer(contentsOf: ringtonePath)
self.ringtonePlayer?.delegate = self
self.ringtonePlayer?.play()
} catch {
NSLog("Failed to initialize audio player")
self.ringtonePlaybackCallback?()
}
}

func playIncomingRingtone() {
let ringtonePath = URL(fileURLWithPath: Bundle.main.path(forResource: "incoming", ofType: "wav")!)
do {
self.ringtonePlayer = try AVAudioPlayer(contentsOf: ringtonePath)
self.ringtonePlayer?.delegate = self
self.ringtonePlayer?.numberOfLoops = -1
self.ringtonePlayer?.play()
} catch {
NSLog("Failed to initialize audio player")
}
}

func stopIncomingRingtone(completion: ((Void?) -> Void)?) {
self.ringtonePlaybackCallback = completion
if (self.ringtonePlayer?.isPlaying == false) {
self.ringtonePlaybackCallback?()
return
}

self.ringtonePlayer?.delegate = self
self.ringtonePlayer?.numberOfLoops = 1
}

func playDisconnectSound() {
let ringtonePath = URL(fileURLWithPath: Bundle.main.path(forResource: "disconnect", ofType: "wav")!)
do {
self.ringtonePlayer = try AVAudioPlayer(contentsOf: ringtonePath)
self.ringtonePlayer?.delegate = self
self.ringtonePlaybackCallback = nil
self.ringtonePlayer?.play()
} catch {
NSLog("Failed to initialize audio player")
}
}

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if (self.ringtonePlaybackCallback != nil) {
DispatchQueue.main.async {
self.ringtonePlaybackCallback!()
}
}
}


// MARK: Icon spinning
Expand Down

0 comments on commit 2f73a80

Please sign in to comment.