Skip to content

Commit 392fed7

Browse files
committed
feat: option to link speed with pitch
ref: #755
1 parent 2f80c67 commit 392fed7

File tree

3 files changed

+120
-51
lines changed

3 files changed

+120
-51
lines changed

lib/controller/settings.player.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class _PlayerSettings with SettingsFileWriter {
1010
final volume = 1.0.obs;
1111
final speed = 1.0.obs;
1212
final pitch = 1.0.obs;
13+
final linkSpeedPitch = false.obs;
1314

1415
var speeds = <double>[0.25, 0.5, 0.75, 0.9, 1.0, 1.1, 1.25, 1.5, 1.75, 2.0];
1516

@@ -53,6 +54,7 @@ class _PlayerSettings with SettingsFileWriter {
5354
double? volume,
5455
double? speed,
5556
double? pitch,
57+
bool? linkSpeedPitch,
5658
List<double>? speeds,
5759
int? seekDurationInSeconds,
5860
int? seekDurationInPercentage,
@@ -86,6 +88,7 @@ class _PlayerSettings with SettingsFileWriter {
8688
if (volume != null) this.volume.value = volume;
8789
if (speed != null) this.speed.value = speed;
8890
if (pitch != null) this.pitch.value = pitch;
91+
if (linkSpeedPitch != null) this.linkSpeedPitch.value = linkSpeedPitch;
8992
if (speeds != null) this.speeds = speeds;
9093
if (seekDurationInSeconds != null) this.seekDurationInSeconds.value = seekDurationInSeconds;
9194
if (seekDurationInPercentage != null) this.seekDurationInPercentage.value = seekDurationInPercentage;
@@ -139,6 +142,7 @@ class _PlayerSettings with SettingsFileWriter {
139142
volume.value = json['volume'] ?? volume.value;
140143
speed.value = json['speed'] ?? speed.value;
141144
pitch.value = json['pitch'] ?? pitch.value;
145+
linkSpeedPitch.value = json['linkSpeedPitch'] ?? linkSpeedPitch.value;
142146
speeds = (json['speeds'] as List?)?.cast<double>() ?? speeds;
143147
seekDurationInSeconds.value = json['seekDurationInSeconds'] ?? seekDurationInSeconds.value;
144148
seekDurationInPercentage.value = json['seekDurationInPercentage'] ?? seekDurationInPercentage.value;
@@ -193,6 +197,7 @@ class _PlayerSettings with SettingsFileWriter {
193197
'volume': volume.value,
194198
'speed': speed.value,
195199
'pitch': pitch.value,
200+
'linkSpeedPitch': linkSpeedPitch.value,
196201
'speeds': speeds,
197202
'seekDurationInSeconds': seekDurationInSeconds.value,
198203
'seekDurationInPercentage': seekDurationInPercentage.value,

lib/ui/pages/equalizer_page.dart

Lines changed: 114 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -43,83 +43,142 @@ class EqualizerMainSlidersColumn extends StatelessWidget {
4343

4444
return Column(
4545
children: [
46+
verticalPadding,
47+
ObxO(
48+
rx: settings.player.linkSpeedPitch,
49+
builder: (context, enabled) => AnimatedEnabled(
50+
enabled: !enabled,
51+
child: Obx(
52+
(context) {
53+
final pitch = settings.player.pitch.valueR;
54+
const hz432Value = 432.0 / 440.0;
55+
final is432HzEnabled = pitch == hz432Value;
56+
return _SliderTextWidget(
57+
icon: Broken.airpods,
58+
title: lang.PITCH,
59+
value: pitch,
60+
restoreDefault: () {
61+
Player.inst.setPlayerPitch(1.0);
62+
settings.player.save(pitch: 1.0);
63+
pitchKey.currentState?._updateVal(1.0);
64+
},
65+
onManualChange: (value) {
66+
pitchKey.currentState?._updateValNoRound(value);
67+
},
68+
featuredButton: NamidaInkWellButton(
69+
icon: null,
70+
text: '',
71+
borderRadius: 8.0,
72+
sizeMultiplier: 0.9,
73+
paddingMultiplier: 0.7,
74+
bgColor: theme.colorScheme.secondaryContainer.withValues(alpha: is432HzEnabled ? 0.5 : 0.2),
75+
onTap: () {
76+
final newValue = is432HzEnabled ? 1.0 : hz432Value;
77+
Player.inst.setPlayerPitch(newValue);
78+
settings.player.save(pitch: newValue);
79+
pitchKey.currentState?._updateValNoRound(newValue);
80+
},
81+
leading: Row(
82+
mainAxisSize: MainAxisSize.min,
83+
children: [
84+
Text(
85+
'✓ ',
86+
style: textTheme.displaySmall,
87+
).animateEntrance(
88+
showWhen: is432HzEnabled,
89+
allCurves: Curves.fastLinearToSlowEaseIn,
90+
durationMS: 300,
91+
),
92+
Text(
93+
'432Hz',
94+
style: textTheme.displaySmall,
95+
),
96+
],
97+
),
98+
),
99+
);
100+
},
101+
),
102+
),
103+
),
104+
ObxO(
105+
rx: settings.player.linkSpeedPitch,
106+
builder: (context, enabled) => AnimatedEnabled(
107+
enabled: !enabled,
108+
child: _CuteSlider(
109+
key: pitchKey,
110+
valueListenable: settings.player.pitch,
111+
onChanged: (value) {
112+
Player.inst.setPlayerPitch(value);
113+
settings.player.save(pitch: value);
114+
},
115+
tapToUpdate: tapToUpdate,
116+
),
117+
),
118+
),
46119
verticalPadding,
47120
Obx(
48-
(context) {
49-
final pitch = settings.player.pitch.valueR;
50-
const hz432Value = 432.0 / 440.0;
51-
final is432HzEnabled = pitch == hz432Value;
52-
return _SliderTextWidget(
53-
icon: Broken.airpods,
54-
title: lang.PITCH,
55-
value: pitch,
56-
restoreDefault: () {
121+
(context) => _SliderTextWidget(
122+
icon: Broken.forward,
123+
title: lang.SPEED,
124+
value: settings.player.speed.valueR,
125+
onManualChange: (value) {
126+
speedKey.currentState?._updateValNoRound(value);
127+
if (settings.player.linkSpeedPitch.value) {
128+
pitchKey.currentState?._updateValNoRound(value);
129+
}
130+
},
131+
restoreDefault: () {
132+
Player.inst.setPlayerSpeed(1.0);
133+
settings.player.save(speed: 1.0);
134+
speedKey.currentState?._updateVal(1.0);
135+
136+
if (settings.player.linkSpeedPitch.value) {
57137
Player.inst.setPlayerPitch(1.0);
58138
settings.player.save(pitch: 1.0);
59139
pitchKey.currentState?._updateVal(1.0);
60-
},
61-
onManualChange: (value) {
62-
pitchKey.currentState?._updateValNoRound(value);
63-
},
64-
featuredButton: NamidaInkWellButton(
140+
}
141+
},
142+
useMaxToLimitPreciseValue: false,
143+
valToText: _SliderTextWidget.toXMultiplier,
144+
featuredButton: ObxO(
145+
rx: settings.player.linkSpeedPitch,
146+
builder: (context, enabled) => NamidaInkWellButton(
65147
icon: null,
66148
text: '',
67149
borderRadius: 8.0,
68150
sizeMultiplier: 0.9,
69151
paddingMultiplier: 0.7,
70-
bgColor: theme.colorScheme.secondaryContainer.withValues(alpha: is432HzEnabled ? 0.5 : 0.2),
152+
bgColor: theme.colorScheme.secondaryContainer.withValues(alpha: enabled ? 0.5 : 0.2),
71153
onTap: () {
72-
final newValue = is432HzEnabled ? 1.0 : hz432Value;
154+
final newLinkValue = !settings.player.linkSpeedPitch.value;
155+
final newValue = newLinkValue ? settings.player.speed.value : settings.player.pitch.value;
73156
Player.inst.setPlayerPitch(newValue);
74-
settings.player.save(pitch: newValue);
157+
settings.player.save(pitch: newValue, linkSpeedPitch: newLinkValue);
75158
pitchKey.currentState?._updateValNoRound(newValue);
76159
},
77160
leading: Row(
78161
mainAxisSize: MainAxisSize.min,
79162
children: [
80-
Text(
81-
'✓ ',
82-
style: textTheme.displaySmall,
163+
Padding(
164+
padding: const EdgeInsets.only(right: 4.0),
165+
child: Icon(
166+
Broken.link_21,
167+
size: 12.0,
168+
),
83169
).animateEntrance(
84-
showWhen: is432HzEnabled,
170+
showWhen: enabled,
85171
allCurves: Curves.fastLinearToSlowEaseIn,
86172
durationMS: 300,
87173
),
88174
Text(
89-
'432Hz',
175+
lang.PITCH,
90176
style: textTheme.displaySmall,
91177
),
92178
],
93179
),
94180
),
95-
);
96-
},
97-
),
98-
_CuteSlider(
99-
key: pitchKey,
100-
valueListenable: settings.player.pitch,
101-
onChanged: (value) {
102-
Player.inst.setPlayerPitch(value);
103-
settings.player.save(pitch: value);
104-
},
105-
tapToUpdate: tapToUpdate,
106-
),
107-
verticalPadding,
108-
Obx(
109-
(context) => _SliderTextWidget(
110-
icon: Broken.forward,
111-
title: lang.SPEED,
112-
value: settings.player.speed.valueR,
113-
onManualChange: (value) {
114-
speedKey.currentState?._updateValNoRound(value);
115-
},
116-
restoreDefault: () {
117-
Player.inst.setPlayerSpeed(1.0);
118-
settings.player.save(speed: 1.0);
119-
speedKey.currentState?._updateVal(1.0);
120-
},
121-
useMaxToLimitPreciseValue: false,
122-
valToText: _SliderTextWidget.toXMultiplier,
181+
),
123182
),
124183
),
125184
_CuteSlider(
@@ -128,6 +187,11 @@ class EqualizerMainSlidersColumn extends StatelessWidget {
128187
onChanged: (value) {
129188
Player.inst.setPlayerSpeed(value);
130189
settings.player.save(speed: value);
190+
191+
if (settings.player.linkSpeedPitch.value) {
192+
Player.inst.setPlayerPitch(value);
193+
settings.player.save(pitch: value);
194+
}
131195
},
132196
tapToUpdate: tapToUpdate,
133197
),

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: namida
22
description: A Beautiful and Feature-rich Music Player, With YouTube & Video Support Built in Flutter
33
publish_to: "none"
4-
version: 5.4.8-beta+251125207
4+
version: 5.4.81-beta+251125208
55

66
environment:
77
sdk: ">=3.6.0 <4.0.0"

0 commit comments

Comments
 (0)