Skip to content

Commit

Permalink
[WIP] VideoController で SwiftUIVideoView (VideoView) を制御する
Browse files Browse the repository at this point in the history
  • Loading branch information
zztkm committed Oct 9, 2024
1 parent 1b2811c commit 7ff85ca
Showing 1 changed file with 24 additions and 52 deletions.
76 changes: 24 additions & 52 deletions Sora/SwiftUIVideoView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,15 @@ import UIKit
*/
@available(iOS 14, *)
public struct SwiftUIVideoView<Background>: View where Background: View {
private var stream: MediaStream?
private var background: Background

// TODO(zztkm): わかりやすいコメントを書く
// 親 View で定義された stopVideo 変数と接続するための変数
@Binding private var isStop: Bool
@Binding private var isClear: Bool

@ObservedObject private var controller: VideoController

private var background: Background
/**
ビューを初期化します。
- parameter stream: 描画される映像ストリーム。 nil の場合は何も描画されません
- parameter isStop: 映像の描画を制御するフラグ (default: false)
- parameter isClear: 映像をクリアして背景 View を表示するためのフラグ (default: false)
- parameter controller: VideoController
*/
public init(_ stream: MediaStream?, isStop: Binding<Bool>? = nil, isClear: Binding<Bool>? = nil) where Background == EmptyView {
self.init(stream, background: EmptyView(), isStop: isStop, isClear: isClear)
public init(_ controller: VideoController) where Background == EmptyView {
self.init(controller, background: EmptyView())
}

/**
Expand All @@ -36,22 +26,23 @@ public struct SwiftUIVideoView<Background>: View where Background: View {
- parameter isStop: 映像の描画を制御するフラグ (default: false)
- parameter isClear: 映像をクリアして背景 View を表示するためのフラグ (default: false)
*/
public init(_ stream: MediaStream?, background: Background, isStop: Binding<Bool>? = nil, isClear: Binding<Bool>? = nil) {
self.stream = stream
public init(_ controller: VideoController, background: Background) {
self.controller = controller
self.background = background
// 指定がない場合は固定値 false を与える
_isStop = isStop ?? .constant(false)
_isClear = isClear ?? .constant(false)
controller = VideoController(stream: stream)
}

/// :nodoc:
/// TODO(zztkm): SwiftUI での Background と UIKit での Background が同居しているが使い分けについて考える
/// 今の実装だと isClear で UIKit の方も clear してるけど、これは意味がなくて isClear すると SwiftUI の Backgroud View が表示されるようになる
/// なので、そもそも VideView の clear() method を呼ぶ意味がなくなってしまってる
/// この辺の制御はできるだけ SwiftUI 側に寄せたいので、clear() metthod を呼ばないようにするなど検討したい
public var body: some View {
ZStack {
// isClear が true のときは背景を表示し、false のときは Video を表示する
background
.opacity(controller.isCleared ? 1 : 0)
.opacity(isClear ? 1 : 0)
RepresentedVideoView(controller, isStop: $isStop, isClear: $isClear)
.opacity(controller.isCleared ? 0 : 1)
.opacity(isClear ? 0 : 1)
}
}

Expand Down Expand Up @@ -85,33 +76,7 @@ public struct SwiftUIVideoView<Background>: View where Background: View {

/// 映像のクリア時に表示する背景ビューを指定します。
public func videoBackground<Background>(_ background: Background) -> SwiftUIVideoView<Background> where Background: View {
var new = SwiftUIVideoView<Background>(stream, background: background)
new.controller = controller
return new
}

/**
映像の描画を停止します。
*/
private func videoStop(_ flag: Bool) -> SwiftUIVideoView<Background> {
if flag {
controller.videoView.stop()
} else if !controller.videoView.isRendering {
controller.videoView.start()
}
return self
}

/**
画面を背景ビューに切り替えます。
このメソッドは描画停止時のみ有効です。
*/
public func videoClear(_ flag: Bool) -> SwiftUIVideoView<Background> {
if flag {
controller.videoView.clear()
controller.isCleared = true
}
return self
SwiftUIVideoView<Background>(controller, background: background)
}

/// 映像のサイズの変更時に実行されるブロックを指定します。
Expand All @@ -134,7 +99,11 @@ private struct RepresentedVideoView: UIViewRepresentable {
typealias UIViewType = VideoView

@ObservedObject private var controller: VideoController

// 以下は SDK ユーザー側で制御される変数
/// 映像を停止するかを制御するフラグ
@Binding private var isStop: Bool
/// backgroundView を表示するか制御するフラグ
@Binding private var isClear: Bool

public init(_ controller: VideoController, isStop: Binding<Bool>, isClear: Binding<Bool>) {
Expand All @@ -158,6 +127,11 @@ private struct RepresentedVideoView: UIViewRepresentable {
controller.stream?.videoRenderer = uiView
}

// 現在 VideoView が表示している映像の元々のフレームサイズを返します。
public var currentVideoFrameSize: CGSize? {
controller.videoView.currentVideoFrameSize
}

/**
映像の描画を停止します。TODO(zztkm): method 名の検討 (stop start の toggle なので、stop はおかしいかも?
*/
Expand All @@ -182,15 +156,13 @@ private struct RepresentedVideoView: UIViewRepresentable {
}
}

class VideoController: ObservableObject {
public class VideoController: ObservableObject {
var stream: MediaStream?

// init() で VideoView を生成すると次のエラーが出るので、生成のタイミングを遅らせておく
// Failed to bind EAGLDrawable: <CAEAGLLayer: 0x********> to GL_RENDERBUFFER 1
lazy var videoView = VideoView()

@Published var isCleared: Bool = false

init(stream: MediaStream?) {
self.stream = stream
}
Expand Down

0 comments on commit 7ff85ca

Please sign in to comment.