captains-log

[TO-FIX] audiojournaling app
git clone git://git.figbert.com/captains-log.git
Log | Files | Refs

AudioRecorder.swift (8214B)


      1 //
      2 //  AudioRecorder.swift
      3 //  captainsLog
      4 //
      5 //  Created by Benjamin Welner on 10/29/19.
      6 //  Copyright © 2019 FIGBERT Industries. All rights reserved.
      7 //
      8 
      9 import Foundation
     10 import SwiftUI
     11 import Combine
     12 import AVFoundation
     13 
     14 class AudioRecorder: NSObject, ObservableObject {
     15     
     16     override init() {
     17         super.init()
     18         fetchRecordings()
     19     }
     20     
     21     var audioRecorder: AVAudioRecorder!
     22     @Published var recordings = [Recording]()
     23     @Published var recording: Bool = false
     24     @Published var hasRecorded: Bool = false
     25     
     26     func startRecording() {
     27         if (!hasRecorded) {
     28             let recordingSession = AVAudioSession.sharedInstance()
     29             do {
     30                 try recordingSession.setCategory(.playAndRecord, mode: .default)
     31                 try recordingSession.setActive(true)
     32             } catch {
     33                 print("Failed to set up audio session")
     34             }
     35             let documentPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
     36             let rawDate = Date()
     37             let dateMatch = rawDate.toString(dateFormat: "dd-MM-YY_'at'_HH:mm:ss")
     38             let audioFilename = documentPath.appendingPathComponent("\(dateMatch).m4a")
     39             let jsonFilename = documentPath.appendingPathComponent("\(dateMatch).json")
     40             let title = "alertHere"
     41             let number = recordings.count+1
     42             let detailObject = Recording(audioURL: audioFilename, fileURL: jsonFilename, createdAt: rawDate, title: title, number: number)
     43             let json = try! JSONEncoder().encode(detailObject)
     44             let settings = [
     45                 AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
     46                 AVSampleRateKey: 12000,
     47                 AVNumberOfChannelsKey: 1,
     48                 AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
     49             ]
     50             do {
     51                 audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
     52                 audioRecorder.record()
     53                 recording = true
     54                 hasRecorded = true
     55             } catch {
     56                 print("Could not start recording")
     57             }
     58             do {
     59                 try json.write(to: jsonFilename)
     60             } catch {
     61                 print("Could not write files")
     62             }
     63         } else {
     64             audioRecorder.record()
     65             recording = true
     66         }
     67     }
     68     
     69     func pauseRecording() {
     70         audioRecorder.pause()
     71         recording = false
     72     }
     73     
     74     func endRecording() {
     75         audioRecorder.stop()
     76         recording = false
     77         hasRecorded = false
     78         fetchRecordings()
     79     }
     80     
     81     func getCreationDate(for file: URL) -> Date {
     82         if let attributes = try? FileManager.default.attributesOfItem(atPath: file.path) as [FileAttributeKey: Any],
     83             let creationDate = attributes[FileAttributeKey.creationDate] as? Date {
     84             return creationDate
     85         } else {
     86             return Date()
     87         }
     88     }
     89     
     90     func fetchRecordings() {
     91         recordings.removeAll()
     92         let fileManager = FileManager.default
     93         let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
     94         let directoryContents = try! fileManager.contentsOfDirectory(at: documentDirectory, includingPropertiesForKeys: nil)
     95         for file in directoryContents {
     96             if (file.pathExtension == "json") {
     97                 let contents = try! String(contentsOf: file, encoding: .utf8)
     98                 let serialized = contents.data(using: .utf8)!
     99                 let recording = try! JSONDecoder().decode(Recording.self, from: serialized)
    100                 recordings.append(recording)
    101             }
    102         }
    103         recordings.sort(by: { $0.createdAt.compare($1.createdAt) == .orderedAscending})
    104         for (index, _) in recordings.enumerated() {
    105             recordings[index].number = index + 1
    106         }
    107     }
    108     
    109     func deleteRecording(urlsToDelete: [URL]) {
    110         for url in urlsToDelete {
    111             do {
    112                 try FileManager.default.removeItem(at: url)
    113             } catch {
    114                 print("File could not be deleted")
    115             }
    116         }
    117         fetchRecordings()
    118     }
    119 }
    120 
    121 struct RecordingRow: View {
    122     var audioURL: URL
    123     let createdAt: Date
    124     let title: String
    125     let number: Int
    126     @State private var strDate: String = ""
    127     @ObservedObject var audioPlayer = AudioPlayer()
    128     @EnvironmentObject var globalVars: GlobalVars
    129     var body: some View {
    130         HStack {
    131             VStack(alignment: .leading) {
    132                 Text("\(title)")
    133                     .font(.headline)
    134                 Group {
    135                     if (globalVars.currentDateFormat == 1) {
    136                         Text("#\(number) – \(createdAt.multi(type: "Jewish").joined(separator: ""))")
    137                             .font(.caption)
    138                     } else if (globalVars.currentDateFormat == 2) {
    139                         Text("#\(number) – \(createdAt.multi(type: "Islamic").joined(separator: ""))")
    140                             .font(.caption)
    141                     } else if (globalVars.currentDateFormat == 3) {
    142                         Text("#\(number) – \(createdAt.multi(type: "Persian").joined(separator: ""))")
    143                             .font(.caption)
    144                     } else if (globalVars.currentDateFormat == 4) {
    145                         Text("#\(number) – \(createdAt.multi(type: "Indian").joined(separator: ""))")
    146                             .font(.caption)
    147                     } else if (globalVars.currentDateFormat == 5) {
    148                         Text("#\(number) – \(createdAt.multi(type: "Coptic").joined(separator: ""))")
    149                             .font(.caption)
    150                     } else if (globalVars.currentDateFormat == 6) {
    151                         Text("#\(number) – \(createdAt.multi(type: "Chinese").joined(separator: ""))")
    152                             .font(.caption)
    153                     } else if (globalVars.currentDateFormat == 7) {
    154                         Text("#\(number) – \(createdAt.multi(type: "Japanese").joined(separator: ""))")
    155                             .font(.caption)
    156                     } else if (globalVars.currentDateFormat == 8) {
    157                         Text("#\(number) – \(createdAt.multi(type: "Ethiopian").joined(separator: ""))")
    158                             .font(.caption)
    159                     } else if (globalVars.currentDateFormat == 9) {
    160                         Text("#\(number) – \(createdAt.multi(type: "Gregorian").joined(separator: ""))")
    161                             .font(.caption)
    162                     } else {
    163                         Text("#\(number) – \(createdAt.stardate().joined(separator: " "))")
    164                             .font(.caption)
    165                     }
    166                 }
    167             }
    168             Spacer()
    169             if (!audioPlayer.isPlaying) {
    170                 Button(action: {
    171                     self.audioPlayer.startPlayback(audio: self.audioURL)
    172                 }) {
    173                     Image(
    174                         uiImage: UIImage(
    175                             systemName: "play.circle",
    176                             withConfiguration: UIImage.SymbolConfiguration(
    177                                 pointSize: CGFloat.init(15),
    178                                 weight: .regular,
    179                                 scale: .large
    180                             )
    181                         )!
    182                     )
    183                 }
    184             } else {
    185                 Button(action: {
    186                     self.audioPlayer.pausePlayback()
    187                 }) {
    188                     Image(
    189                         uiImage: UIImage (
    190                             systemName: "pause.circle",
    191                             withConfiguration: UIImage.SymbolConfiguration(
    192                                 pointSize: CGFloat.init(15),
    193                                 weight: .regular,
    194                                 scale: .large
    195                             )
    196                         )!
    197                     )
    198                 }
    199             }
    200         }
    201     }
    202 }
    203 
    204 struct Recording: Codable {
    205     let audioURL: URL
    206     let fileURL: URL
    207     let createdAt: Date
    208     let title: String
    209     var number: Int
    210 }