annotate foosdk/sdk/foobar2000/SDK/playback_control.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #include "foobar2000-sdk-pch.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2 #include "playback_control.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include "titleformat.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 static double parseFraction(const char * fraction) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 unsigned v = 0, d = 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 while(pfc::char_is_numeric( *fraction) ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 d *= 10;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 v *= 10;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 v += (unsigned) ( *fraction - '0' );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 ++fraction;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 PFC_ASSERT( *fraction == 0 );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 return (double)v / (double)d;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 static double parse_time(const char * time) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 unsigned vTotal = 0, vCur = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 for(;;) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 char c = *time++;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 if (c == 0) return (double) (vTotal + vCur);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 else if (pfc::char_is_numeric( c ) ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 vCur = vCur * 10 + (unsigned)(c-'0');
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 } else if (c == ':') {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 if (vCur >= 60) {PFC_ASSERT(!"Invalid input"); return 0; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 vTotal += vCur; vCur = 0; vTotal *= 60;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 } else if (c == '.') {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 return (double) (vTotal + vCur) + parseFraction(time);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 PFC_ASSERT(!"Invalid input"); return 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 double playback_control::playback_get_length()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 double rv = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 metadb_handle_ptr ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 if (get_now_playing(ptr))
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 rv = ptr->get_length();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 return rv;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 double playback_control::playback_get_length_ex() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 double rv = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 metadb_handle_ptr ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 if (get_now_playing(ptr))
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 rv = ptr->get_length();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 if (rv <= 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 pfc::string8 temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 titleformat_object::ptr script;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 titleformat_compiler::get()->compile_force(script, "[%length_ex%]");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 this->playback_format_title(NULL, temp, script, NULL, display_level_titles);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 if (temp.length() > 0) rv = parse_time(temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 return rv;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 void playback_control::userPrev() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 userActionHook();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 if (this->is_playing() && this->playback_can_seek() && this->playback_get_position() > 5) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 this->playback_seek(0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 this->previous();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 void playback_control::userNext() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 userActionHook();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 this->start(track_command_next);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 void playback_control::userMute() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 userActionHook();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 this->volume_mute_toggle();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 void playback_control::userStop() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 userActionHook();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 this->stop();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 void playback_control::userPlay() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 userActionHook();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 this->play_or_pause();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 void playback_control::userPause() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 userActionHook();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 nonUserPause();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 void playback_control::nonUserPause() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 if (this->is_playing()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 this->pause(true);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 void playback_control::userStart() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 userActionHook();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 if (this->is_playing()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 this->pause(false);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 this->start();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 static const double seekDelta = 30;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 void playback_control::userFastForward() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 userActionHook();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 if (!this->playback_can_seek()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 this->userNext(); return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 this->playback_seek_delta(seekDelta);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 void playback_control::userRewind() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 userActionHook();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 if (!this->playback_can_seek()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 this->userPrev(); return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 double p = this->playback_get_position();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 if (p < 0) return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 if (p < seekDelta) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 if (p < seekDelta / 3) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 this->userPrev();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 this->playback_seek(0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 this->playback_seek_delta(-30);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 }