1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Playback control methods for TimelinePlayer
impl TimelinePlayer {
/// Start auto-advance playback
///
/// Sets `is_playing` to true. The UI layer is responsible for implementing
/// timer-based frame advancement at the current playback speed.
///
/// # Example
///
/// ```rust,no_run
/// # use pmat::services::dap::{Recording, TimelinePlayer};
/// # let recording = Recording::new("test".to_string(), vec![]);
/// let mut player = TimelinePlayer::new(recording);
///
/// assert!(!player.is_playing());
/// player.play();
/// assert!(player.is_playing());
/// ```
pub fn play(&mut self) {
self.is_playing = true;
}
/// Stop auto-advance playback
///
/// Sets `is_playing` to false, pausing frame advancement.
///
/// # Example
///
/// ```rust,no_run
/// # use pmat::services::dap::{Recording, TimelinePlayer};
/// # let recording = Recording::new("test".to_string(), vec![]);
/// let mut player = TimelinePlayer::new(recording);
///
/// player.play();
/// assert!(player.is_playing());
///
/// player.pause();
/// assert!(!player.is_playing());
/// ```
pub fn pause(&mut self) {
self.is_playing = false;
}
/// Check if playback is currently active
///
/// Returns true if play() has been called without a subsequent pause().
///
/// # Example
///
/// ```rust,no_run
/// # use pmat::services::dap::{Recording, TimelinePlayer};
/// # let recording = Recording::new("test".to_string(), vec![]);
/// let mut player = TimelinePlayer::new(recording);
///
/// assert!(!player.is_playing());
/// player.play();
/// assert!(player.is_playing());
/// ```
pub fn is_playing(&self) -> bool {
self.is_playing
}
/// Set the playback speed multiplier
///
/// The speed affects how fast frames advance during auto-play mode:
/// - 0.5 = half speed (2x slower)
/// - 1.0 = normal speed
/// - 2.0 = double speed (2x faster)
///
/// The UI layer implements the timing logic using this value.
///
/// # Example
///
/// ```rust,no_run
/// # use pmat::services::dap::{Recording, TimelinePlayer};
/// # let recording = Recording::new("test".to_string(), vec![]);
/// let mut player = TimelinePlayer::new(recording);
///
/// assert_eq!(player.playback_speed(), 1.0);
///
/// player.set_speed(2.0);
/// assert_eq!(player.playback_speed(), 2.0);
///
/// player.set_speed(0.5);
/// assert_eq!(player.playback_speed(), 0.5);
/// ```
pub fn set_speed(&mut self, speed: f64) {
self.playback_speed = speed;
}
/// Get the current playback speed
///
/// Returns the playback speed multiplier (default: 1.0).
///
/// # Example
///
/// ```rust,no_run
/// # use pmat::services::dap::{Recording, TimelinePlayer};
/// # let recording = Recording::new("test".to_string(), vec![]);
/// let mut player = TimelinePlayer::new(recording);
///
/// assert_eq!(player.playback_speed(), 1.0);
/// player.set_speed(2.0);
/// assert_eq!(player.playback_speed(), 2.0);
/// ```
pub fn playback_speed(&self) -> f64 {
self.playback_speed
}
/// Get a reference to the underlying recording
///
/// Provides access to recording metadata and all snapshots.
///
/// # Example
///
/// ```rust,no_run
/// # use pmat::services::dap::{Recording, TimelinePlayer};
/// # let recording = Recording::new("test_program".to_string(), vec![]);
/// let player = TimelinePlayer::new(recording);
///
/// let metadata = player.recording().metadata();
/// println!("Program: {}", metadata.program);
/// ```
pub fn recording(&self) -> &Recording {
&self.recording
}
}