tucue 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CLAUDE.md +4 -0
- data/README.md +5 -1
- data/lib/tucue/player.rb +34 -0
- data/lib/tucue/ui.rb +13 -1
- data/lib/tucue/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b13df268982a614c075c660f19f057f249be6f0da5f542cd48755bf3f10ba79d
|
|
4
|
+
data.tar.gz: d44cddbf91c73703b81d359dfabbf23af5e05507af59e8a16fdc166d1acbdcea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: df62e31a13f104dc63717aecaefc7dd41ae64463db3730a283a7f67d528ae0c9e61edaa983274cdf55643c10eb3fbefe0b8fb09e57381363092f845e8be03b9b
|
|
7
|
+
data.tar.gz: ee69e7d79e3ecd3a19803e4044b248a34018f6985d33389f5db083626a084dffb1da4f366bf41c8f488a1a96b06402bb1b13b649901b7b75613a8f8943465bb1
|
data/CLAUDE.md
CHANGED
|
@@ -23,6 +23,7 @@ moments, and exporting them.
|
|
|
23
23
|
|
|
24
24
|
- [x] Play mp3 / wav files
|
|
25
25
|
- [x] Rewind / fast-forward in 5- and 15-second steps
|
|
26
|
+
- [x] Adjust playback speed in steps (0.5x – 2.0x)
|
|
26
27
|
- [x] Mark the current position (with an optional label)
|
|
27
28
|
- [x] Export the mark list to a file (CSV / JSON)
|
|
28
29
|
|
|
@@ -99,6 +100,9 @@ IPC notes (see `lib/tucue/player.rb`):
|
|
|
99
100
|
| `←` | -5 seconds |
|
|
100
101
|
| `]` | +15 seconds |
|
|
101
102
|
| `[` | -15 seconds |
|
|
103
|
+
| `+` / `=` | Speed up one step (max 2.0x) |
|
|
104
|
+
| `-` | Slow down one step (min 0.5x) |
|
|
105
|
+
| `0` | Reset speed to 1.0x |
|
|
102
106
|
| `m` | Mark the current position |
|
|
103
107
|
| `e` | Export the marks |
|
|
104
108
|
| `q` | Quit |
|
data/README.md
CHANGED
|
@@ -11,11 +11,12 @@ The name is a blend of **TUI** and **Cue** (pronounced "too-cue").
|
|
|
11
11
|
```
|
|
12
12
|
┌─────────────────────────────────┐
|
|
13
13
|
│ File: interview.mp3 │
|
|
14
|
-
│ 00:01:23 / 00:45:10 ####---- │
|
|
14
|
+
│ 00:01:23 / 00:45:10 ####---- 1.25x │
|
|
15
15
|
├─────────────────────────────────┤
|
|
16
16
|
│ [Space] play/pause │
|
|
17
17
|
│ [<-] -5s [->] +5s │
|
|
18
18
|
│ [[] -15s []] +15s │
|
|
19
|
+
│ [-] slower [+] faster [0] reset speed │
|
|
19
20
|
│ [m] mark [e] export │
|
|
20
21
|
│ [q] quit │
|
|
21
22
|
├─────────────────────────────────┤
|
|
@@ -81,6 +82,9 @@ bundle exec tucue --start 01:02:03 interview.mp3
|
|
|
81
82
|
| `←` | -5 seconds |
|
|
82
83
|
| `]` | +15 seconds |
|
|
83
84
|
| `[` | -15 seconds |
|
|
85
|
+
| `+` / `=` | Speed up one step (max 2x) |
|
|
86
|
+
| `-` | Slow down one step (min 0.5x) |
|
|
87
|
+
| `0` | Reset speed to 1x |
|
|
84
88
|
| `m` | Mark the current position (prompts for an optional label) |
|
|
85
89
|
| `e` | Export the marks |
|
|
86
90
|
| `q` | Quit |
|
data/lib/tucue/player.rb
CHANGED
|
@@ -16,6 +16,10 @@ module Tucue
|
|
|
16
16
|
# Max seconds to wait for the IPC socket to appear.
|
|
17
17
|
SOCKET_TIMEOUT = 5
|
|
18
18
|
|
|
19
|
+
# Selectable playback speeds, from half to double, centered on 1.0.
|
|
20
|
+
SPEED_STEPS = [0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0].freeze
|
|
21
|
+
DEFAULT_SPEED_INDEX = SPEED_STEPS.index(1.0)
|
|
22
|
+
|
|
19
23
|
def initialize(file, socket_path: "/tmp/tucue.sock", start_at: nil, extra_args: [])
|
|
20
24
|
@file = file
|
|
21
25
|
@socket_path = socket_path
|
|
@@ -25,6 +29,7 @@ module Tucue
|
|
|
25
29
|
@socket = nil
|
|
26
30
|
@request_id = 0
|
|
27
31
|
@mutex = Mutex.new
|
|
32
|
+
@speed_index = DEFAULT_SPEED_INDEX
|
|
28
33
|
end
|
|
29
34
|
|
|
30
35
|
attr_reader :file
|
|
@@ -71,6 +76,29 @@ module Tucue
|
|
|
71
76
|
command("seek", seconds, "relative")
|
|
72
77
|
end
|
|
73
78
|
|
|
79
|
+
# Current playback speed multiplier (e.g. 1.0, 1.25).
|
|
80
|
+
def speed
|
|
81
|
+
SPEED_STEPS[@speed_index]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Step the speed up one notch (capped at the fastest step).
|
|
85
|
+
def speed_up
|
|
86
|
+
@speed_index = [@speed_index + 1, SPEED_STEPS.size - 1].min
|
|
87
|
+
apply_speed
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Step the speed down one notch (capped at the slowest step).
|
|
91
|
+
def speed_down
|
|
92
|
+
@speed_index = [@speed_index - 1, 0].max
|
|
93
|
+
apply_speed
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Reset the speed back to 1.0.
|
|
97
|
+
def reset_speed
|
|
98
|
+
@speed_index = DEFAULT_SPEED_INDEX
|
|
99
|
+
apply_speed
|
|
100
|
+
end
|
|
101
|
+
|
|
74
102
|
# Current playback position in seconds, or nil if unavailable.
|
|
75
103
|
def time_pos
|
|
76
104
|
get_property("time-pos")
|
|
@@ -92,6 +120,12 @@ module Tucue
|
|
|
92
120
|
|
|
93
121
|
private
|
|
94
122
|
|
|
123
|
+
# Push the current speed to mpv and return it.
|
|
124
|
+
def apply_speed
|
|
125
|
+
set_property("speed", speed)
|
|
126
|
+
speed
|
|
127
|
+
end
|
|
128
|
+
|
|
95
129
|
def mpv_available?
|
|
96
130
|
ENV["PATH"].to_s.split(File::PATH_SEPARATOR).any? do |dir|
|
|
97
131
|
File.executable?(File.join(dir, "mpv"))
|
data/lib/tucue/ui.rb
CHANGED
|
@@ -72,6 +72,12 @@ module Tucue
|
|
|
72
72
|
@player.seek(SEEK_LARGE)
|
|
73
73
|
when "["
|
|
74
74
|
@player.seek(-SEEK_LARGE)
|
|
75
|
+
when "+", "="
|
|
76
|
+
@status = "Speed #{format_speed(@player.speed_up)}"
|
|
77
|
+
when "-"
|
|
78
|
+
@status = "Speed #{format_speed(@player.speed_down)}"
|
|
79
|
+
when "0"
|
|
80
|
+
@status = "Speed #{format_speed(@player.reset_speed)}"
|
|
75
81
|
when "m"
|
|
76
82
|
add_mark
|
|
77
83
|
when "e"
|
|
@@ -125,7 +131,7 @@ module Tucue
|
|
|
125
131
|
pos = @player.time_pos
|
|
126
132
|
dur = @player.duration
|
|
127
133
|
@window.setpos(row, 0)
|
|
128
|
-
@window.addstr(" #{format_time(pos)} / #{format_time(dur)} #{progress_bar(pos, dur)}")
|
|
134
|
+
@window.addstr(" #{format_time(pos)} / #{format_time(dur)} #{progress_bar(pos, dur)} #{format_speed(@player.speed)}")
|
|
129
135
|
|
|
130
136
|
row += 1
|
|
131
137
|
@window.setpos(row, 0)
|
|
@@ -135,6 +141,7 @@ module Tucue
|
|
|
135
141
|
"[Space] play/pause",
|
|
136
142
|
"[<-] -#{SEEK_SMALL}s [->] +#{SEEK_SMALL}s",
|
|
137
143
|
"[[] -#{SEEK_LARGE}s []] +#{SEEK_LARGE}s",
|
|
144
|
+
"[-] slower [+] faster [0] reset speed",
|
|
138
145
|
"[m] mark [e] export",
|
|
139
146
|
"[q] quit"
|
|
140
147
|
].each do |line|
|
|
@@ -172,6 +179,11 @@ module Tucue
|
|
|
172
179
|
("#" * filled) + ("-" * (PROGRESS_WIDTH - filled))
|
|
173
180
|
end
|
|
174
181
|
|
|
182
|
+
# Format a speed multiplier compactly, e.g. 0.5x, 1x, 1.25x.
|
|
183
|
+
def format_speed(value)
|
|
184
|
+
"#{format("%g", value)}x"
|
|
185
|
+
end
|
|
186
|
+
|
|
175
187
|
# Format seconds as HH:MM:SS.
|
|
176
188
|
def format_time(seconds)
|
|
177
189
|
return "--:--:--" if seconds.nil?
|
data/lib/tucue/version.rb
CHANGED