HaishinKit.swift/Examples/macOS/MainViewController.swift

164 lines
6.0 KiB
Swift

import AVFoundation
import Cocoa
import HaishinKit
import VideoToolbox
extension NSPopUpButton {
fileprivate func present(mediaType: AVMediaType) {
let devices = AVCaptureDevice.devices(for: mediaType)
devices.forEach {
self.addItem(withTitle: $0.localizedName)
}
}
}
final class MainViewController: NSViewController {
var rtmpConnection = RTMPConnection()
var rtmpStream: RTMPStream!
var httpService = HLSService(
domain: "local", type: HTTPService.type, name: "", port: HTTPService.defaultPort
)
var httpStream = HTTPStream()
@IBOutlet private weak var lfView: MTHKView!
@IBOutlet private weak var audioPopUpButton: NSPopUpButton!
@IBOutlet private weak var cameraPopUpButton: NSPopUpButton!
@IBOutlet private weak var urlField: NSTextField!
@IBOutlet private weak var segmentedControl: NSSegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
rtmpStream = RTMPStream(connection: rtmpConnection)
rtmpStream.addObserver(self, forKeyPath: "currentFPS", options: .new, context: nil)
urlField.stringValue = Preference.defaultInstance.uri ?? ""
audioPopUpButton?.present(mediaType: .audio)
cameraPopUpButton?.present(mediaType: .video)
}
override func viewWillAppear() {
super.viewWillAppear()
rtmpStream.attachAudio(DeviceUtil.device(withLocalizedName: audioPopUpButton.titleOfSelectedItem!, mediaType: .audio))
rtmpStream.attachCamera(DeviceUtil.device(withLocalizedName: cameraPopUpButton.titleOfSelectedItem!, mediaType: .video))
lfView?.attachStream(rtmpStream)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
guard let keyPath: String = keyPath, Thread.isMainThread else {
return
}
switch keyPath {
case "currentFPS":
view.window!.title = "HaishinKit(FPS: \(rtmpStream.currentFPS): totalBytesIn: \(rtmpConnection.totalBytesIn): totalBytesOut: \(rtmpConnection.totalBytesOut))"
default:
break
}
}
@IBAction private func publishOrStop(_ sender: NSButton) {
// Publish
if sender.title == "Publish" {
sender.title = "Stop"
segmentedControl.isEnabled = false
switch segmentedControl.selectedSegment {
case 0:
rtmpConnection.addEventListener(.rtmpStatus, selector: #selector(rtmpStatusHandler), observer: self)
rtmpConnection.connect(urlField.stringValue)
case 1:
httpStream.publish("hello")
httpService.addHTTPStream(httpStream)
httpService.startRunning()
default:
break
}
return
}
// Stop
sender.title = "Publish"
segmentedControl.isEnabled = true
switch segmentedControl.selectedSegment {
case 0:
rtmpConnection.removeEventListener(.rtmpStatus, selector: #selector(rtmpStatusHandler), observer: self)
rtmpConnection.close()
case 1:
httpService.removeHTTPStream(httpStream)
httpService.stopRunning()
httpStream.publish(nil)
default:
break
}
return
}
@IBAction private func orientation(_ sender: AnyObject) {
lfView.rotate(byDegrees: 90)
}
@IBAction private func selectAudio(_ sender: AnyObject) {
let device: AVCaptureDevice? = DeviceUtil.device(withLocalizedName: audioPopUpButton.titleOfSelectedItem!, mediaType: .audio)
switch segmentedControl.selectedSegment {
case 0:
rtmpStream.attachAudio(device)
httpStream.attachAudio(nil)
case 1:
rtmpStream.attachAudio(nil)
httpStream.attachAudio(device)
default:
break
}
}
@IBAction private func selectCamera(_ sender: AnyObject) {
let device: AVCaptureDevice? = DeviceUtil.device(withLocalizedName: cameraPopUpButton.titleOfSelectedItem!, mediaType: .video)
switch segmentedControl.selectedSegment {
case 0:
rtmpStream.attachCamera(device)
httpStream.attachCamera(nil)
case 1:
rtmpStream.attachCamera(nil)
httpStream.attachCamera(device)
default:
break
}
}
@IBAction private func modeChanged(_ sender: NSSegmentedControl) {
switch sender.selectedSegment {
case 0:
httpStream.attachAudio(nil)
httpStream.attachCamera(nil)
rtmpStream.attachAudio(DeviceUtil.device(withLocalizedName: audioPopUpButton.titleOfSelectedItem!, mediaType: .audio))
rtmpStream.attachCamera(DeviceUtil.device(withLocalizedName: cameraPopUpButton.titleOfSelectedItem!, mediaType: .video))
lfView.attachStream(rtmpStream)
urlField.stringValue = Preference.defaultInstance.uri ?? ""
case 1:
rtmpStream.attachAudio(nil)
rtmpStream.attachCamera(nil)
httpStream.attachAudio(DeviceUtil.device(withLocalizedName: audioPopUpButton.titleOfSelectedItem!, mediaType: .audio))
httpStream.attachCamera(DeviceUtil.device(withLocalizedName: cameraPopUpButton.titleOfSelectedItem!, mediaType: .video))
lfView.attachStream(httpStream)
urlField.stringValue = "http://{ipAddress}:8080/hello/playlist.m3u8"
default:
break
}
}
@objc
private func rtmpStatusHandler(_ notification: Notification) {
let e = Event.from(notification)
guard
let data: ASObject = e.data as? ASObject,
let code: String = data["code"] as? String else {
return
}
switch code {
case RTMPConnection.Code.connectSuccess.rawValue:
rtmpStream!.publish(Preference.defaultInstance.streamName)
default:
break
}
}
}