Skip to content

Commit b73f295

Browse files
committed
added new commands loop and unloop
1 parent 4e1cda2 commit b73f295

File tree

4 files changed

+82
-48
lines changed

4 files changed

+82
-48
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ Please note that using videos from URLs requires ensuring that you have the righ
2626
| `init(settings: () -> VideoSettings, command:)` | Constructor | Initializes the player with a declarative settings block and playback command binding. |
2727

2828

29+
### Playback Commands
30+
2931
### Playback Commands
3032

3133
| Command | Description |
@@ -40,6 +42,8 @@ Please note that using videos from URLs requires ensuring that you have the righ
4042
| `volume(Float)` | Command to adjust the volume of the video playback. The `volume` parameter is a `Float` value between 0.0 (mute) and 1.0 (full volume). If a value outside this range is passed, it will be clamped to the nearest valid value (0.0 or 1.0). |
4143
| `subtitles(String?)` | Command to set subtitles to a specified language or turn them off. Pass a language code (e.g., "en" for English) to set subtitles, or `nil` to turn them off. |
4244
| `playbackSpeed(Float)` | Command to adjust the playback speed of the video. The `speed` parameter is a `Float` value representing the playback speed (e.g., 1.0 for normal speed, 0.5 for half speed, 2.0 for double speed). If a negative value is passed, it will be clamped to 0.0. |
45+
| `loop` | Command to enable looping of the video playback. By default, looping is enabled, so this command will have no effect if looping is already active. |
46+
| `unloop` | Command to disable looping of the video playback. This command will only take effect if the video is currently being looped. |
4347

4448

4549
### Initializer Parameters Settings

Sources/swiftui-loop-videoplayer/enum/PlaybackCommand.swift

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
//
2-
// PlaybackCommand.swift
3-
//
4-
//
5-
// Created by Igor Shelopaev on 06.08.24.
6-
//
7-
81
import AVFoundation
92

