Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
6fd0562a41
commit
2904536334
@ -8,26 +8,60 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
/// Sound data model for audio files
|
/// Sound data model for audio files
|
||||||
public struct Sound: Identifiable, Hashable {
|
public struct Sound: Identifiable, Hashable, Codable {
|
||||||
public let id: String
|
public let id: String
|
||||||
public let name: String
|
public let name: String
|
||||||
public let fileName: String
|
public let fileName: String
|
||||||
public let category: String
|
public let category: String
|
||||||
public let description: String
|
public let description: String
|
||||||
public let bundleName: String? // Optional bundle name for organization
|
public let bundleName: String? // Optional bundle name for organization
|
||||||
|
public let isDefault: Bool? // Optional - used for alarm sounds to mark default
|
||||||
|
|
||||||
// MARK: - Initialization
|
// MARK: - Initialization
|
||||||
public init(name: String, fileName: String, category: String, description: String, bundleName: String? = nil) {
|
public init(id: String? = nil, name: String, fileName: String, category: String, description: String, bundleName: String? = nil, isDefault: Bool? = nil) {
|
||||||
self.id = fileName // Use fileName as stable identifier
|
self.id = id ?? UUID().uuidString // Use provided id or generate GUID
|
||||||
self.name = name
|
self.name = name
|
||||||
self.fileName = fileName
|
self.fileName = fileName
|
||||||
self.category = category
|
self.category = category
|
||||||
self.description = description
|
self.description = description
|
||||||
self.bundleName = bundleName
|
self.bundleName = bundleName
|
||||||
|
self.isDefault = isDefault
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Codable Custom Implementation
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
// Generate a new GUID for each sound loaded from JSON
|
||||||
|
self.id = UUID().uuidString
|
||||||
|
|
||||||
|
self.name = try container.decode(String.self, forKey: .name)
|
||||||
|
self.fileName = try container.decode(String.self, forKey: .fileName)
|
||||||
|
self.category = try container.decode(String.self, forKey: .category)
|
||||||
|
self.description = try container.decode(String.self, forKey: .description)
|
||||||
|
self.bundleName = try container.decodeIfPresent(String.self, forKey: .bundleName)
|
||||||
|
self.isDefault = try container.decodeIfPresent(Bool.self, forKey: .isDefault)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(id, forKey: .id)
|
||||||
|
try container.encode(name, forKey: .name)
|
||||||
|
try container.encode(fileName, forKey: .fileName)
|
||||||
|
try container.encode(category, forKey: .category)
|
||||||
|
try container.encode(description, forKey: .description)
|
||||||
|
try container.encodeIfPresent(bundleName, forKey: .bundleName)
|
||||||
|
try container.encodeIfPresent(isDefault, forKey: .isDefault)
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case id, name, fileName, category, description, bundleName, isDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Hashable
|
// MARK: - Hashable
|
||||||
public func hash(into hasher: inout Hasher) {
|
public func hash(into hasher: inout Hasher) {
|
||||||
hasher.combine(id)
|
hasher.combine(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,40 +9,17 @@ import Foundation
|
|||||||
|
|
||||||
/// Configuration model for sound system loaded from JSON
|
/// Configuration model for sound system loaded from JSON
|
||||||
public struct SoundConfiguration: Codable {
|
public struct SoundConfiguration: Codable {
|
||||||
public let sounds: [SoundConfig]
|
public let sounds: [Sound]
|
||||||
public let categories: [SoundCategory]
|
public let categories: [SoundCategory]
|
||||||
public let settings: AudioSettings
|
public let settings: AudioSettings
|
||||||
|
|
||||||
public init(sounds: [SoundConfig], categories: [SoundCategory], settings: AudioSettings) {
|
public init(sounds: [Sound], categories: [SoundCategory], settings: AudioSettings) {
|
||||||
self.sounds = sounds
|
self.sounds = sounds
|
||||||
self.categories = categories
|
self.categories = categories
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Individual sound configuration
|
|
||||||
public struct SoundConfig: Codable, Identifiable {
|
|
||||||
public let id: String
|
|
||||||
public let name: String
|
|
||||||
public let fileName: String
|
|
||||||
public let category: String
|
|
||||||
public let description: String
|
|
||||||
public let bundleName: String? // Optional bundle name for organization
|
|
||||||
|
|
||||||
public init(id: String, name: String, fileName: String, category: String, description: String, bundleName: String? = nil) {
|
|
||||||
self.id = id
|
|
||||||
self.name = name
|
|
||||||
self.fileName = fileName
|
|
||||||
self.category = category
|
|
||||||
self.description = description
|
|
||||||
self.bundleName = bundleName
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert to Sound model for compatibility
|
|
||||||
public func toSound() -> Sound {
|
|
||||||
return Sound(name: name, fileName: fileName, category: category, description: description, bundleName: bundleName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sound category configuration
|
/// Sound category configuration
|
||||||
public struct SoundCategory: Codable, Identifiable {
|
public struct SoundCategory: Codable, Identifiable {
|
||||||
@ -89,10 +66,9 @@ public class SoundConfigurationService {
|
|||||||
private init() {}
|
private init() {}
|
||||||
|
|
||||||
/// Load sound configuration from JSON file
|
/// Load sound configuration from JSON file
|
||||||
public func loadConfiguration(from bundle: Bundle = .main, fileName: String = "sounds") -> SoundConfiguration? {
|
public func loadConfiguration(from bundle: Bundle = .main, fileName: String = "sounds") -> SoundConfiguration {
|
||||||
guard let url = bundle.url(forResource: fileName, withExtension: "json") else {
|
guard let url = bundle.url(forResource: fileName, withExtension: "json") else {
|
||||||
print("❌ \(fileName).json not found in bundle")
|
fatalError("❌ \(fileName).json not found in bundle. Ensure the file exists in your app bundle.")
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -102,81 +78,43 @@ public class SoundConfigurationService {
|
|||||||
print("✅ Loaded sound configuration with \(config.sounds.count) sounds")
|
print("✅ Loaded sound configuration with \(config.sounds.count) sounds")
|
||||||
return config
|
return config
|
||||||
} catch {
|
} catch {
|
||||||
print("❌ Error loading sound configuration: \(error)")
|
fatalError("❌ Error loading sound configuration: \(error)")
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get current configuration
|
/// Get current configuration
|
||||||
public func getConfiguration() -> SoundConfiguration? {
|
public func getConfiguration() -> SoundConfiguration {
|
||||||
if configuration == nil {
|
if configuration == nil {
|
||||||
return loadConfiguration()
|
return loadConfiguration()
|
||||||
}
|
}
|
||||||
return configuration
|
return configuration!
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get all available sounds
|
/// Get all available sounds
|
||||||
public func getAvailableSounds() -> [Sound] {
|
public func getAvailableSounds() -> [Sound] {
|
||||||
guard let config = getConfiguration() else {
|
return getConfiguration().sounds
|
||||||
print("⚠️ No configuration available, falling back to constants")
|
|
||||||
return getFallbackSounds()
|
|
||||||
}
|
|
||||||
|
|
||||||
return config.sounds.map { $0.toSound() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get sounds by category
|
/// Get sounds by category
|
||||||
public func getSoundsByCategory(_ categoryId: String) -> [Sound] {
|
public func getSoundsByCategory(_ categoryId: String) -> [Sound] {
|
||||||
guard let config = getConfiguration() else {
|
return getConfiguration().sounds
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
return config.sounds
|
|
||||||
.filter { $0.category == categoryId }
|
.filter { $0.category == categoryId }
|
||||||
.map { $0.toSound() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get sounds by bundle name
|
/// Get sounds by bundle name
|
||||||
public func getSoundsByBundle(_ bundleName: String) -> [Sound] {
|
public func getSoundsByBundle(_ bundleName: String) -> [Sound] {
|
||||||
guard let config = getConfiguration() else {
|
return getConfiguration().sounds
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
return config.sounds
|
|
||||||
.filter { $0.bundleName == bundleName }
|
.filter { $0.bundleName == bundleName }
|
||||||
.map { $0.toSound() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get alarm sounds specifically
|
|
||||||
public func getAlarmSounds() -> [Sound] {
|
|
||||||
return getSoundsByCategory("alarm")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get available categories
|
/// Get available categories
|
||||||
public func getAvailableCategories() -> [SoundCategory] {
|
public func getAvailableCategories() -> [SoundCategory] {
|
||||||
return getConfiguration()?.categories ?? []
|
return getConfiguration().categories
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get audio settings
|
/// Get audio settings
|
||||||
public func getAudioSettings() -> AudioSettings? {
|
public func getAudioSettings() -> AudioSettings {
|
||||||
return getConfiguration()?.settings
|
return getConfiguration().settings
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fallback sounds if JSON loading fails
|
|
||||||
private func getFallbackSounds() -> [Sound] {
|
|
||||||
return [
|
|
||||||
// White noise sounds
|
|
||||||
Sound(name: "White Noise", fileName: "white-noise.mp3", category: "ambient", description: "Classic white noise for focus and relaxation", bundleName: "Ambient"),
|
|
||||||
Sound(name: "Heavy Rain White Noise", fileName: "heavy-rain-white-noise.mp3", category: "nature", description: "Heavy rainfall sounds for peaceful sleep", bundleName: "Nature"),
|
|
||||||
Sound(name: "Fan White Noise", fileName: "fan-white-noise-heater.mp3", category: "mechanical", description: "Fan and heater sounds for consistent background noise", bundleName: "Mechanical"),
|
|
||||||
|
|
||||||
// Alarm sounds
|
|
||||||
Sound(name: "Digital Alarm", fileName: "digital-alarm.mp3", category: "alarm", description: "Classic digital alarm sound", bundleName: "AlarmSounds"),
|
|
||||||
Sound(name: "iPhone Alarm", fileName: "iphone-alarm.mp3", category: "alarm", description: "iPhone-style alarm sound", bundleName: "AlarmSounds"),
|
|
||||||
Sound(name: "Classic Alarm", fileName: "classic-alarm.mp3", category: "alarm", description: "Traditional alarm sound", bundleName: "AlarmSounds"),
|
|
||||||
Sound(name: "Beep Alarm", fileName: "beep-alarm.mp3", category: "alarm", description: "Short beep alarm sound", bundleName: "AlarmSounds"),
|
|
||||||
Sound(name: "Siren Alarm", fileName: "siren-alarm.mp3", category: "alarm", description: "Emergency siren alarm for heavy sleepers", bundleName: "AlarmSounds"),
|
|
||||||
Sound(name: "Voice Wake Up", fileName: "voice-wakeup.mp3", category: "alarm", description: "Voice-based wake up sound", bundleName: "AlarmSounds")
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,11 +128,11 @@ public class NoisePlayer {
|
|||||||
let settings = soundConfigurationService.getAudioSettings()
|
let settings = soundConfigurationService.getAudioSettings()
|
||||||
|
|
||||||
// Use configuration settings or fall back to constants
|
// Use configuration settings or fall back to constants
|
||||||
let category = settings?.audioSessionCategory == "playback" ?
|
let category = settings.audioSessionCategory == "playback" ?
|
||||||
AVAudioSession.Category.playback : AudioConstants.AudioSession.category
|
AVAudioSession.Category.playback : AudioConstants.AudioSession.category
|
||||||
let mode = settings?.audioSessionMode == "default" ?
|
let mode = settings.audioSessionMode == "default" ?
|
||||||
AVAudioSession.Mode.default : AudioConstants.AudioSession.mode
|
AVAudioSession.Mode.default : AudioConstants.AudioSession.mode
|
||||||
let options: AVAudioSession.CategoryOptions = settings?.audioSessionOptions.contains("mixWithOthers") == true ?
|
let options: AVAudioSession.CategoryOptions = settings.audioSessionOptions.contains("mixWithOthers") == true ?
|
||||||
[.mixWithOthers] : AudioConstants.AudioSession.options
|
[.mixWithOthers] : AudioConstants.AudioSession.options
|
||||||
|
|
||||||
try AVAudioSession.sharedInstance().setCategory(category, mode: mode, options: options)
|
try AVAudioSession.sharedInstance().setCategory(category, mode: mode, options: options)
|
||||||
@ -163,9 +163,9 @@ public class NoisePlayer {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
let player = try AVAudioPlayer(contentsOf: fileUrl)
|
let player = try AVAudioPlayer(contentsOf: fileUrl)
|
||||||
player.numberOfLoops = settings?.defaultLoopCount ?? AudioConstants.Playback.numberOfLoops
|
player.numberOfLoops = settings.defaultLoopCount
|
||||||
player.volume = settings?.defaultVolume ?? AudioConstants.Volume.default
|
player.volume = settings.defaultVolume
|
||||||
if settings?.preloadSounds ?? AudioConstants.Playback.prepareToPlay {
|
if settings.preloadSounds {
|
||||||
player.prepareToPlay()
|
player.prepareToPlay()
|
||||||
}
|
}
|
||||||
players[sound.fileName] = player
|
players[sound.fileName] = player
|
||||||
|
|||||||
65
TheNoiseClock/Resources/alarm-sounds.json
Normal file
65
TheNoiseClock/Resources/alarm-sounds.json
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"sounds": [
|
||||||
|
{
|
||||||
|
"id": "digital-alarm",
|
||||||
|
"name": "Digital Alarm",
|
||||||
|
"fileName": "digital-alarm.caf",
|
||||||
|
"description": "Classic digital alarm sound",
|
||||||
|
"category": "alarm",
|
||||||
|
"bundleName": null,
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "buzzing-alarm",
|
||||||
|
"name": "Buzzing Alarm",
|
||||||
|
"fileName": "buzzing-alarm.caf",
|
||||||
|
"description": "Buzzing sound for gentle wake-up",
|
||||||
|
"category": "alarm",
|
||||||
|
"bundleName": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "classic-alarm",
|
||||||
|
"name": "Classic Alarm",
|
||||||
|
"fileName": "classic-alarm.caf",
|
||||||
|
"description": "Traditional alarm sound",
|
||||||
|
"category": "alarm",
|
||||||
|
"bundleName": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "beep-alarm",
|
||||||
|
"name": "Beep Alarm",
|
||||||
|
"fileName": "beep-alarm.caf",
|
||||||
|
"description": "Short beep alarm sound",
|
||||||
|
"category": "alarm",
|
||||||
|
"bundleName": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "siren-alarm",
|
||||||
|
"name": "Siren Alarm",
|
||||||
|
"fileName": "siren-alarm.caf",
|
||||||
|
"description": "Emergency siren alarm for heavy sleepers",
|
||||||
|
"category": "alarm",
|
||||||
|
"bundleName": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"id": "alarm",
|
||||||
|
"name": "Alarm Sounds",
|
||||||
|
"description": "Wake-up and notification alarm sounds",
|
||||||
|
"bundleName": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"defaultVolume": 1.0,
|
||||||
|
"defaultLoopCount": -1,
|
||||||
|
"preloadSounds": true,
|
||||||
|
"preloadStrategy": "category",
|
||||||
|
"audioSessionCategory": "playback",
|
||||||
|
"audioSessionMode": "default",
|
||||||
|
"audioSessionOptions": ["mixWithOthers"],
|
||||||
|
"defaultSound": "digital-alarm.caf",
|
||||||
|
"previewDuration": 3.0,
|
||||||
|
"fadeInDuration": 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,46 +23,6 @@
|
|||||||
"category": "mechanical",
|
"category": "mechanical",
|
||||||
"description": "Fan and heater sounds for consistent background noise",
|
"description": "Fan and heater sounds for consistent background noise",
|
||||||
"bundleName": "Mechanical"
|
"bundleName": "Mechanical"
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "digital-alarm",
|
|
||||||
"name": "Digital Alarm",
|
|
||||||
"fileName": "digital-alarm.caf",
|
|
||||||
"category": "alarm",
|
|
||||||
"description": "Classic digital alarm sound",
|
|
||||||
"bundleName": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "iphone-alarm",
|
|
||||||
"name": "Buzzing Alarm",
|
|
||||||
"fileName": "buzzing-alarm.caf",
|
|
||||||
"category": "alarm",
|
|
||||||
"description": "Buzzing sound",
|
|
||||||
"bundleName": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "classic-alarm",
|
|
||||||
"name": "Classic Alarm",
|
|
||||||
"fileName": "classic-alarm.caf",
|
|
||||||
"category": "alarm",
|
|
||||||
"description": "Traditional alarm sound",
|
|
||||||
"bundleName": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "beep-alarm",
|
|
||||||
"name": "Beep Alarm",
|
|
||||||
"fileName": "beep-alarm.caf",
|
|
||||||
"category": "alarm",
|
|
||||||
"description": "Short beep alarm sound",
|
|
||||||
"bundleName": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "siren-alarm",
|
|
||||||
"name": "Siren Alarm",
|
|
||||||
"fileName": "siren-alarm.caf",
|
|
||||||
"category": "alarm",
|
|
||||||
"description": "Emergency siren alarm for heavy sleepers",
|
|
||||||
"bundleName": null
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"categories": [
|
"categories": [
|
||||||
@ -83,12 +43,6 @@
|
|||||||
"name": "Mechanical",
|
"name": "Mechanical",
|
||||||
"description": "Mechanical and electronic sounds",
|
"description": "Mechanical and electronic sounds",
|
||||||
"bundleName": "Mechanical"
|
"bundleName": "Mechanical"
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "alarm",
|
|
||||||
"name": "Alarm Sounds",
|
|
||||||
"description": "Wake-up and notification alarm sounds",
|
|
||||||
"bundleName": "AlarmSounds"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
|
|||||||
76
TheNoiseClock/Services/AlarmSoundService.swift
Normal file
76
TheNoiseClock/Services/AlarmSoundService.swift
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// AlarmSoundService.swift
|
||||||
|
// TheNoiseClock
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 9/8/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import AudioPlaybackKit
|
||||||
|
|
||||||
|
/// Extension service for alarm-specific sound functionality
|
||||||
|
class AlarmSoundService {
|
||||||
|
static let shared = AlarmSoundService()
|
||||||
|
|
||||||
|
// MARK: - Constants
|
||||||
|
/// The category ID for alarm sounds as defined in alarm-sounds.json
|
||||||
|
static let alarmCategoryId = "alarm"
|
||||||
|
|
||||||
|
private init() {}
|
||||||
|
|
||||||
|
/// Load alarm sound configuration from alarm-sounds.json
|
||||||
|
private func loadAlarmConfiguration() -> SoundConfiguration {
|
||||||
|
guard let url = Bundle.main.url(forResource: "alarm-sounds", withExtension: "json") else {
|
||||||
|
fatalError("❌ alarm-sounds.json not found in bundle. Ensure the file exists in your app bundle.")
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
let data = try Data(contentsOf: url)
|
||||||
|
let config = try JSONDecoder().decode(SoundConfiguration.self, from: data)
|
||||||
|
return config
|
||||||
|
} catch {
|
||||||
|
fatalError("❌ Error loading alarm sound configuration: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get all available alarm sounds
|
||||||
|
func getAlarmSounds() -> [Sound] {
|
||||||
|
return loadAlarmConfiguration().sounds
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get alarm sounds by category
|
||||||
|
func getAlarmSoundsByCategory(_ categoryId: String) -> [Sound] {
|
||||||
|
return loadAlarmConfiguration().sounds
|
||||||
|
.filter { $0.category == categoryId }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get alarm sounds for the default alarm category
|
||||||
|
func getAlarmSoundsForDefaultCategory() -> [Sound] {
|
||||||
|
return getAlarmSoundsByCategory(Self.alarmCategoryId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get default alarm sound
|
||||||
|
func getDefaultAlarmSound() -> Sound? {
|
||||||
|
let sounds = loadAlarmConfiguration().sounds
|
||||||
|
return sounds.first { $0.isDefault == true } ?? sounds.first
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get alarm sound categories
|
||||||
|
func getAlarmSoundCategories() -> [SoundCategory] {
|
||||||
|
return loadAlarmConfiguration().categories
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get alarm sound settings
|
||||||
|
func getAlarmSoundSettings() -> AudioSettings {
|
||||||
|
return loadAlarmConfiguration().settings
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get sound display name by filename
|
||||||
|
func getSoundDisplayName(_ fileName: String) -> String {
|
||||||
|
let alarmSounds = getAlarmSounds()
|
||||||
|
if let sound = alarmSounds.first(where: { $0.fileName == fileName }) {
|
||||||
|
return sound.name
|
||||||
|
}
|
||||||
|
return fileName.replacingOccurrences(of: ".caf", with: "").capitalized
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -125,10 +125,6 @@ struct AddAlarmView: View {
|
|||||||
|
|
||||||
// MARK: - Helper Methods
|
// MARK: - Helper Methods
|
||||||
private func getSoundDisplayName(_ fileName: String) -> String {
|
private func getSoundDisplayName(_ fileName: String) -> String {
|
||||||
let alarmSounds = SoundConfigurationService.shared.getAlarmSounds()
|
return AlarmSoundService.shared.getSoundDisplayName(fileName)
|
||||||
if let sound = alarmSounds.first(where: { $0.fileName == fileName }) {
|
|
||||||
return sound.name
|
|
||||||
}
|
|
||||||
return fileName.replacingOccurrences(of: ".mp3", with: "").capitalized
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -15,7 +15,7 @@ struct SoundSelectionView: View {
|
|||||||
|
|
||||||
// Use shared player instance to avoid audio conflicts
|
// Use shared player instance to avoid audio conflicts
|
||||||
private let noisePlayer = NoisePlayer.shared
|
private let noisePlayer = NoisePlayer.shared
|
||||||
private let alarmSounds = SoundConfigurationService.shared.getAlarmSounds().sorted { $0.name < $1.name }
|
private let alarmSounds = AlarmSoundService.shared.getAlarmSounds().sorted { $0.name < $1.name }
|
||||||
|
|
||||||
@State private var isPlaying = false
|
@State private var isPlaying = false
|
||||||
@State private var currentlyPlayingSound: String? = nil
|
@State private var currentlyPlayingSound: String? = nil
|
||||||
|
|||||||
@ -145,11 +145,7 @@ struct EditAlarmView: View {
|
|||||||
|
|
||||||
// MARK: - Helper Methods
|
// MARK: - Helper Methods
|
||||||
private func getSoundDisplayName(_ fileName: String) -> String {
|
private func getSoundDisplayName(_ fileName: String) -> String {
|
||||||
let alarmSounds = SoundConfigurationService.shared.getAlarmSounds()
|
return AlarmSoundService.shared.getSoundDisplayName(fileName)
|
||||||
if let sound = alarmSounds.first(where: { $0.fileName == fileName }) {
|
|
||||||
return sound.name
|
|
||||||
}
|
|
||||||
return fileName.replacingOccurrences(of: ".mp3", with: "").capitalized
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user