diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index bc960aaa7a..3817c5a802 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -8,6 +8,48 @@ /* Begin PBXBuildFile section */ 2AE2882E4C2B96BFFF9EE27C /* Pods_SignalShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F94C85CB0B235DA37F68ED0 /* Pods_SignalShareExtension.framework */; }; + 34074F5B203D093B004596AE /* OWSSoundSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34074F59203D093A004596AE /* OWSSoundSettingsViewController.m */; }; + 34074F61203D0CBE004596AE /* OWSSounds.m in Sources */ = {isa = PBXBuildFile; fileRef = 34074F5F203D0CBD004596AE /* OWSSounds.m */; }; + 34074F62203D0CBE004596AE /* OWSSounds.h in Headers */ = {isa = PBXBuildFile; fileRef = 34074F60203D0CBE004596AE /* OWSSounds.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 34074FEE203E5436004596AE /* aurora.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FC6203E5435004596AE /* aurora.m4r */; }; + 34074FEF203E5436004596AE /* bamboo.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FC7203E5435004596AE /* bamboo.m4r */; }; + 34074FF0203E5436004596AE /* chord.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FC8203E5435004596AE /* chord.m4r */; }; + 34074FF1203E5436004596AE /* circles.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FC9203E5435004596AE /* circles.m4r */; }; + 34074FF2203E5436004596AE /* complete.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FCA203E5435004596AE /* complete.m4r */; }; + 34074FF3203E5436004596AE /* hello.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FCB203E5435004596AE /* hello.m4r */; }; + 34074FF4203E5436004596AE /* input.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FCC203E5435004596AE /* input.m4r */; }; + 34074FF5203E5436004596AE /* keys.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FCD203E5435004596AE /* keys.m4r */; }; + 34074FF6203E5436004596AE /* note.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FCE203E5435004596AE /* note.m4r */; }; + 34074FF7203E5436004596AE /* popcorn.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FCF203E5435004596AE /* popcorn.m4r */; }; + 34074FF8203E5436004596AE /* pulse.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FD0203E5435004596AE /* pulse.m4r */; }; + 34074FF9203E5436004596AE /* synth.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FD1203E5435004596AE /* synth.m4r */; }; + 34074FFA203E5436004596AE /* Apex.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FD3203E5436004596AE /* Apex.m4r */; }; + 34074FFB203E5436004596AE /* Beacon.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FD4203E5436004596AE /* Beacon.m4r */; }; + 34074FFC203E5436004596AE /* Bulletin.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FD5203E5436004596AE /* Bulletin.m4r */; }; + 34074FFD203E5436004596AE /* By The Seaside.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FD6203E5436004596AE /* By The Seaside.m4r */; }; + 34074FFE203E5436004596AE /* Chimes.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FD7203E5436004596AE /* Chimes.m4r */; }; + 34074FFF203E5436004596AE /* Circuit.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FD8203E5436004596AE /* Circuit.m4r */; }; + 34075000203E5436004596AE /* Constellation.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FD9203E5436004596AE /* Constellation.m4r */; }; + 34075001203E5436004596AE /* Cosmic.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FDA203E5436004596AE /* Cosmic.m4r */; }; + 34075002203E5436004596AE /* Crystals.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FDB203E5436004596AE /* Crystals.m4r */; }; + 34075003203E5436004596AE /* Hillside.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FDC203E5436004596AE /* Hillside.m4r */; }; + 34075004203E5436004596AE /* Illuminate.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FDD203E5436004596AE /* Illuminate.m4r */; }; + 34075005203E5436004596AE /* Night Owl.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FDE203E5436004596AE /* Night Owl.m4r */; }; + 34075006203E5436004596AE /* Opening.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FDF203E5436004596AE /* Opening.m4r */; }; + 34075007203E5436004596AE /* Playtime.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FE0203E5436004596AE /* Playtime.m4r */; }; + 34075008203E5436004596AE /* Presto.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FE1203E5436004596AE /* Presto.m4r */; }; + 34075009203E5436004596AE /* Radar.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FE2203E5436004596AE /* Radar.m4r */; }; + 3407500A203E5436004596AE /* Radiate.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FE3203E5436004596AE /* Radiate.m4r */; }; + 3407500B203E5436004596AE /* Ripples.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FE4203E5436004596AE /* Ripples.m4r */; }; + 3407500C203E5436004596AE /* Sencha.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FE5203E5436004596AE /* Sencha.m4r */; }; + 3407500D203E5436004596AE /* Signal.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FE6203E5436004596AE /* Signal.m4r */; }; + 3407500E203E5436004596AE /* Silk.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FE7203E5436004596AE /* Silk.m4r */; }; + 3407500F203E5436004596AE /* Slow Rise.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FE8203E5436004596AE /* Slow Rise.m4r */; }; + 34075010203E5436004596AE /* Stargaze.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FE9203E5436004596AE /* Stargaze.m4r */; }; + 34075011203E5436004596AE /* Summit.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FEA203E5436004596AE /* Summit.m4r */; }; + 34075012203E5436004596AE /* Twinkle.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FEB203E5436004596AE /* Twinkle.m4r */; }; + 34075013203E5436004596AE /* Uplift.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FEC203E5436004596AE /* Uplift.m4r */; }; + 34075014203E5436004596AE /* Waves.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34074FED203E5436004596AE /* Waves.m4r */; }; 340B02BA1FA0D6C700F9CFEC /* ConversationViewItemTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 340B02B91FA0D6C700F9CFEC /* ConversationViewItemTest.m */; }; 340CB2271EAC25820001CAA1 /* UpdateGroupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340CB2261EAC25820001CAA1 /* UpdateGroupViewController.m */; }; 341F2C0F1F2B8AE700D07D6B /* DebugUIMisc.m in Sources */ = {isa = PBXBuildFile; fileRef = 341F2C0E1F2B8AE700D07D6B /* DebugUIMisc.m */; }; @@ -166,6 +208,10 @@ 34CCAF381F0C0599004084F4 /* AppUpdateNag.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CCAF371F0C0599004084F4 /* AppUpdateNag.m */; }; 34CCAF3B1F0C2748004084F4 /* OWSAddToContactViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CCAF3A1F0C2748004084F4 /* OWSAddToContactViewController.m */; }; 34CE88E71F2FB9A10098030F /* ProfileViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34CE88E61F2FB9A10098030F /* ProfileViewController.m */; }; + 34CF0787203E6B78005C4D61 /* busy_tone_ansi.caf in Resources */ = {isa = PBXBuildFile; fileRef = 34CF0783203E6B77005C4D61 /* busy_tone_ansi.caf */; }; + 34CF0788203E6B78005C4D61 /* ringback_tone_ansi.caf in Resources */ = {isa = PBXBuildFile; fileRef = 34CF0784203E6B77005C4D61 /* ringback_tone_ansi.caf */; }; + 34CF0789203E6B78005C4D61 /* ringback_tone_cept.caf in Resources */ = {isa = PBXBuildFile; fileRef = 34CF0785203E6B77005C4D61 /* ringback_tone_cept.caf */; }; + 34CF078A203E6B78005C4D61 /* end_call_tone_cept.caf in Resources */ = {isa = PBXBuildFile; fileRef = 34CF0786203E6B78005C4D61 /* end_call_tone_cept.caf */; }; 34D1F0501F7D45A60066283D /* GifPickerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D1F04F1F7D45A60066283D /* GifPickerCell.swift */; }; 34D1F0521F7E8EA30066283D /* GiphyDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D1F0511F7E8EA30066283D /* GiphyDownloader.swift */; }; 34D1F0821F8678AA0066283D /* ConversationHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D1F0661F8678AA0066283D /* ConversationHeaderView.m */; }; @@ -349,7 +395,6 @@ B10C9B621A7049EC00ECA2BF /* play_icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B10C9B5E1A7049EC00ECA2BF /* play_icon@2x.png */; }; B609597C1C2C0FC6004E8797 /* iRate.m in Sources */ = {isa = PBXBuildFile; fileRef = B609597B1C2C0FC6004E8797 /* iRate.m */; }; B60EDE041A05A01700D73516 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B60EDE031A05A01700D73516 /* AudioToolbox.framework */; }; - B625CD561ABB589C00E8B23C /* NewMessage.aifc in Resources */ = {isa = PBXBuildFile; fileRef = B625CD551ABB589C00E8B23C /* NewMessage.aifc */; }; B633C5861A1D190B0059AC12 /* call@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5041A1D190B0059AC12 /* call@2x.png */; }; B633C58D1A1D190B0059AC12 /* contact_default_feed.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C50B1A1D190B0059AC12 /* contact_default_feed.png */; }; B633C59D1A1D190B0059AC12 /* endcall@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C51B1A1D190B0059AC12 /* endcall@2x.png */; }; @@ -392,11 +437,6 @@ D24B5BD5169F568C00681372 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D24B5BD4169F568C00681372 /* AudioToolbox.framework */; }; D2AEACDC16C426DA00C364C0 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */; }; E1368CBE18A1C36B00109378 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9EB5ABC1884C002007CBB57 /* MessageUI.framework */; }; - E1370BE018A0686600826894 /* busy.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = E18AB40718A05754001A532A /* busy.mp3 */; }; - E1370BE218A0686C00826894 /* failure.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = E18AB40918A05754001A532A /* failure.mp3 */; }; - E1370BE418A0686C00826894 /* outring.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = E18AB40B18A05754001A532A /* outring.mp3 */; }; - E1370BE518A0686C00826894 /* r.caf in Resources */ = {isa = PBXBuildFile; fileRef = E18AB40C18A05754001A532A /* r.caf */; }; - E1370BE618A0686C00826894 /* sonarping.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = E18AB40D18A05754001A532A /* sonarping.mp3 */; }; EF764C351DB67CC5000D9A87 /* UIViewController+Permissions.m in Sources */ = {isa = PBXBuildFile; fileRef = EF764C341DB67CC5000D9A87 /* UIViewController+Permissions.m */; }; FC3BD9881A30A790005B96BB /* Social.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FC3BD9871A30A790005B96BB /* Social.framework */; }; FC5CDF391A3393DD00B47253 /* error_white@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC5CDF371A3393DD00B47253 /* error_white@2x.png */; }; @@ -478,6 +518,49 @@ 3400C7951EAF99F4008A8584 /* SelectThreadViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SelectThreadViewController.m; sourceTree = ""; }; 3400C7971EAFB772008A8584 /* ThreadViewHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadViewHelper.h; sourceTree = ""; }; 3400C7981EAFB772008A8584 /* ThreadViewHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThreadViewHelper.m; sourceTree = ""; }; + 34074F59203D093A004596AE /* OWSSoundSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSSoundSettingsViewController.m; sourceTree = ""; }; + 34074F5A203D093B004596AE /* OWSSoundSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSSoundSettingsViewController.h; sourceTree = ""; }; + 34074F5F203D0CBD004596AE /* OWSSounds.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSSounds.m; sourceTree = ""; }; + 34074F60203D0CBE004596AE /* OWSSounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSSounds.h; sourceTree = ""; }; + 34074FC6203E5435004596AE /* aurora.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = aurora.m4r; sourceTree = ""; }; + 34074FC7203E5435004596AE /* bamboo.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = bamboo.m4r; sourceTree = ""; }; + 34074FC8203E5435004596AE /* chord.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = chord.m4r; sourceTree = ""; }; + 34074FC9203E5435004596AE /* circles.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = circles.m4r; sourceTree = ""; }; + 34074FCA203E5435004596AE /* complete.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = complete.m4r; sourceTree = ""; }; + 34074FCB203E5435004596AE /* hello.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = hello.m4r; sourceTree = ""; }; + 34074FCC203E5435004596AE /* input.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = input.m4r; sourceTree = ""; }; + 34074FCD203E5435004596AE /* keys.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = keys.m4r; sourceTree = ""; }; + 34074FCE203E5435004596AE /* note.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = note.m4r; sourceTree = ""; }; + 34074FCF203E5435004596AE /* popcorn.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = popcorn.m4r; sourceTree = ""; }; + 34074FD0203E5435004596AE /* pulse.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = pulse.m4r; sourceTree = ""; }; + 34074FD1203E5435004596AE /* synth.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = synth.m4r; sourceTree = ""; }; + 34074FD3203E5436004596AE /* Apex.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Apex.m4r; sourceTree = ""; }; + 34074FD4203E5436004596AE /* Beacon.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Beacon.m4r; sourceTree = ""; }; + 34074FD5203E5436004596AE /* Bulletin.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Bulletin.m4r; sourceTree = ""; }; + 34074FD6203E5436004596AE /* By The Seaside.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = "By The Seaside.m4r"; sourceTree = ""; }; + 34074FD7203E5436004596AE /* Chimes.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Chimes.m4r; sourceTree = ""; }; + 34074FD8203E5436004596AE /* Circuit.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Circuit.m4r; sourceTree = ""; }; + 34074FD9203E5436004596AE /* Constellation.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Constellation.m4r; sourceTree = ""; }; + 34074FDA203E5436004596AE /* Cosmic.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Cosmic.m4r; sourceTree = ""; }; + 34074FDB203E5436004596AE /* Crystals.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Crystals.m4r; sourceTree = ""; }; + 34074FDC203E5436004596AE /* Hillside.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Hillside.m4r; sourceTree = ""; }; + 34074FDD203E5436004596AE /* Illuminate.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Illuminate.m4r; sourceTree = ""; }; + 34074FDE203E5436004596AE /* Night Owl.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Night Owl.m4r"; sourceTree = ""; }; + 34074FDF203E5436004596AE /* Opening.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Opening.m4r; sourceTree = ""; }; + 34074FE0203E5436004596AE /* Playtime.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Playtime.m4r; sourceTree = ""; }; + 34074FE1203E5436004596AE /* Presto.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Presto.m4r; sourceTree = ""; }; + 34074FE2203E5436004596AE /* Radar.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Radar.m4r; sourceTree = ""; }; + 34074FE3203E5436004596AE /* Radiate.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Radiate.m4r; sourceTree = ""; }; + 34074FE4203E5436004596AE /* Ripples.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Ripples.m4r; sourceTree = ""; }; + 34074FE5203E5436004596AE /* Sencha.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Sencha.m4r; sourceTree = ""; }; + 34074FE6203E5436004596AE /* Signal.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Signal.m4r; sourceTree = ""; }; + 34074FE7203E5436004596AE /* Silk.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Silk.m4r; sourceTree = ""; }; + 34074FE8203E5436004596AE /* Slow Rise.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Slow Rise.m4r"; sourceTree = ""; }; + 34074FE9203E5436004596AE /* Stargaze.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Stargaze.m4r; sourceTree = ""; }; + 34074FEA203E5436004596AE /* Summit.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Summit.m4r; sourceTree = ""; }; + 34074FEB203E5436004596AE /* Twinkle.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Twinkle.m4r; sourceTree = ""; }; + 34074FEC203E5436004596AE /* Uplift.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Uplift.m4r; sourceTree = ""; }; + 34074FED203E5436004596AE /* Waves.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Waves.m4r; sourceTree = ""; }; 340B02B61F9FD31800F9CFEC /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = translations/he.lproj/Localizable.strings; sourceTree = ""; }; 340B02B91FA0D6C700F9CFEC /* ConversationViewItemTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConversationViewItemTest.m; sourceTree = ""; }; 340CB2221EAC155C0001CAA1 /* ContactsViewHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsViewHelper.h; sourceTree = ""; }; @@ -696,6 +779,10 @@ 34CCAF3A1F0C2748004084F4 /* OWSAddToContactViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSAddToContactViewController.m; sourceTree = ""; }; 34CE88E51F2FB9A10098030F /* ProfileViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProfileViewController.h; sourceTree = ""; }; 34CE88E61F2FB9A10098030F /* ProfileViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProfileViewController.m; sourceTree = ""; }; + 34CF0783203E6B77005C4D61 /* busy_tone_ansi.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = busy_tone_ansi.caf; path = Signal/AudioFiles/busy_tone_ansi.caf; sourceTree = SOURCE_ROOT; }; + 34CF0784203E6B77005C4D61 /* ringback_tone_ansi.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = ringback_tone_ansi.caf; path = Signal/AudioFiles/ringback_tone_ansi.caf; sourceTree = SOURCE_ROOT; }; + 34CF0785203E6B77005C4D61 /* ringback_tone_cept.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = ringback_tone_cept.caf; path = Signal/AudioFiles/ringback_tone_cept.caf; sourceTree = SOURCE_ROOT; }; + 34CF0786203E6B78005C4D61 /* end_call_tone_cept.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = end_call_tone_cept.caf; path = Signal/AudioFiles/end_call_tone_cept.caf; sourceTree = SOURCE_ROOT; }; 34D1F04F1F7D45A60066283D /* GifPickerCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GifPickerCell.swift; sourceTree = ""; }; 34D1F0511F7E8EA30066283D /* GiphyDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GiphyDownloader.swift; sourceTree = ""; }; 34D1F0651F8678AA0066283D /* ConversationHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConversationHeaderView.h; sourceTree = ""; }; @@ -908,7 +995,6 @@ B609597A1C2C0FC6004E8797 /* iRate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = iRate.h; path = Libraries/iRate/iRate.h; sourceTree = SOURCE_ROOT; }; B609597B1C2C0FC6004E8797 /* iRate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = iRate.m; path = Libraries/iRate/iRate.m; sourceTree = SOURCE_ROOT; }; B60EDE031A05A01700D73516 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; - B625CD551ABB589C00E8B23C /* NewMessage.aifc */ = {isa = PBXFileReference; lastKnownFileType = file; path = NewMessage.aifc; sourceTree = ""; }; B633C5041A1D190B0059AC12 /* call@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call@2x.png"; sourceTree = ""; }; B633C50B1A1D190B0059AC12 /* contact_default_feed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = contact_default_feed.png; sourceTree = ""; }; B633C51B1A1D190B0059AC12 /* endcall@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "endcall@2x.png"; sourceTree = ""; }; @@ -987,11 +1073,6 @@ D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; DE2DD605305BC6EFAD731723 /* Pods-Signal.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Signal.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Signal/Pods-Signal.debug.xcconfig"; sourceTree = ""; }; DF728B4B438716EAF95CEC18 /* Pods-Signal.app store release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Signal.app store release.xcconfig"; path = "Pods/Target Support Files/Pods-Signal/Pods-Signal.app store release.xcconfig"; sourceTree = ""; }; - E18AB40718A05754001A532A /* busy.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = busy.mp3; sourceTree = ""; }; - E18AB40918A05754001A532A /* failure.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = failure.mp3; sourceTree = ""; }; - E18AB40B18A05754001A532A /* outring.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = outring.mp3; sourceTree = ""; }; - E18AB40C18A05754001A532A /* r.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = r.caf; sourceTree = ""; }; - E18AB40D18A05754001A532A /* sonarping.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = sonarping.mp3; sourceTree = ""; }; E1A0AD8B16E13FDD0071E604 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; E85DB184824BA9DC302EC8B3 /* Pods-SignalTests.app store release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalTests.app store release.xcconfig"; path = "Pods/Target Support Files/Pods-SignalTests/Pods-SignalTests.app store release.xcconfig"; sourceTree = ""; }; EF764C331DB67CC5000D9A87 /* UIViewController+Permissions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIViewController+Permissions.h"; path = "util/UIViewController+Permissions.h"; sourceTree = ""; }; @@ -1086,6 +1167,74 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 34074F54203D0722004596AE /* Sounds */ = { + isa = PBXGroup; + children = ( + 34CF0783203E6B77005C4D61 /* busy_tone_ansi.caf */, + 34CF0786203E6B78005C4D61 /* end_call_tone_cept.caf */, + 34074FC5203E5435004596AE /* messageReceivedSounds */, + 34CF0784203E6B77005C4D61 /* ringback_tone_ansi.caf */, + 34CF0785203E6B77005C4D61 /* ringback_tone_cept.caf */, + 34074FD2203E5436004596AE /* ringtoneSounds */, + ); + path = Sounds; + sourceTree = ""; + }; + 34074FC5203E5435004596AE /* messageReceivedSounds */ = { + isa = PBXGroup; + children = ( + 34074FC6203E5435004596AE /* aurora.m4r */, + 34074FC7203E5435004596AE /* bamboo.m4r */, + 34074FC8203E5435004596AE /* chord.m4r */, + 34074FC9203E5435004596AE /* circles.m4r */, + 34074FCA203E5435004596AE /* complete.m4r */, + 34074FCB203E5435004596AE /* hello.m4r */, + 34074FCC203E5435004596AE /* input.m4r */, + 34074FCD203E5435004596AE /* keys.m4r */, + 34074FCE203E5435004596AE /* note.m4r */, + 34074FCF203E5435004596AE /* popcorn.m4r */, + 34074FD0203E5435004596AE /* pulse.m4r */, + 34074FD1203E5435004596AE /* synth.m4r */, + ); + name = messageReceivedSounds; + path = Signal/AudioFiles/messageReceivedSounds; + sourceTree = SOURCE_ROOT; + }; + 34074FD2203E5436004596AE /* ringtoneSounds */ = { + isa = PBXGroup; + children = ( + 34074FD3203E5436004596AE /* Apex.m4r */, + 34074FD4203E5436004596AE /* Beacon.m4r */, + 34074FD5203E5436004596AE /* Bulletin.m4r */, + 34074FD6203E5436004596AE /* By The Seaside.m4r */, + 34074FD7203E5436004596AE /* Chimes.m4r */, + 34074FD8203E5436004596AE /* Circuit.m4r */, + 34074FD9203E5436004596AE /* Constellation.m4r */, + 34074FDA203E5436004596AE /* Cosmic.m4r */, + 34074FDB203E5436004596AE /* Crystals.m4r */, + 34074FDC203E5436004596AE /* Hillside.m4r */, + 34074FDD203E5436004596AE /* Illuminate.m4r */, + 34074FDE203E5436004596AE /* Night Owl.m4r */, + 34074FDF203E5436004596AE /* Opening.m4r */, + 34074FE0203E5436004596AE /* Playtime.m4r */, + 34074FE1203E5436004596AE /* Presto.m4r */, + 34074FE2203E5436004596AE /* Radar.m4r */, + 34074FE3203E5436004596AE /* Radiate.m4r */, + 34074FE4203E5436004596AE /* Ripples.m4r */, + 34074FE5203E5436004596AE /* Sencha.m4r */, + 34074FE6203E5436004596AE /* Signal.m4r */, + 34074FE7203E5436004596AE /* Silk.m4r */, + 34074FE8203E5436004596AE /* Slow Rise.m4r */, + 34074FE9203E5436004596AE /* Stargaze.m4r */, + 34074FEA203E5436004596AE /* Summit.m4r */, + 34074FEB203E5436004596AE /* Twinkle.m4r */, + 34074FEC203E5436004596AE /* Uplift.m4r */, + 34074FED203E5436004596AE /* Waves.m4r */, + ); + name = ringtoneSounds; + path = Signal/AudioFiles/ringtoneSounds; + sourceTree = SOURCE_ROOT; + }; 34330A581E7875FB00DF2FB9 /* Fonts */ = { isa = PBXGroup; children = ( @@ -1203,6 +1352,8 @@ 347850671FD9B78A007B8332 /* NoopCallMessageHandler.swift */, 347850681FD9B78A007B8332 /* NoopNotificationsManager.swift */, 45F170AB1E2F0351003FC1F2 /* OWSAudioSession.swift */, + 34074F60203D0CBE004596AE /* OWSSounds.h */, + 34074F5F203D0CBD004596AE /* OWSSounds.m */, 346129561FD1D74B00532771 /* Release.h */, 346129571FD1D74B00532771 /* Release.m */, 346129581FD1D74B00532771 /* SignalKeyingStorage.h */, @@ -1371,6 +1522,8 @@ 34C42D5A1F45F7A80072EC04 /* OWSNavigationController.m */, 34B3F8621E8DF1700035BE1A /* OWSQRCodeScanningViewController.h */, 34B3F8631E8DF1700035BE1A /* OWSQRCodeScanningViewController.m */, + 34074F5A203D093B004596AE /* OWSSoundSettingsViewController.h */, + 34074F59203D093A004596AE /* OWSSoundSettingsViewController.m */, 34B3F8641E8DF1700035BE1A /* PrivacySettingsTableViewController.h */, 34B3F8651E8DF1700035BE1A /* PrivacySettingsTableViewController.m */, 34CE88E51F2FB9A10098030F /* ProfileViewController.h */, @@ -1992,14 +2145,15 @@ D221A093169C9E5E00537ABF /* Signal */ = { isa = PBXGroup; children = ( - B657DDC91911A40500F45B0C /* Signal.entitlements */, 34330A581E7875FB00DF2FB9 /* Fonts */, B633C4FD1A1D190B0059AC12 /* Images */, - B67EBF5C19194AC60084CCFD /* Settings.bundle */, - 76EB03C118170B33006006FC /* src */, - B660F66C1C29867F00687D6E /* test */, - D221A094169C9E5E00537ABF /* Supporting Files */, B66DBF4919D5BBC8006EA940 /* Images.xcassets */, + B67EBF5C19194AC60084CCFD /* Settings.bundle */, + B657DDC91911A40500F45B0C /* Signal.entitlements */, + 34074F54203D0722004596AE /* Sounds */, + 76EB03C118170B33006006FC /* src */, + D221A094169C9E5E00537ABF /* Supporting Files */, + B660F66C1C29867F00687D6E /* test */, ); path = Signal; sourceTree = ""; @@ -2008,7 +2162,6 @@ isa = PBXGroup; children = ( B6B6C3C419193F5B00C0B76B /* Translations */, - E18AB40618A05754001A532A /* AudioFiles */, D221A099169C9E5E00537ABF /* main.m */, D221A095169C9E5E00537ABF /* Signal-Info.plist */, D221A09B169C9E5E00537ABF /* Signal-Prefix.pch */, @@ -2016,19 +2169,6 @@ name = "Supporting Files"; sourceTree = ""; }; - E18AB40618A05754001A532A /* AudioFiles */ = { - isa = PBXGroup; - children = ( - B625CD551ABB589C00E8B23C /* NewMessage.aifc */, - E18AB40718A05754001A532A /* busy.mp3 */, - E18AB40918A05754001A532A /* failure.mp3 */, - E18AB40B18A05754001A532A /* outring.mp3 */, - E18AB40C18A05754001A532A /* r.caf */, - E18AB40D18A05754001A532A /* sonarping.mp3 */, - ); - path = AudioFiles; - sourceTree = ""; - }; FCFA64B11A24F29E0007FB87 /* UI Categories */ = { isa = PBXGroup; children = ( @@ -2103,6 +2243,7 @@ 45194F901FD7200000333B2C /* ThreadUtil.h in Headers */, 346129CC1FD2072E00532771 /* NSAttributedString+OWS.h in Headers */, 346129FD1FD5F31400532771 /* OWS102MoveLoggingPreferenceToUserDefaults.h in Headers */, + 34074F62203D0CBE004596AE /* OWSSounds.h in Headers */, 344F2499200FD03300CFB4F4 /* SharingThreadPickerViewController.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2368,42 +2509,79 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 34CF078A203E6B78005C4D61 /* end_call_tone_cept.caf in Resources */, AD83FF3F1A73426500B5C81A /* audio_pause_button_blue.png in Resources */, + 3407500C203E5436004596AE /* Sencha.m4r in Resources */, 34330A5A1E7875FB00DF2FB9 /* fontawesome-webfont.ttf in Resources */, A5509ECA1A69AB8B00ABA4BC /* Main.storyboard in Resources */, AD83FF421A73426500B5C81A /* audio_play_button.png in Resources */, + 34074FEF203E5436004596AE /* bamboo.m4r in Resources */, 34330A5C1E787A9800DF2FB9 /* dripicons-v2.ttf in Resources */, B633C5C41A1D190B0059AC12 /* mute_on@2x.png in Resources */, B633C5CE1A1D190B0059AC12 /* quit@2x.png in Resources */, + 34075008203E5436004596AE /* Presto.m4r in Resources */, + 34074FF1203E5436004596AE /* circles.m4r in Resources */, AD83FF441A73426500B5C81A /* audio_pause_button.png in Resources */, + 34075005203E5436004596AE /* Night Owl.m4r in Resources */, B6F509971AA53F760068F56A /* Localizable.strings in Resources */, B633C59D1A1D190B0059AC12 /* endcall@2x.png in Resources */, FC5CDF391A3393DD00B47253 /* error_white@2x.png in Resources */, + 34075003203E5436004596AE /* Hillside.m4r in Resources */, + 34074FFA203E5436004596AE /* Apex.m4r in Resources */, + 3407500E203E5436004596AE /* Silk.m4r in Resources */, + 34075004203E5436004596AE /* Illuminate.m4r in Resources */, B633C5D21A1D190B0059AC12 /* savephoto@2x.png in Resources */, B10C9B611A7049EC00ECA2BF /* play_icon.png in Resources */, + 34074FF3203E5436004596AE /* hello.m4r in Resources */, + 34074FF9203E5436004596AE /* synth.m4r in Resources */, AD83FF401A73426500B5C81A /* audio_pause_button_blue@2x.png in Resources */, B66DBF4A19D5BBC8006EA940 /* Images.xcassets in Resources */, + 34CF0788203E6B78005C4D61 /* ringback_tone_ansi.caf in Resources */, + 34074FF7203E5436004596AE /* popcorn.m4r in Resources */, + 34CF0789203E6B78005C4D61 /* ringback_tone_cept.caf in Resources */, + 34074FFF203E5436004596AE /* Circuit.m4r in Resources */, + 34074FF8203E5436004596AE /* pulse.m4r in Resources */, 4517642A1DE939FD00EDB8B9 /* ContactCell.xib in Resources */, AD83FF431A73426500B5C81A /* audio_play_button@2x.png in Resources */, + 34075007203E5436004596AE /* Playtime.m4r in Resources */, 45CB2FA81CB7146C00E1B343 /* Launch Screen.storyboard in Resources */, 34B3F8781E8DF1700035BE1A /* ContactsPicker.xib in Resources */, B633C5C31A1D190B0059AC12 /* mute_off@2x.png in Resources */, + 3407500F203E5436004596AE /* Slow Rise.m4r in Resources */, + 34074FF2203E5436004596AE /* complete.m4r in Resources */, + 34074FFB203E5436004596AE /* Beacon.m4r in Resources */, AD83FF411A73426500B5C81A /* audio_play_button_blue@2x.png in Resources */, FC5CDF3A1A3393DD00B47253 /* warning_white@2x.png in Resources */, - E1370BE018A0686600826894 /* busy.mp3 in Resources */, - E1370BE218A0686C00826894 /* failure.mp3 in Resources */, - B625CD561ABB589C00E8B23C /* NewMessage.aifc in Resources */, + 34075014203E5436004596AE /* Waves.m4r in Resources */, + 34075011203E5436004596AE /* Summit.m4r in Resources */, + 34075006203E5436004596AE /* Opening.m4r in Resources */, + 34074FF6203E5436004596AE /* note.m4r in Resources */, + 34075009203E5436004596AE /* Radar.m4r in Resources */, + 34075012203E5436004596AE /* Twinkle.m4r in Resources */, B633C58D1A1D190B0059AC12 /* contact_default_feed.png in Resources */, B10C9B621A7049EC00ECA2BF /* play_icon@2x.png in Resources */, + 34074FFE203E5436004596AE /* Chimes.m4r in Resources */, B633C5861A1D190B0059AC12 /* call@2x.png in Resources */, B67EBF5D19194AC60084CCFD /* Settings.bundle in Resources */, - E1370BE418A0686C00826894 /* outring.mp3 in Resources */, + 34074FF5203E5436004596AE /* keys.m4r in Resources */, + 3407500D203E5436004596AE /* Signal.m4r in Resources */, + 34075000203E5436004596AE /* Constellation.m4r in Resources */, B10C9B601A7049EC00ECA2BF /* pause_icon@2x.png in Resources */, - E1370BE518A0686C00826894 /* r.caf in Resources */, + 34075002203E5436004596AE /* Crystals.m4r in Resources */, FC9120411A39EFB70074545C /* qr@2x.png in Resources */, - E1370BE618A0686C00826894 /* sonarping.mp3 in Resources */, + 34075001203E5436004596AE /* Cosmic.m4r in Resources */, + 34074FFD203E5436004596AE /* By The Seaside.m4r in Resources */, + 34075013203E5436004596AE /* Uplift.m4r in Resources */, + 3407500B203E5436004596AE /* Ripples.m4r in Resources */, + 34CF0787203E6B78005C4D61 /* busy_tone_ansi.caf in Resources */, + 34075010203E5436004596AE /* Stargaze.m4r in Resources */, + 34074FF0203E5436004596AE /* chord.m4r in Resources */, + 34074FF4203E5436004596AE /* input.m4r in Resources */, B10C9B5F1A7049EC00ECA2BF /* pause_icon.png in Resources */, + 3407500A203E5436004596AE /* Radiate.m4r in Resources */, AD83FF471A73428300B5C81A /* audio_play_button_blue.png in Resources */, + 34074FFC203E5436004596AE /* Bulletin.m4r in Resources */, + 34074FEE203E5436004596AE /* aurora.m4r in Resources */, 34330A5E1E787BD800DF2FB9 /* ElegantIcons.ttf in Resources */, AD83FF451A73426500B5C81A /* audio_pause_button@2x.png in Resources */, ); @@ -2782,6 +2960,7 @@ 347850711FDAEB17007B8332 /* OWSUserProfile.m in Sources */, 346129761FD1E0B500532771 /* WeakTimer.swift in Sources */, 346129F81FD5F31400532771 /* OWS100RemoveTSRecipientsMigration.m in Sources */, + 34074F61203D0CBE004596AE /* OWSSounds.m in Sources */, 346129B51FD1F7E800532771 /* OWSProfileManager.m in Sources */, 346129701FD1D74C00532771 /* Release.m in Sources */, 3478506C1FD9B78A007B8332 /* NoopNotificationsManager.swift in Sources */, @@ -2977,6 +3156,7 @@ 34D1F0B11F867BFC0066283D /* OWSUnreadIndicatorCell.m in Sources */, 34B3F89C1E8DF3270035BE1A /* BlockListViewController.m in Sources */, 34BECE2B1F74C12700D7438D /* DebugUIStress.m in Sources */, + 34074F5B203D093B004596AE /* OWSSoundSettingsViewController.m in Sources */, 34C42D5B1F45F7A80072EC04 /* OWSNavigationController.m in Sources */, B609597C1C2C0FC6004E8797 /* iRate.m in Sources */, 4574A5D61DD6704700C6B692 /* CallService.swift in Sources */, diff --git a/Signal/AudioFiles/NewMessage.aifc b/Signal/AudioFiles/NewMessage.aifc index 694ff1c238..0f87778618 100644 Binary files a/Signal/AudioFiles/NewMessage.aifc and b/Signal/AudioFiles/NewMessage.aifc differ diff --git a/Signal/AudioFiles/busy.mp3 b/Signal/AudioFiles/busy.mp3 deleted file mode 100644 index 865005e512..0000000000 Binary files a/Signal/AudioFiles/busy.mp3 and /dev/null differ diff --git a/Signal/AudioFiles/busy_tone_ansi.caf b/Signal/AudioFiles/busy_tone_ansi.caf new file mode 100644 index 0000000000..7a6d839506 Binary files /dev/null and b/Signal/AudioFiles/busy_tone_ansi.caf differ diff --git a/Signal/AudioFiles/end_call_tone_cept.caf b/Signal/AudioFiles/end_call_tone_cept.caf new file mode 100644 index 0000000000..c0a22b1389 Binary files /dev/null and b/Signal/AudioFiles/end_call_tone_cept.caf differ diff --git a/Signal/AudioFiles/failure.mp3 b/Signal/AudioFiles/failure.mp3 deleted file mode 100644 index 33fc485576..0000000000 Binary files a/Signal/AudioFiles/failure.mp3 and /dev/null differ diff --git a/Signal/AudioFiles/messageReceivedSounds/aurora.m4r b/Signal/AudioFiles/messageReceivedSounds/aurora.m4r new file mode 100644 index 0000000000..a9dce516d3 Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/aurora.m4r differ diff --git a/Signal/AudioFiles/messageReceivedSounds/bamboo.m4r b/Signal/AudioFiles/messageReceivedSounds/bamboo.m4r new file mode 100644 index 0000000000..b795043d8b Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/bamboo.m4r differ diff --git a/Signal/AudioFiles/messageReceivedSounds/chord.m4r b/Signal/AudioFiles/messageReceivedSounds/chord.m4r new file mode 100644 index 0000000000..89d9c567f4 Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/chord.m4r differ diff --git a/Signal/AudioFiles/messageReceivedSounds/circles.m4r b/Signal/AudioFiles/messageReceivedSounds/circles.m4r new file mode 100644 index 0000000000..81e54a2c50 Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/circles.m4r differ diff --git a/Signal/AudioFiles/messageReceivedSounds/complete.m4r b/Signal/AudioFiles/messageReceivedSounds/complete.m4r new file mode 100644 index 0000000000..9bba6dd426 Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/complete.m4r differ diff --git a/Signal/AudioFiles/messageReceivedSounds/hello.m4r b/Signal/AudioFiles/messageReceivedSounds/hello.m4r new file mode 100644 index 0000000000..9504e9a0d9 Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/hello.m4r differ diff --git a/Signal/AudioFiles/messageReceivedSounds/input.m4r b/Signal/AudioFiles/messageReceivedSounds/input.m4r new file mode 100644 index 0000000000..5e86616bab Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/input.m4r differ diff --git a/Signal/AudioFiles/messageReceivedSounds/keys.m4r b/Signal/AudioFiles/messageReceivedSounds/keys.m4r new file mode 100644 index 0000000000..ebdcb00b62 Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/keys.m4r differ diff --git a/Signal/AudioFiles/messageReceivedSounds/note.m4r b/Signal/AudioFiles/messageReceivedSounds/note.m4r new file mode 100644 index 0000000000..5e394836ab Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/note.m4r differ diff --git a/Signal/AudioFiles/messageReceivedSounds/popcorn.m4r b/Signal/AudioFiles/messageReceivedSounds/popcorn.m4r new file mode 100644 index 0000000000..2c2ca24d13 Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/popcorn.m4r differ diff --git a/Signal/AudioFiles/messageReceivedSounds/pulse.m4r b/Signal/AudioFiles/messageReceivedSounds/pulse.m4r new file mode 100644 index 0000000000..8b3777e682 Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/pulse.m4r differ diff --git a/Signal/AudioFiles/messageReceivedSounds/synth.m4r b/Signal/AudioFiles/messageReceivedSounds/synth.m4r new file mode 100644 index 0000000000..78cfbe6544 Binary files /dev/null and b/Signal/AudioFiles/messageReceivedSounds/synth.m4r differ diff --git a/Signal/AudioFiles/outring.mp3 b/Signal/AudioFiles/outring.mp3 deleted file mode 100644 index ee041d7b46..0000000000 Binary files a/Signal/AudioFiles/outring.mp3 and /dev/null differ diff --git a/Signal/AudioFiles/r.caf b/Signal/AudioFiles/r.caf deleted file mode 100644 index 070b4622b5..0000000000 Binary files a/Signal/AudioFiles/r.caf and /dev/null differ diff --git a/Signal/AudioFiles/ringback_tone_ansi.caf b/Signal/AudioFiles/ringback_tone_ansi.caf new file mode 100644 index 0000000000..af7253776c Binary files /dev/null and b/Signal/AudioFiles/ringback_tone_ansi.caf differ diff --git a/Signal/AudioFiles/ringback_tone_cept.caf b/Signal/AudioFiles/ringback_tone_cept.caf new file mode 100644 index 0000000000..89121d2113 Binary files /dev/null and b/Signal/AudioFiles/ringback_tone_cept.caf differ diff --git a/Signal/AudioFiles/ringtoneSounds/Apex.m4r b/Signal/AudioFiles/ringtoneSounds/Apex.m4r new file mode 100644 index 0000000000..df8beb260d Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Apex.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Beacon.m4r b/Signal/AudioFiles/ringtoneSounds/Beacon.m4r new file mode 100644 index 0000000000..987e0ba7db Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Beacon.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Bulletin.m4r b/Signal/AudioFiles/ringtoneSounds/Bulletin.m4r new file mode 100644 index 0000000000..769ef1a550 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Bulletin.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/By The Seaside.m4r b/Signal/AudioFiles/ringtoneSounds/By The Seaside.m4r new file mode 100644 index 0000000000..3d56bfb5a4 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/By The Seaside.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Chimes.m4r b/Signal/AudioFiles/ringtoneSounds/Chimes.m4r new file mode 100644 index 0000000000..2aa8a8339a Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Chimes.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Circuit.m4r b/Signal/AudioFiles/ringtoneSounds/Circuit.m4r new file mode 100644 index 0000000000..42e1b7cd03 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Circuit.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Constellation.m4r b/Signal/AudioFiles/ringtoneSounds/Constellation.m4r new file mode 100644 index 0000000000..c175d2aaa9 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Constellation.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Cosmic.m4r b/Signal/AudioFiles/ringtoneSounds/Cosmic.m4r new file mode 100644 index 0000000000..be56ed9ed1 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Cosmic.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Crystals.m4r b/Signal/AudioFiles/ringtoneSounds/Crystals.m4r new file mode 100644 index 0000000000..5a4fa89db2 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Crystals.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Hillside.m4r b/Signal/AudioFiles/ringtoneSounds/Hillside.m4r new file mode 100644 index 0000000000..b899c4bdcc Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Hillside.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Illuminate.m4r b/Signal/AudioFiles/ringtoneSounds/Illuminate.m4r new file mode 100644 index 0000000000..9488ba2842 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Illuminate.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Night Owl.m4r b/Signal/AudioFiles/ringtoneSounds/Night Owl.m4r new file mode 100644 index 0000000000..6333188434 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Night Owl.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Opening.m4r b/Signal/AudioFiles/ringtoneSounds/Opening.m4r new file mode 100644 index 0000000000..4daeb96d6d Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Opening.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Playtime.m4r b/Signal/AudioFiles/ringtoneSounds/Playtime.m4r new file mode 100644 index 0000000000..55f370cb63 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Playtime.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Presto.m4r b/Signal/AudioFiles/ringtoneSounds/Presto.m4r new file mode 100644 index 0000000000..77d5a8bc94 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Presto.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Radar.m4r b/Signal/AudioFiles/ringtoneSounds/Radar.m4r new file mode 100644 index 0000000000..f477267524 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Radar.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Radiate.m4r b/Signal/AudioFiles/ringtoneSounds/Radiate.m4r new file mode 100644 index 0000000000..f33359a3a7 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Radiate.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Ripples.m4r b/Signal/AudioFiles/ringtoneSounds/Ripples.m4r new file mode 100644 index 0000000000..c8eefd56d3 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Ripples.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Sencha.m4r b/Signal/AudioFiles/ringtoneSounds/Sencha.m4r new file mode 100644 index 0000000000..95fe89f5a9 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Sencha.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Signal.m4r b/Signal/AudioFiles/ringtoneSounds/Signal.m4r new file mode 100644 index 0000000000..c3f4b1526e Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Signal.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Silk.m4r b/Signal/AudioFiles/ringtoneSounds/Silk.m4r new file mode 100644 index 0000000000..ce30381966 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Silk.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Slow Rise.m4r b/Signal/AudioFiles/ringtoneSounds/Slow Rise.m4r new file mode 100644 index 0000000000..414b5cc8fb Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Slow Rise.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Stargaze.m4r b/Signal/AudioFiles/ringtoneSounds/Stargaze.m4r new file mode 100644 index 0000000000..92d86a8316 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Stargaze.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Summit.m4r b/Signal/AudioFiles/ringtoneSounds/Summit.m4r new file mode 100644 index 0000000000..a8f2a1d9e6 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Summit.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Twinkle.m4r b/Signal/AudioFiles/ringtoneSounds/Twinkle.m4r new file mode 100644 index 0000000000..512afa77e0 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Twinkle.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Uplift.m4r b/Signal/AudioFiles/ringtoneSounds/Uplift.m4r new file mode 100644 index 0000000000..f13d050128 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Uplift.m4r differ diff --git a/Signal/AudioFiles/ringtoneSounds/Waves.m4r b/Signal/AudioFiles/ringtoneSounds/Waves.m4r new file mode 100644 index 0000000000..fa16ea0b16 Binary files /dev/null and b/Signal/AudioFiles/ringtoneSounds/Waves.m4r differ diff --git a/Signal/AudioFiles/sonarping.mp3 b/Signal/AudioFiles/sonarping.mp3 deleted file mode 100644 index 801764bafc..0000000000 Binary files a/Signal/AudioFiles/sonarping.mp3 and /dev/null differ diff --git a/Signal/src/Signal-Bridging-Header.h b/Signal/src/Signal-Bridging-Header.h index f2158e0f94..9ec88cf159 100644 --- a/Signal/src/Signal-Bridging-Header.h +++ b/Signal/src/Signal-Bridging-Header.h @@ -10,9 +10,9 @@ #import "ConversationViewItem.h" #import "DateUtil.h" #import "DebugUIPage.h" +#import "DebugUITableViewController.h" #import "FingerprintViewController.h" #import "HomeViewController.h" -#import "DebugUITableViewController.h" #import "MediaDetailViewController.h" #import "NSString+OWS.h" #import "NotificationsManager.h" @@ -51,6 +51,7 @@ #import #import #import +#import #import #import #import diff --git a/Signal/src/ViewControllers/NotificationSettingsViewController.m b/Signal/src/ViewControllers/NotificationSettingsViewController.m index aa4ce9b76e..6f4966f193 100644 --- a/Signal/src/ViewControllers/NotificationSettingsViewController.m +++ b/Signal/src/ViewControllers/NotificationSettingsViewController.m @@ -1,9 +1,10 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "NotificationSettingsViewController.h" #import "NotificationSettingsOptionsViewController.h" +#import "OWSSoundSettingsViewController.h" #import #import @@ -30,7 +31,34 @@ __weak NotificationSettingsViewController *weakSelf = self; OWSPreferences *prefs = [Environment preferences]; - + + // Sounds section. + + OWSTableSection *soundsSection = [OWSTableSection new]; + soundsSection.headerTitle = NSLocalizedString(@"SETTINGS_SECTION_SOUNDS", + @"Label for the sounds section of settings views."); + [soundsSection + addItem:[OWSTableItem disclosureItemWithText: + NSLocalizedString(@"SETTINGS_ITEM_NOTIFICATION_SOUND", + @"Label for settings view that allows user to change the notification sound.") + actionBlock:^{ + OWSSoundSettingsViewController *vc = + [OWSSoundSettingsViewController new]; + vc.soundType = OWSSoundType_Notification; + [weakSelf.navigationController pushViewController:vc animated:YES]; + }]]; + [soundsSection + addItem:[OWSTableItem disclosureItemWithText: + NSLocalizedString(@"SETTINGS_ITEM_RINGTONE_SOUND", + @"Label for settings view that allows user to change the ringtone sound.") + actionBlock:^{ + OWSSoundSettingsViewController *vc = + [OWSSoundSettingsViewController new]; + vc.soundType = OWSSoundType_Ringtone; + [weakSelf.navigationController pushViewController:vc animated:YES]; + }]]; + [contents addSection:soundsSection]; + OWSTableSection *backgroundSection = [OWSTableSection new]; backgroundSection.headerTitle = NSLocalizedString(@"NOTIFICATIONS_SECTION_BACKGROUND", nil); [backgroundSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ diff --git a/Signal/src/ViewControllers/OWSConversationSettingsViewController.m b/Signal/src/ViewControllers/OWSConversationSettingsViewController.m index 0f493de33b..e80d5cb6d5 100644 --- a/Signal/src/ViewControllers/OWSConversationSettingsViewController.m +++ b/Signal/src/ViewControllers/OWSConversationSettingsViewController.m @@ -8,6 +8,7 @@ #import "FingerprintViewController.h" #import "OWSAddToContactViewController.h" #import "OWSBlockingManager.h" +#import "OWSSoundSettingsViewController.h" #import "PhoneNumber.h" #import "ShowGroupMembersViewController.h" #import "Signal-Swift.h" @@ -566,6 +567,37 @@ NS_ASSUME_NONNULL_BEGIN [contents addSection:section]; } + // Sounds section. + + OWSTableSection *soundsSection = [OWSTableSection new]; + soundsSection.headerTitle = NSLocalizedString(@"SETTINGS_SECTION_SOUNDS", + @"Label for the sounds section of settings views."); + [soundsSection + addItem:[OWSTableItem disclosureItemWithText: + NSLocalizedString(@"SETTINGS_ITEM_NOTIFICATION_SOUND", + @"Label for settings view that allows user to change the notification sound.") + actionBlock:^{ + OWSSoundSettingsViewController *vc = + [OWSSoundSettingsViewController new]; + vc.soundType = OWSSoundType_Notification; + vc.thread = weakSelf.thread; + [weakSelf.navigationController pushViewController:vc animated:YES]; + }]]; + if (!self.isGroupThread) { + [soundsSection + addItem:[OWSTableItem disclosureItemWithText: + NSLocalizedString(@"SETTINGS_ITEM_RINGTONE_SOUND", + @"Label for settings view that allows user to change the ringtone sound.") + actionBlock:^{ + OWSSoundSettingsViewController *vc = + [OWSSoundSettingsViewController new]; + vc.soundType = OWSSoundType_Ringtone; + vc.thread = weakSelf.thread; + [weakSelf.navigationController pushViewController:vc animated:YES]; + }]]; + } + [contents addSection:soundsSection]; + self.contents = contents; } diff --git a/Signal/src/ViewControllers/OWSSoundSettingsViewController.h b/Signal/src/ViewControllers/OWSSoundSettingsViewController.h new file mode 100644 index 0000000000..0adc432b66 --- /dev/null +++ b/Signal/src/ViewControllers/OWSSoundSettingsViewController.h @@ -0,0 +1,26 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import "OWSTableViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, OWSSoundType) { + OWSSoundType_Notification = 0, + OWSSoundType_Ringtone, +}; + +@class TSThread; + +@interface OWSSoundSettingsViewController : OWSTableViewController + +@property (nonatomic) OWSSoundType soundType; + +// This property is optional. If it is not set, we are +// editing the global notification sound. +@property (nonatomic, nullable) TSThread *thread; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OWSSoundSettingsViewController.m b/Signal/src/ViewControllers/OWSSoundSettingsViewController.m new file mode 100644 index 0000000000..ec5dfe09cc --- /dev/null +++ b/Signal/src/ViewControllers/OWSSoundSettingsViewController.m @@ -0,0 +1,165 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import "OWSSoundSettingsViewController.h" +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OWSSoundSettingsViewController () + +@property (nonatomic) BOOL isDirty; + +@property (nonatomic) OWSSound currentSound; + +@property (nonatomic) AVAudioPlayer *audioPlayer; + +@end + +#pragma mark - + +@implementation OWSSoundSettingsViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + switch (self.soundType) { + case OWSSoundType_Notification: + [self setTitle:NSLocalizedString(@"SETTINGS_ITEM_NOTIFICATION_SOUND", + @"Label for settings view that allows user to change the notification sound.")]; + self.currentSound + = (self.thread ? [OWSSounds notificationSoundForThread:self.thread] : [OWSSounds globalNotificationSound]); + break; + case OWSSoundType_Ringtone: + [self setTitle:NSLocalizedString(@"SETTINGS_ITEM_RINGTONE_SOUND", + @"Label for settings view that allows user to change the ringtone sound.")]; + self.currentSound + = (self.thread ? [OWSSounds ringtoneSoundForThread:self.thread] : [OWSSounds globalRingtoneSound]); + break; + } + + [self updateTableContents]; + [self updateNavigationItems]; +} + +- (void)viewDidAppear:(BOOL)animated +{ + [self updateTableContents]; +} + +- (void)updateNavigationItems +{ + self.navigationItem.leftBarButtonItem = + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self + action:@selector(cancelWasPressed:)]; + + if (self.isDirty) { + self.navigationItem.rightBarButtonItem = + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave + target:self + action:@selector(saveWasPressed:)]; + } else { + self.navigationItem.rightBarButtonItem = nil; + } +} + +#pragma mark - Table Contents + +- (void)updateTableContents +{ + OWSTableContents *contents = [OWSTableContents new]; + + __weak OWSSoundSettingsViewController *weakSelf = self; + + OWSTableSection *soundsSection = [OWSTableSection new]; + soundsSection.headerTitle = NSLocalizedString( + @"NOTIFICATIONS_SECTION_SOUNDS", @"Label for settings UI that allows user to change the notification sound."); + + NSArray *allSounds; + switch (self.soundType) { + case OWSSoundType_Notification: + allSounds = [OWSSounds allNotificationSounds]; + break; + case OWSSoundType_Ringtone: + allSounds = [OWSSounds allRingtoneSounds]; + break; + } + for (NSNumber *nsValue in allSounds) { + OWSSound sound = (OWSSound)nsValue.intValue; + OWSTableItem *item; + if (sound == self.currentSound) { + item = [OWSTableItem checkmarkItemWithText:[OWSSounds displayNameForSound:sound] + actionBlock:^{ + [weakSelf soundWasSelected:sound]; + }]; + } else { + item = [OWSTableItem actionItemWithText:[OWSSounds displayNameForSound:sound] + actionBlock:^{ + [weakSelf soundWasSelected:sound]; + }]; + } + [soundsSection addItem:item]; + } + + [contents addSection:soundsSection]; + + self.contents = contents; +} + +#pragma mark - Events + +- (void)soundWasSelected:(OWSSound)sound +{ + [self.audioPlayer stop]; + self.audioPlayer = [OWSSounds audioPlayerForSound:sound]; + // Suppress looping in this view. + self.audioPlayer.numberOfLoops = 0; + [self.audioPlayer play]; + + if (self.currentSound == sound) { + return; + } + + self.currentSound = sound; + self.isDirty = YES; + [self updateTableContents]; + [self updateNavigationItems]; +} + +- (void)cancelWasPressed:(id)sender +{ + // TODO: Add "discard changes?" alert. + [self.audioPlayer stop]; + [self.navigationController popViewControllerAnimated:YES]; +} + +- (void)saveWasPressed:(id)sender +{ + switch (self.soundType) { + case OWSSoundType_Notification: + if (self.thread) { + [OWSSounds setNotificationSound:self.currentSound forThread:self.thread]; + } else { + [OWSSounds setGlobalNotificationSound:self.currentSound]; + } + break; + case OWSSoundType_Ringtone: + if (self.thread) { + [OWSSounds setRingtoneSound:self.currentSound forThread:self.thread]; + } else { + [OWSSounds setGlobalRingtoneSound:self.currentSound]; + } + break; + } + + [self.audioPlayer stop]; + [self.navigationController popViewControllerAnimated:YES]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/call/CallAudioService.swift b/Signal/src/call/CallAudioService.swift index 43d28884f5..e2c6216569 100644 --- a/Signal/src/call/CallAudioService.swift +++ b/Signal/src/call/CallAudioService.swift @@ -37,7 +37,7 @@ struct AudioSource: Hashable { let localizedName = isBuiltInEarPiece ? UIDevice.current.localizedModel : portDescription.portName self.init(localizedName: localizedName, - image:#imageLiteral(resourceName: "button_phone_white"), // TODO + image: #imageLiteral(resourceName: "button_phone_white"), // TODO isBuiltInSpeaker: false, isBuiltInEarPiece: isBuiltInEarPiece, portDescription: portDescription) @@ -102,42 +102,6 @@ protocol CallAudioServiceDelegate: class { } } - class Sound: NSObject { - - static let incomingRing = Sound(filePath: "r", fileExtension: "caf", loop: true) - static let outgoingRing = Sound(filePath: "outring", fileExtension: "mp3", loop: true) - static let dialing = Sound(filePath: "sonarping", fileExtension: "mp3", loop: true) - static let busy = Sound(filePath: "busy", fileExtension: "mp3", loop: false) - static let failure = Sound(filePath: "failure", fileExtension: "mp3", loop: false) - - let filePath: String - let fileExtension: String - let url: URL - - let loop: Bool - - init(filePath: String, fileExtension: String, loop: Bool) { - self.filePath = filePath - self.fileExtension = fileExtension - self.url = Bundle.main.url(forResource: self.filePath, withExtension: self.fileExtension)! - self.loop = loop - } - - lazy var player: AVAudioPlayer? = { - let newPlayer: AVAudioPlayer? - do { - try newPlayer = AVAudioPlayer(contentsOf: self.url, fileTypeHint: nil) - if self.loop { - newPlayer?.numberOfLoops = -1 - } - } catch { - owsFail("\(self.logTag) failed to build audio player with error: \(error)") - newPlayer = nil - } - return newPlayer - }() - } - // MARK: Vibration config private let vibrateRepeatDuration = 1.6 @@ -175,7 +139,7 @@ protocol CallAudioServiceDelegate: class { internal func stateDidChange(call: SignalCall, state: CallState) { AssertIsOnMainThread() - self.handleState(call:call) + self.handleState(call: call) } internal func muteDidChange(call: SignalCall, isMuted: Bool) { @@ -340,7 +304,7 @@ protocol CallAudioServiceDelegate: class { // HACK: Without this async, dialing sound only plays once. I don't really understand why. Does the audioSession // need some time to settle? Is somethign else interrupting our session? DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2) { - self.play(sound: Sound.dialing) + self.play(sound: OWSSound.callConnecting) } } @@ -353,7 +317,7 @@ protocol CallAudioServiceDelegate: class { Logger.debug("\(self.logTag) \(#function)") AssertIsOnMainThread() - self.play(sound: Sound.outgoingRing) + self.play(sound: OWSSound.callOutboundRinging) } private func handleLocalRinging(call: SignalCall) { @@ -372,7 +336,7 @@ protocol CallAudioServiceDelegate: class { Logger.debug("\(self.logTag) \(#function)") AssertIsOnMainThread() - play(sound: Sound.failure) + play(sound: OWSSound.callFailure) handleCallEnded(call: call) } @@ -389,14 +353,14 @@ protocol CallAudioServiceDelegate: class { vibrate() - handleCallEnded(call:call) + handleCallEnded(call: call) } private func handleBusy(call: SignalCall) { Logger.debug("\(self.logTag) \(#function)") AssertIsOnMainThread() - play(sound: Sound.busy) + play(sound: OWSSound.callBusy) // Let the busy sound play for 4 seconds. The full file is longer than necessary DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 4.0) { @@ -422,12 +386,12 @@ protocol CallAudioServiceDelegate: class { stopAnyRingingVibration() } - private func play(sound: Sound) { - guard let newPlayer = sound.player else { - owsFail("\(self.logTag) unable to build player") + private func play(sound: OWSSound) { + guard let newPlayer = OWSSounds.audioPlayer(for: sound) else { + owsFail("\(self.logTag) unable to build player for sound: \(OWSSounds.displayName(for: sound))") return } - Logger.info("\(self.logTag) playing sound: \(sound.filePath)") + Logger.info("\(self.logTag) playing sound: \(OWSSounds.displayName(for: sound))") // It's important to stop the current player **before** starting the new player. In the case that // we're playing the same sound, since the player is memoized on the sound instance, we'd otherwise @@ -449,7 +413,8 @@ protocol CallAudioServiceDelegate: class { self?.ringVibration() } vibrateTimer?.fire() - play(sound: Sound.incomingRing) + let sound = OWSSounds.ringtoneSound(for: call.thread) + play(sound: sound) } private func stopAnyRingingVibration() { diff --git a/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift b/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift index 36b9bb2305..7066e091de 100644 --- a/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift +++ b/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift @@ -46,7 +46,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate { let iconMaskImage = #imageLiteral(resourceName: "logoSignal") providerConfiguration.iconTemplateImageData = UIImagePNGRepresentation(iconMaskImage) - providerConfiguration.ringtoneSound = "r.caf" + // We set the ringtoneSound property later. return providerConfiguration } @@ -113,7 +113,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate { if Environment.current().preferences.isCallKitPrivacyEnabled() { let callKitId = CallKitCallManager.kAnonymousCallHandlePrefix + call.localId.uuidString update.remoteHandle = CXHandle(type: .generic, value: callKitId) - TSStorageManager.shared().setPhoneNumber(call.remotePhoneNumber, forCallKitId:callKitId) + TSStorageManager.shared().setPhoneNumber(call.remotePhoneNumber, forCallKitId: callKitId) update.localizedCallerName = NSLocalizedString("CALLKIT_ANONYMOUS_CONTACT_NAME", comment: "The generic name used for calls if CallKit privacy is enabled") } else { update.localizedCallerName = self.contactsManager.stringForConversationTitle(withPhoneIdentifier: call.remotePhoneNumber) @@ -124,6 +124,12 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate { disableUnsupportedFeatures(callUpdate: update) + // Update the provider configuration to reflect the caller's ringtone. + let sound = OWSSounds.ringtoneSound(for: call.thread) + let providerConfiguration = provider.configuration + providerConfiguration.ringtoneSound = OWSSounds.filename(for: sound) + provider.configuration = providerConfiguration + // Report the incoming call to the system provider.reportNewIncomingCall(with: call.localId, update: update) { error in /* diff --git a/Signal/src/environment/NotificationsManager.m b/Signal/src/environment/NotificationsManager.m index 7b227f6e03..092b33e63b 100644 --- a/Signal/src/environment/NotificationsManager.m +++ b/Signal/src/environment/NotificationsManager.m @@ -10,6 +10,7 @@ #import #import #import +#import #import #import #import @@ -18,11 +19,8 @@ #import #import -NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc"; - @interface NotificationsManager () -@property (nonatomic) SystemSoundID newMessageSound; @property (nonatomic, readonly) NSMutableDictionary *currentNotifications; @property (nonatomic, readonly) NotificationType notificationPreviewType; @@ -43,9 +41,6 @@ NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc"; _currentNotifications = [NSMutableDictionary new]; - NSURL *newMessageURL = [[NSBundle mainBundle] URLForResource:@"NewMessage" withExtension:@"aifc"]; - AudioServicesCreateSystemSoundID((__bridge CFURLRef)newMessageURL, &_newMessageSound); - _notificationHistory = [NSMutableArray new]; OWSSingletonAssert(); @@ -65,7 +60,8 @@ NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc"; UILocalNotification *notification = [UILocalNotification new]; notification.category = PushManagerCategoriesIncomingCall; // Rather than using notification sounds, we control the ringtone and repeat vibrations with the CallAudioManager. - notification.soundName = @"r.caf"; + OWSSound sound = [OWSSounds ringtoneSoundForThread:call.thread]; + notification.soundName = [OWSSounds filenameForSound:sound]; NSString *localCallId = call.localId.UUIDString; notification.userInfo = @{ PushManagerUserInfoKeysLocalCallId : localCallId }; @@ -105,7 +101,8 @@ NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc"; }; if ([self shouldPlaySoundForNotification]) { - notification.soundName = kNotificationsManagerNewMesssageSoundName; + OWSSound sound = [OWSSounds notificationSoundForThread:thread]; + notification.soundName = [OWSSounds filenameForSound:sound]; } NSString *alertMessage; @@ -144,7 +141,8 @@ NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc"; Signal_Thread_UserInfo_Key : thread.uniqueId }; if ([self shouldPlaySoundForNotification]) { - notification.soundName = kNotificationsManagerNewMesssageSoundName; + OWSSound sound = [OWSSounds notificationSoundForThread:thread]; + notification.soundName = [OWSSounds filenameForSound:sound]; } NSString *alertMessage; @@ -184,7 +182,8 @@ NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc"; Signal_Thread_UserInfo_Key : thread.uniqueId }; if ([self shouldPlaySoundForNotification]) { - notification.soundName = kNotificationsManagerNewMesssageSoundName; + OWSSound sound = [OWSSounds notificationSoundForThread:thread]; + notification.soundName = [OWSSounds filenameForSound:sound]; } NSString *alertMessage; @@ -228,7 +227,8 @@ NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc"; UILocalNotification *notification = [[UILocalNotification alloc] init]; notification.userInfo = @{ Signal_Thread_UserInfo_Key : thread.uniqueId }; if (shouldPlaySound) { - notification.soundName = kNotificationsManagerNewMesssageSoundName; + OWSSound sound = [OWSSounds notificationSoundForThread:thread]; + notification.soundName = [OWSSounds filenameForSound:sound]; } NSString *alertBodyString = @""; @@ -248,7 +248,8 @@ NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc"; [[PushManager sharedManager] presentNotification:notification checkForCancel:NO]; } else { if (shouldPlaySound && [Environment.preferences soundInForeground]) { - AudioServicesPlayAlertSound(_newMessageSound); + OWSSound sound = [OWSSounds notificationSoundForThread:thread]; + [OWSSounds playSound:sound]; } } }); @@ -289,7 +290,8 @@ NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc"; if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive && messageText) { UILocalNotification *notification = [[UILocalNotification alloc] init]; if (shouldPlaySound) { - notification.soundName = kNotificationsManagerNewMesssageSoundName; + OWSSound sound = [OWSSounds notificationSoundForThread:thread]; + notification.soundName = [OWSSounds filenameForSound:sound]; } switch (self.notificationPreviewType) { @@ -351,7 +353,8 @@ NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc"; [[PushManager sharedManager] presentNotification:notification checkForCancel:YES]; } else { if (shouldPlaySound && [Environment.preferences soundInForeground]) { - AudioServicesPlayAlertSound(_newMessageSound); + OWSSound sound = [OWSSounds notificationSoundForThread:thread]; + [OWSSounds playSound:sound]; } } }); diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 2832ba90c7..558b61d39d 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -1155,6 +1155,9 @@ /* No comment provided by engineer. */ "NOTIFICATIONS_SECTION_INAPP" = "In-App Notifications"; +/* Label for settings UI that allows user to change the notification sound. */ +"NOTIFICATIONS_SECTION_SOUNDS" = "Sounds"; + /* No comment provided by engineer. */ "NOTIFICATIONS_SENDER_AND_MESSAGE" = "Sender name & message"; @@ -1566,6 +1569,12 @@ /* content of tweet when inviting via twitter */ "SETTINGS_INVITE_TWITTER_TEXT" = "You can reach me using Signal by @WhisperSystems, get it now."; +/* Label for settings view that allows user to change the notification sound. */ +"SETTINGS_ITEM_NOTIFICATION_SOUND" = "Notification"; + +/* Label for settings view that allows user to change the ringtone sound. */ +"SETTINGS_ITEM_RINGTONE_SOUND" = "Ringtone"; + /* Title for settings activity */ "SETTINGS_NAV_BAR_TITLE" = "Settings"; @@ -1596,6 +1605,9 @@ /* Settings table section footer. */ "SETTINGS_SECTION_CALL_KIT_DESCRIPTION" = "iOS Call Integration shows Signal calls on your lock screen and in the system's call history. You may optionally show your contact's name and number. If iCloud is enabled, this call history will be shared with Apple."; +/* Label for the sounds section of settings views. */ +"SETTINGS_SECTION_SOUNDS" = "Sounds"; + /* settings topic header for table section */ "SETTINGS_SECTION_TITLE_CALLING" = "Calling"; diff --git a/SignalMessaging/SignalMessaging.h b/SignalMessaging/SignalMessaging.h index 5122e313fd..3e192132b1 100644 --- a/SignalMessaging/SignalMessaging.h +++ b/SignalMessaging/SignalMessaging.h @@ -29,6 +29,7 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[]; #import #import #import +#import #import #import #import diff --git a/SignalMessaging/ViewControllers/OWSTableViewController.h b/SignalMessaging/ViewControllers/OWSTableViewController.h index e1c67e170c..12a390a90d 100644 --- a/SignalMessaging/ViewControllers/OWSTableViewController.h +++ b/SignalMessaging/ViewControllers/OWSTableViewController.h @@ -76,6 +76,12 @@ typedef UITableViewCell *_Nonnull (^OWSTableCustomCellBlock)(void); customRowHeight:(CGFloat)customRowHeight actionBlock:(nullable OWSTableActionBlock)actionBlock; ++ (OWSTableItem *)checkmarkItemWithText:(NSString *)text actionBlock:(nullable OWSTableActionBlock)actionBlock; + ++ (OWSTableItem *)itemWithText:(NSString *)text + actionBlock:(nullable OWSTableActionBlock)actionBlock + accessoryType:(UITableViewCellAccessoryType)accessoryType; + + (OWSTableItem *)subPageItemWithText:(NSString *)text actionBlock:(nullable OWSTableSubPageBlock)actionBlock; + (OWSTableItem *)subPageItemWithText:(NSString *)text diff --git a/SignalMessaging/ViewControllers/OWSTableViewController.m b/SignalMessaging/ViewControllers/OWSTableViewController.m index 1575659562..7f75932f96 100644 --- a/SignalMessaging/ViewControllers/OWSTableViewController.m +++ b/SignalMessaging/ViewControllers/OWSTableViewController.m @@ -147,20 +147,31 @@ const CGFloat kOWSTable_DefaultCellHeight = 45.f; } + (OWSTableItem *)disclosureItemWithText:(NSString *)text actionBlock:(nullable OWSTableActionBlock)actionBlock +{ + return [self itemWithText:text actionBlock:actionBlock accessoryType:UITableViewCellAccessoryDisclosureIndicator]; +} + ++ (OWSTableItem *)checkmarkItemWithText:(NSString *)text actionBlock:(nullable OWSTableActionBlock)actionBlock +{ + return [self itemWithText:text actionBlock:actionBlock accessoryType:UITableViewCellAccessoryCheckmark]; +} + ++ (OWSTableItem *)itemWithText:(NSString *)text + actionBlock:(nullable OWSTableActionBlock)actionBlock + accessoryType:(UITableViewCellAccessoryType)accessoryType { OWSAssert(text.length > 0); OWSAssert(actionBlock); OWSTableItem *item = [OWSTableItem new]; item.itemType = OWSTableItemTypeAction; - __weak OWSTableItem *weakItem = item; item.actionBlock = actionBlock; item.customCellBlock = ^{ UITableViewCell *cell = [UITableViewCell new]; cell.textLabel.text = text; cell.textLabel.font = [UIFont ows_regularFontWithSize:18.f]; cell.textLabel.textColor = [UIColor blackColor]; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + cell.accessoryType = accessoryType; return cell; }; return item; diff --git a/SignalMessaging/environment/OWSSounds.h b/SignalMessaging/environment/OWSSounds.h new file mode 100644 index 0000000000..69f68bef19 --- /dev/null +++ b/SignalMessaging/environment/OWSSounds.h @@ -0,0 +1,97 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, OWSSound) { + OWSSound_Default = 0, + // Notification Sounds + OWSSound_Aurora, + OWSSound_Bamboo, + OWSSound_Chord, + OWSSound_Circles, + OWSSound_Complete, + OWSSound_Hello, + OWSSound_Input, + OWSSound_Keys, + OWSSound_Note, + OWSSound_Popcorn, + OWSSound_Pulse, + OWSSound_Synth, + // Ringtone Sounds + OWSSound_Apex, + OWSSound_Beacon, + OWSSound_Bulletin, + OWSSound_By_The_Seaside, + OWSSound_Chimes, + OWSSound_Circuit, + OWSSound_Constellation, + OWSSound_Cosmic, + OWSSound_Crystals, + OWSSound_Hillside, + OWSSound_Illuminate, + OWSSound_Night_Owl, + OWSSound_Opening, + OWSSound_Playtime, + OWSSound_Presto, + OWSSound_Radar, + OWSSound_Radiate, + OWSSound_Ripples, + OWSSound_Sencha, + OWSSound_Signal, + OWSSound_Silk, + OWSSound_Slow_Rise, + OWSSound_Stargaze, + OWSSound_Summit, + OWSSound_Twinkle, + OWSSound_Uplift, + OWSSound_Waves, + + // Calls + OWSSound_CallConnecting, + OWSSound_CallOutboundRinging, + OWSSound_CallBusy, + OWSSound_CallFailure, +}; + +@class AVAudioPlayer; +@class TSThread; + +@interface OWSSounds : NSObject + +- (instancetype)init NS_UNAVAILABLE; + ++ (NSString *)displayNameForSound:(OWSSound)sound; + ++ (NSString *)filenameForSound:(OWSSound)sound; + ++ (void)playSound:(OWSSound)sound; + +#pragma mark - Notifications + ++ (NSArray *)allNotificationSounds; + ++ (OWSSound)globalNotificationSound; ++ (void)setGlobalNotificationSound:(OWSSound)sound; + ++ (OWSSound)notificationSoundForThread:(TSThread *)thread; ++ (void)setNotificationSound:(OWSSound)sound forThread:(TSThread *)thread; + +#pragma mark - Ringtones + ++ (NSArray *)allRingtoneSounds; + ++ (OWSSound)globalRingtoneSound; ++ (void)setGlobalRingtoneSound:(OWSSound)sound; + ++ (OWSSound)ringtoneSoundForThread:(TSThread *)thread; ++ (void)setRingtoneSound:(OWSSound)sound forThread:(TSThread *)thread; + +#pragma mark - Calls + ++ (nullable AVAudioPlayer *)audioPlayerForSound:(OWSSound)sound; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/environment/OWSSounds.m b/SignalMessaging/environment/OWSSounds.m new file mode 100644 index 0000000000..3367db382f --- /dev/null +++ b/SignalMessaging/environment/OWSSounds.m @@ -0,0 +1,463 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +#import "OWSSounds.h" +#import +#import +#import +#import +#import + +NSString *const kOWSSoundsStorageNotificationCollection = @"kOWSSoundsStorageNotificationCollection"; +NSString *const kOWSSoundsStorageGlobalNotificationKey = @"kOWSSoundsStorageGlobalNotificationKey"; + +NSString *const kOWSSoundsStorageRingtoneCollection = @"kOWSSoundsStorageRingtoneCollection"; +NSString *const kOWSSoundsStorageGlobalRingtoneKey = @"kOWSSoundsStorageGlobalRingtoneKey"; + +@interface OWSSounds () + +@property (nonatomic, readonly) YapDatabaseConnection *dbConnection; + +@property (nonatomic) NSMutableDictionary *systemSoundIDMap; + +@end + +#pragma mark - + +@implementation OWSSounds + ++ (instancetype)sharedManager +{ + static OWSSounds *instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] initDefault]; + }); + return instance; +} + +- (instancetype)initDefault +{ + TSStorageManager *storageManager = [TSStorageManager sharedManager]; + + return [self initWithStorageManager:storageManager]; +} + +- (instancetype)initWithStorageManager:(TSStorageManager *)storageManager +{ + self = [super init]; + + if (!self) { + return self; + } + + OWSAssert(storageManager); + + _dbConnection = storageManager.newDatabaseConnection; + // TODO: Is it safe to load all of these sounds into memory? + // Probably better to do LRU cache. + self.systemSoundIDMap = [NSMutableDictionary new]; + + OWSSingletonAssert(); + + return self; +} + ++ (NSArray *)allNotificationSounds +{ + return @[ + @(OWSSound_Aurora), + @(OWSSound_Bamboo), + @(OWSSound_Chord), + @(OWSSound_Circles), + @(OWSSound_Complete), + @(OWSSound_Hello), + @(OWSSound_Input), + @(OWSSound_Keys), + @(OWSSound_Note), + @(OWSSound_Popcorn), + @(OWSSound_Pulse), + @(OWSSound_Synth), + ]; +} + ++ (NSArray *)allRingtoneSounds +{ + return @[ + @(OWSSound_Apex), + @(OWSSound_Beacon), + @(OWSSound_Bulletin), + @(OWSSound_By_The_Seaside), + @(OWSSound_Chimes), + @(OWSSound_Circuit), + @(OWSSound_Constellation), + @(OWSSound_Cosmic), + @(OWSSound_Crystals), + @(OWSSound_Hillside), + @(OWSSound_Illuminate), + @(OWSSound_Night_Owl), + @(OWSSound_Opening), + @(OWSSound_Playtime), + @(OWSSound_Presto), + @(OWSSound_Radar), + @(OWSSound_Radiate), + @(OWSSound_Ripples), + @(OWSSound_Sencha), + @(OWSSound_Signal), + @(OWSSound_Silk), + @(OWSSound_Slow_Rise), + @(OWSSound_Stargaze), + @(OWSSound_Summit), + @(OWSSound_Twinkle), + @(OWSSound_Uplift), + @(OWSSound_Waves), + ]; +} + ++ (NSString *)displayNameForSound:(OWSSound)sound +{ + // TODO: Should we localize these sound names? + switch (sound) { + case OWSSound_Default: + OWSFail(@"%@ invalid argument.", self.logTag); + return @""; + + // Notification Sounds + case OWSSound_Aurora: + return @"Aurora"; + case OWSSound_Bamboo: + return @"Bamboo"; + case OWSSound_Chord: + return @"Chord"; + case OWSSound_Circles: + return @"Circles"; + case OWSSound_Complete: + return @"Complete"; + case OWSSound_Hello: + return @"Hello"; + case OWSSound_Input: + return @"Input"; + case OWSSound_Keys: + return @"Keys"; + case OWSSound_Note: + return @"Note"; + case OWSSound_Popcorn: + return @"Popcorn"; + case OWSSound_Pulse: + return @"Pulse"; + case OWSSound_Synth: + return @"Synth"; + + // Ringtone Sounds + case OWSSound_Apex: + return @"Apex"; + case OWSSound_Beacon: + return @"Beacon"; + case OWSSound_Bulletin: + return @"Bulletin"; + case OWSSound_By_The_Seaside: + return @"By The Seaside"; + case OWSSound_Chimes: + return @"Chimes"; + case OWSSound_Circuit: + return @"Circuit"; + case OWSSound_Constellation: + return @"Constellation"; + case OWSSound_Cosmic: + return @"Cosmic"; + case OWSSound_Crystals: + return @"Crystals"; + case OWSSound_Hillside: + return @"Hillside"; + case OWSSound_Illuminate: + return @"Illuminate"; + case OWSSound_Night_Owl: + return @"Night Owl"; + case OWSSound_Opening: + return @"Opening"; + case OWSSound_Playtime: + return @"Playtime"; + case OWSSound_Presto: + return @"Presto"; + case OWSSound_Radar: + return @"Radar"; + case OWSSound_Radiate: + return @"Radiate"; + case OWSSound_Ripples: + return @"Ripples"; + case OWSSound_Sencha: + return @"Sencha"; + case OWSSound_Signal: + return @"Signal"; + case OWSSound_Silk: + return @"Silk"; + case OWSSound_Slow_Rise: + return @"Slow Rise"; + case OWSSound_Stargaze: + return @"Stargaze"; + case OWSSound_Summit: + return @"Summit"; + case OWSSound_Twinkle: + return @"Twinkle"; + case OWSSound_Uplift: + return @"Uplift"; + case OWSSound_Waves: + return @"Waves"; + + // Calls + case OWSSound_CallConnecting: + return @"Call Connecting"; + case OWSSound_CallOutboundRinging: + return @"Call Outboung Ringing"; + case OWSSound_CallBusy: + return @"Call Busy"; + case OWSSound_CallFailure: + return @"Call Failure"; + } +} + ++ (NSString *)filenameForSound:(OWSSound)sound +{ + switch (sound) { + case OWSSound_Default: + OWSFail(@"%@ invalid argument.", self.logTag); + return @""; + + // Notification Sounds + case OWSSound_Aurora: + return @"aurora.m4r"; + case OWSSound_Bamboo: + return @"bamboo.m4r"; + case OWSSound_Chord: + return @"chord.m4r"; + case OWSSound_Circles: + return @"circles.m4r"; + case OWSSound_Complete: + return @"complete.m4r"; + case OWSSound_Hello: + return @"hello.m4r"; + case OWSSound_Input: + return @"input.m4r"; + case OWSSound_Keys: + return @"keys.m4r"; + case OWSSound_Note: + return @"note.m4r"; + case OWSSound_Popcorn: + return @"popcorn.m4r"; + case OWSSound_Pulse: + return @"pulse.m4r"; + case OWSSound_Synth: + return @"synth.m4r"; + + // Ringtone Sounds + case OWSSound_Apex: + return @"Apex.m4r"; + case OWSSound_Beacon: + return @"Beacon.m4r"; + case OWSSound_Bulletin: + return @"Bulletin.m4r"; + case OWSSound_By_The_Seaside: + return @"By The Seaside.m4r"; + case OWSSound_Chimes: + return @"Chimes.m4r"; + case OWSSound_Circuit: + return @"Circuit.m4r"; + case OWSSound_Constellation: + return @"Constellation.m4r"; + case OWSSound_Cosmic: + return @"Cosmic.m4r"; + case OWSSound_Crystals: + return @"Crystals.m4r"; + case OWSSound_Hillside: + return @"Hillside.m4r"; + case OWSSound_Illuminate: + return @"Illuminate.m4r"; + case OWSSound_Night_Owl: + return @"Night Owl.m4r"; + case OWSSound_Opening: + return @"Opening.m4r"; + case OWSSound_Playtime: + return @"Playtime.m4r"; + case OWSSound_Presto: + return @"Presto.m4r"; + case OWSSound_Radar: + return @"Radar.m4r"; + case OWSSound_Radiate: + return @"Radiate.m4r"; + case OWSSound_Ripples: + return @"Ripples.m4r"; + case OWSSound_Sencha: + return @"Sencha.m4r"; + case OWSSound_Signal: + return @"Signal.m4r"; + case OWSSound_Silk: + return @"Silk.m4r"; + case OWSSound_Slow_Rise: + return @"Slow Rise.m4r"; + case OWSSound_Stargaze: + return @"Stargaze.m4r"; + case OWSSound_Summit: + return @"Summit.m4r"; + case OWSSound_Twinkle: + return @"Twinkle.m4r"; + case OWSSound_Uplift: + return @"Uplift.m4r"; + case OWSSound_Waves: + return @"Waves.m4r"; + + // Calls + case OWSSound_CallConnecting: + return @"ringback_tone_cept.caf"; + case OWSSound_CallOutboundRinging: + return @"ringback_tone_ansi.caf"; + case OWSSound_CallBusy: + return @"busy_tone_ansi.caf"; + case OWSSound_CallFailure: + return @"end_call_tone_cept.caf"; + } +} + ++ (NSURL *)soundURLForSound:(OWSSound)sound +{ + NSString *filename = [self filenameForSound:sound]; + NSURL *_Nullable url = [[NSBundle mainBundle] URLForResource:filename.stringByDeletingPathExtension + withExtension:filename.pathExtension]; + OWSAssert(url); + return url; +} + ++ (void)playSound:(OWSSound)sound +{ + [self.sharedManager playSound:sound]; +} + +- (SystemSoundID)systemSoundIDForSound:(OWSSound)sound +{ + @synchronized(self) + { + NSNumber *_Nullable systemSoundID = self.systemSoundIDMap[@(sound)]; + if (!systemSoundID) { + NSURL *soundURL = [OWSSounds soundURLForSound:sound]; + SystemSoundID newSystemSoundID; + OSStatus error = AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &newSystemSoundID); + if (error) { + OWSFail(@"%@ could not load sound.", self.logTag); + } + systemSoundID = @(newSystemSoundID); + self.systemSoundIDMap[@(sound)] = systemSoundID; + } + return (SystemSoundID)systemSoundID.unsignedIntegerValue; + } +} + +- (void)playSound:(OWSSound)sound +{ + SystemSoundID systemSoundID = [self systemSoundIDForSound:sound]; + AudioServicesPlayAlertSound(systemSoundID); +} + +#pragma mark - Notifications + ++ (OWSSound)defaultNotificationSound +{ + return OWSSound_Note; +} + ++ (OWSSound)globalNotificationSound +{ + OWSSounds *instance = OWSSounds.sharedManager; + NSNumber *_Nullable value = [instance.dbConnection objectForKey:kOWSSoundsStorageGlobalNotificationKey + inCollection:kOWSSoundsStorageNotificationCollection]; + // Default to the global default. + return (value ? (OWSSound)value.intValue : [self defaultNotificationSound]); +} + ++ (void)setGlobalNotificationSound:(OWSSound)sound +{ + OWSSounds *instance = OWSSounds.sharedManager; + [instance.dbConnection setObject:@(sound) + forKey:kOWSSoundsStorageGlobalNotificationKey + inCollection:kOWSSoundsStorageNotificationCollection]; +} + ++ (OWSSound)notificationSoundForThread:(TSThread *)thread +{ + OWSSounds *instance = OWSSounds.sharedManager; + NSNumber *_Nullable value = + [instance.dbConnection objectForKey:thread.uniqueId inCollection:kOWSSoundsStorageNotificationCollection]; + // Default to the "global" notification sound, which in turn will default to the global default. + return (value ? (OWSSound)value.intValue : [self globalNotificationSound]); +} + ++ (void)setNotificationSound:(OWSSound)sound forThread:(TSThread *)thread +{ + OWSSounds *instance = OWSSounds.sharedManager; + [instance.dbConnection setObject:@(sound) + forKey:thread.uniqueId + inCollection:kOWSSoundsStorageNotificationCollection]; +} + +#pragma mark - Ringtones + ++ (OWSSound)defaultRingtoneSound +{ + return OWSSound_Opening; +} + ++ (OWSSound)globalRingtoneSound +{ + OWSSounds *instance = OWSSounds.sharedManager; + NSNumber *_Nullable value = [instance.dbConnection objectForKey:kOWSSoundsStorageGlobalRingtoneKey + inCollection:kOWSSoundsStorageRingtoneCollection]; + // Default to the global default. + return (value ? (OWSSound)value.intValue : [self defaultRingtoneSound]); +} + ++ (void)setGlobalRingtoneSound:(OWSSound)sound +{ + OWSSounds *instance = OWSSounds.sharedManager; + [instance.dbConnection setObject:@(sound) + forKey:kOWSSoundsStorageGlobalRingtoneKey + inCollection:kOWSSoundsStorageRingtoneCollection]; +} + ++ (OWSSound)ringtoneSoundForThread:(TSThread *)thread +{ + OWSSounds *instance = OWSSounds.sharedManager; + NSNumber *_Nullable value = + [instance.dbConnection objectForKey:thread.uniqueId inCollection:kOWSSoundsStorageRingtoneCollection]; + // Default to the "global" ringtone sound, which in turn will default to the global default. + return (value ? (OWSSound)value.intValue : [self globalRingtoneSound]); +} + ++ (void)setRingtoneSound:(OWSSound)sound forThread:(TSThread *)thread +{ + OWSSounds *instance = OWSSounds.sharedManager; + [instance.dbConnection setObject:@(sound) forKey:thread.uniqueId inCollection:kOWSSoundsStorageRingtoneCollection]; +} + +#pragma mark - Calls + ++ (BOOL)shouldAudioPlayerLoopForSound:(OWSSound)sound +{ + return (sound == OWSSound_CallConnecting || sound == OWSSound_CallOutboundRinging || + [self.allRingtoneSounds containsObject:@(sound)]); +} + ++ (nullable AVAudioPlayer *)audioPlayerForSound:(OWSSound)sound +{ + NSURL *soundURL = [OWSSounds soundURLForSound:sound]; + NSError *error; + AVAudioPlayer *_Nullable player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:&error]; + if (error || !player) { + OWSFail(@"%@ audioPlayerForSound failed with error: %@.", self.logTag, error); + return nil; + } + if ([self shouldAudioPlayerLoopForSound:sound]) { + player.numberOfLoops = -1; + } + return player; +} + +@end