Files
HaishinKit.swift/Examples/macOS/PublishView.swift
2025-12-09 00:47:00 +09:00

111 lines
2.9 KiB
Swift

import AVFoundation
import HaishinKit
import SwiftUI
enum FPS: String, CaseIterable, Identifiable {
case fps15 = "15"
case fps30 = "30"
case fps60 = "60"
var frameRate: Float64 {
switch self {
case .fps15:
return 15
case .fps30:
return 30
case .fps60:
return 60
}
}
var id: Self { self }
}
enum VideoEffectItem: String, CaseIterable, Identifiable, Sendable {
case none
case monochrome
var id: Self { self }
func makeVideoEffect() -> VideoEffect? {
switch self {
case .none:
return nil
case .monochrome:
return MonochromeEffect()
}
}
}
struct PublishView: View {
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
@EnvironmentObject var preference: PreferenceViewModel
@StateObject private var model = PublishViewModel()
var body: some View {
ZStack {
VStack {
MTHKViewRepresentable(previewSource: model)
}
VStack(alignment: .trailing) {
Picker("FPS", selection: $model.currentFPS) {
ForEach(FPS.allCases) {
Text($0.rawValue).tag($0)
}
}
.onChange(of: model.currentFPS) { tag in
model.setFrameRate(tag.frameRate)
}
.pickerStyle(.segmented)
.frame(width: 150)
.padding()
Spacer()
}
}
.onAppear {
model.startRunning(preference)
}
.onDisappear {
model.stopRunning()
}
.navigationTitle("Publish")
.toolbar {
switch model.readyState {
case .connecting:
ToolbarItem(placement: .primaryAction) {
}
case .open:
ToolbarItem(placement: .primaryAction) {
Button(action: {
model.stopPublishing()
}) {
Image(systemName: "stop.circle")
}
}
case .closed:
ToolbarItem(placement: .primaryAction) {
Button(action: {
model.startPublishing(preference)
}) {
Image(systemName: "record.circle")
}
}
case .closing:
ToolbarItem(placement: .primaryAction) {
}
}
}
.alert(isPresented: $model.isShowError) {
Alert(
title: Text("Error"),
message: Text(model.error?.localizedDescription ?? ""),
dismissButton: .default(Text("OK"))
)
}
}
}
#Preview {
PublishView()
}