103
/// An enumeration of possible playback commands.
@@ -44,23 +37,26 @@ public enum PlaybackCommand: Equatable {
4437
/// Command to set the playback speed of the video playback.
4538
/// - Parameter speed: A `Float` value representing the playback speed (e.g., 1.0 for normal speed, 0.5 for half speed, 2.0 for double speed).
4639
case playbackSpeed(Float)
40+
41+
/// Command to enable looping of the video playback.
42+
case loop
43+
44+
/// Command to disable looping of the video playback.
45+
case unloop
4746

4847
public static func == (lhs: PlaybackCommand, rhs: PlaybackCommand) -> Bool {
4948
switch (lhs, rhs) {
50-
case (.play, .play):
51-
return true
52-
case (.pause, .pause):
49+
case (.play, .play),
50+
(.pause, .pause),
51+
(.begin, .begin),
52+
(.end, .end),
53+
(.mute, .mute),
54+
(.unmute, .unmute),
55+
(.loop, .loop),
56+
(.unloop, .unloop):
5357
return true
5458
case (.seek(let lhsTime), .seek(let rhsTime)):
5559
return lhsTime == rhsTime
56-
case (.begin, .begin):
57-
return true
58-
case (.end, .end):
59-
return true
60-
case (.mute, .mute):
61-
return true
62-
case (.unmute, .unmute):
63-
return true
6460
case (.volume(let lhsVolume), .volume(let rhsVolume)):
6561
return lhsVolume == rhsVolume
6662
case (.subtitles(let lhsLanguage), .subtitles(let rhsLanguage)):

Sources/swiftui-loop-videoplayer/protocol/view/AbstractPlayer.swift

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import Foundation
1010

1111
@available(iOS 14, macOS 11, tvOS 14, *)
1212
public protocol AbstractPlayer: AnyObject{
13+
14+
/// The looper responsible for continuous video playback.
15+
var playerLooper: AVPlayerLooper? { get set }
16+
1317
/// The queue player that plays the video items.
1418
var player: AVQueuePlayer? { get set }
1519

@@ -155,6 +159,34 @@ extension AbstractPlayer{
155159
}
156160
}
157161

162+
/// Enables looping for the current video item.
163+
/// This method sets up the `playerLooper` to loop the currently playing item indefinitely.
164+
func loop() {
165+
guard let player = player, let currentItem = player.currentItem else {
166+
return
167+
}
168+
169+
// Check if the video is already being looped
170+
if playerLooper != nil {
171+
return // Already looped, no need to loop again
172+
}
173+
174+
// Initialize the player looper with the current item
175+
playerLooper = AVPlayerLooper(player: player, templateItem: currentItem)
176+
}
177+
178+
/// Disables looping for the current video item.
179+
/// This method removes the `playerLooper`, stopping the loop.
180+
func unloop() {
181+
// Check if the video is not looped (i.e., playerLooper is nil)
182+
guard playerLooper != nil else {
183+
return // Not looped, no need to unloop
184+
}
185+
186+
playerLooper?.disableLooping()
187+
playerLooper = nil
188+
}
189+
158190
/// Sets the playback command for the video player.
159191
/// - Parameter value: The `PlaybackCommand` to set. This can be one of the following:
160192
/// - `play`: Command to play the video.
@@ -167,28 +199,34 @@ extension AbstractPlayer{
167199
/// - `volume`: Command to adjust the volume of the video playback.
168200
/// - `subtitles`: Command to set subtitles to a specified language or turn them off.
169201
/// - `playbackSpeed`: Command to adjust the playback speed of the video.
170-
func setCommand(_ value: PlaybackCommand) {
171-
switch value {
172-
case .play:
173-
play()
174-
case .pause:
175-
pause()
176-
case .seek(to: let time):
177-
seek(to: time)
178-
case .begin:
179-
seekToStart()
180-
case .end:
181-
seekToEnd()
182-
case .mute:
183-
mute()
184-
case .unmute:
185-
unmute()
186-
case .volume(let volume):
187-
setVolume(volume)
188-
case .subtitles(let language):
189-
setSubtitles(to: language)
190-
case .playbackSpeed(let speed):
191-
setPlaybackSpeed(speed)
192-
}
193-
}
202+
/// - `loop`: Command to enable looping of the video playback.
203+
/// - `unloop`: Command to disable looping of the video playback.
204+
func setCommand(_ value: PlaybackCommand) {
205+
switch value {
206+
case .play:
207+
play()
208+
case .pause:
209+
pause()
210+
case .seek(to: let time):
211+
seek(to: time)
212+
case .begin:
213+
seekToStart()
214+
case .end:
215+
seekToEnd()
216+
case .mute:
217+
mute()
218+
case .unmute:
219+
unmute()
220+
case .volume(let volume):
221+
setVolume(volume)
222+
case .subtitles(let language):
223+
setSubtitles(to: language)
224+
case .playbackSpeed(let speed):
225+
setPlaybackSpeed(speed)
226+
case .loop:
227+
loop()
228+
case .unloop:
229+
unloop()
230+
}
231+
}
194232
}

Sources/swiftui-loop-videoplayer/protocol/view/LoopingPlayerProtocol.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ public protocol LoopingPlayerProtocol: AbstractPlayer{
2828
var layer : CALayer? { get set }
2929
var wantsLayer : Bool { get set }
3030
#endif
31-
32-
/// The looper responsible for continuous video playback.
33-
var playerLooper: AVPlayerLooper? { get set }
3431

3532
/// The delegate to be notified about errors encountered by the player.
3633
var delegate: PlayerErrorDelegate? { get set }
@@ -101,6 +98,7 @@ extension LoopingPlayerProtocol {
10198

10299
// Replace the current item with a new item created from the asset
103100
let newItem = AVPlayerItem(asset: asset)
101+
unloop()
104102
player?.replaceCurrentItem(with: newItem)
105103

106104
// Seek to the beginning of the item if you want to start from the start
@@ -157,9 +155,7 @@ extension LoopingPlayerProtocol {
157155
wantsLayer = true
158156
#endif
159157

160-
if let firstItem = player.items().first {
161-
playerLooper = AVPlayerLooper(player: player, templateItem: firstItem)
162-
}
158+
loop()
163159
player.play()
164160
}
165161

0 commit comments

Comments
 (0)