Skip to content

Commit baffcff

Browse files
Add color customization to Vinyl Record Player desklet
- Add settings-schema.json with fontColor, playerColor, recordColor, labelColor - Update desklet.js to apply colors via CSS variables - Update stylesheet.css to use CSS custom properties for theming - Update info.json description
1 parent e36a4f2 commit baffcff

4 files changed

Lines changed: 135 additions & 90 deletions

File tree

vinyl-player@AttilaHuns288452/files/vinyl-player@AttilaHuns288452/desklet.js

Lines changed: 95 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -4,110 +4,143 @@ const Cinnamon = imports.gi.Cinnamon;
44
const St = imports.gi.St;
55
const Clutter = imports.gi.Clutter;
66
const Main = imports.ui.main;
7+
const PopupMenu = imports.ui.popupMenu;
78

89
const RecordPlayer = class {
910
constructor(metadata, desklet) {
1011
this._metadata = metadata;
1112
this._desklet = desklet;
1213
this._settings = new Cinnamon.AppletSettings(metadata.uuid, metadata.uuid);
1314

14-
// Settings: playing (bool), speed (33 or 45)
15+
// Bind color + control settings
16+
this._settings.bindProperty('', 'fontColor', 'fontColor',
17+
() => this._applyColors(), true, false);
18+
this._settings.bindProperty('', 'playerColor', 'playerColor',
19+
() => this._applyColors(), true, false);
20+
this._settings.bindProperty('', 'recordColor', 'recordColor',
21+
() => this._applyColors(), true, false);
22+
this._settings.bindProperty('', 'labelColor', 'labelColor',
23+
() => this._applyColors(), true, false);
1524
this._settings.bindProperty('', 'playing', 'playing',
1625
() => this._onSettingsChanged(), true, false);
1726
this._settings.bindProperty('', 'speed', 'speed',
1827
() => this._onSettingsChanged(), true, 33);
28+
29+
this._settings.setDefault('fontColor', '#b4afa5');
30+
this._settings.setDefault('playerColor', '#5a4a3a');
31+
this._settings.setDefault('recordColor', '#111111');
32+
this._settings.setDefault('labelColor', '#c4b089');
1933
this._settings.setDefault('playing', true);
2034
this._settings.setDefault('speed', 33);
2135

22-
this._elapsed = 0;
23-
this._startTime = 0;
2436
this._angle = 0;
37+
this._startTime = 0;
2538
this._rate = 0;
2639

2740
this._initLayout();
41+
this._applyColors();
2842
this._onSettingsChanged();
2943
}
3044

3145
_initLayout() {
32-
this._layout = new St.Bin({
33-
style_class: 'vinyl-desklet-bin',
34-
reactive: true,
46+
// Container bin — acts as our positioning canvas
47+
this._canvas = new St.Bin({
48+
style_class: 'vinyl-canvas',
49+
width: 200,
50+
height: 200,
3551
});
3652

37-
this._desklet.layout = new St.BoxLayout({ style_class: 'vinyl-desklet-panel' });
38-
39-
// Turntable platter (outer ring)
40-
this._platter = new St.Bin({
41-
style_class: 'vinyl-platter',
42-
x_expand: true,
43-
y_expand: true,
44-
});
53+
// Platter (circular via CSS border-radius)
54+
this._platter = new St.Bin({ style_class: 'vinyl-platter' });
55+
this._platter.set_position(18, 18);
56+
this._platter.set_size(164, 164);
57+
this._canvas.add_child(this._platter);
4558

4659
// Record
47-
this._record = new St.Bin({
48-
style_class: 'vinyl-record',
49-
});
60+
this._record = new St.Bin({ style_class: 'vinyl-record' });
61+
this._record.set_position(28, 28);
62+
this._record.set_size(144, 144);
63+
this._canvas.add_child(this._record);
5064

51-
// Label
52-
this._label = new St.Bin({
53-
style_class: 'vinyl-label',
54-
});
65+
// Center label
66+
this._label = new St.Bin({ style_class: 'vinyl-label' });
67+
this._label.set_position(70, 70);
68+
this._label.set_size(60, 60);
69+
this._canvas.add_child(this._label);
5570

5671
// Spindle
57-
this._spindle = new St.Bin({
58-
style_class: 'vinyl-spindle',
59-
});
72+
this._spindle = new St.Bin({ style_class: 'vinyl-spindle' });
73+
this._spindle.set_position(95, 95);
74+
this._spindle.set_size(10, 10);
75+
this._canvas.add_child(this._spindle);
6076

61-
// Tonearm group
62-
this._armGroup = new St.Group();
77+
// Tonearm
6378
this._armBase = new St.Bin({ style_class: 'arm-base' });
64-
this._armBody = new St.Bin({ style_class: 'arm-body' });
79+
this._armBase.set_position(150, 22);
80+
this._armBase.set_size(12, 12);
81+
this._canvas.add_child(this._armBase);
6582

66-
this._armGroup.add_child(this._armBase);
67-
this._armGroup.add_child(this._armBody);
68-
69-
// Popup menu for controls
83+
this._armBody = new St.Bin({ style_class: 'arm-body' });
84+
this._armBody.set_position(156, 28);
85+
this._armBody.set_size(80, 4);
86+
this._canvas.add_child(this._armBody);
87+
// Rotate arm ~35deg from vertical
88+
this._armBody.rotation_angle_z = 35;
89+
this._armBody.set_pivot_point(0, 0.5);
90+
91+
// Title text (bottom)
92+
this._title = new St.Label({ style_class: 'vinyl-title', text: 'Vinyl Player' });
93+
this._title.set_position(50, 182);
94+
this._canvas.add_child(this._title);
95+
96+
// Click to toggle play
97+
this._canvas.reactive = true;
98+
this._canvas.connect('button-press-event', () => this._togglePlay());
99+
100+
// Popup menu
70101
this._menuManager = new Desklet.DeskletManager(this);
71-
this._popupManager = new Cinnamon.PopupMenu.PopupMenuManager(this._layout);
72-
this._popupMenu = new Cinnamon.PopupMenu.PopupMenu(this._layout, 0);
102+
this._popupManager = new PopupMenu.PopupMenuManager(this);
103+
this._popupMenu = new PopupMenu.PopupMenu(this._canvas, 0);
73104

74105
const playItem = new PopupMenu.PopupMenuItem('Play / Pause');
75106
playItem.connect('activated', () => this._togglePlay());
76107
this._popupMenu.addMenuItem(playItem);
77108

78-
const separator = new PopupMenu.PopupSeparatorMenuItem();
79-
this._popupMenu.addMenuItem(separator);
80-
81-
const speed33 = new PopupMenu.PopupMenuItem('33 RPM');
82-
speed33.connect('activated', () => this._setSpeed(33));
83-
this._popupMenu.addMenuItem(speed33);
109+
const sep = new PopupMenu.PopupSeparatorMenuItem();
110+
this._popupMenu.addMenuItem(sep);
84111

85-
const speed45 = new PopupMenu.PopupMenuItem('45 RPM');
86-
speed45.connect('activated', () => this._setSpeed(45));
87-
this._popupMenu.addMenuItem(speed45);
112+
const s33 = new PopupMenu.PopupMenuItem('33 RPM');
113+
s33.connect('activated', () => this._setSpeed(33));
114+
this._popupMenu.addMenuItem(s33);
88115

89-
this._popupManager.setMenu(this._popupMenu);
116+
const s45 = new PopupMenu.PopupMenuItem('45 RPM');
117+
s45.connect('activated', () => this._setSpeed(45));
118+
this._popupMenu.addMenuItem(s45);
90119

91-
// Layout: record on top of platter
92-
this._desklet.layout.add_child(this._platter);
93-
this._desklet.layout.add_child(this._record);
94-
this._desklet.layout.add_child(this._label);
95-
this._desklet.layout.add_child(this._spindle);
96-
this._desklet.layout.add_child(this._armGroup);
120+
this._popupManager.addMenu(this._popupMenu);
97121

98-
// Header
99-
this._desklet.header.add_child(this._desklet.layout);
122+
this._desklet.header.add_child(this._canvas);
123+
}
100124

101-
// Click to toggle
102-
this._desklet.header.actor.connect('button-press-event', (actor, event) => {
103-
this._togglePlay();
104-
return Clutter.EVENT_STOP;
105-
});
125+
_applyColors() {
126+
if (!this._canvas) return;
127+
const fc = this._settings.get_property('fontColor');
128+
const pc = this._settings.get_property('playerColor');
129+
const rc = this._settings.get_property('recordColor');
130+
const lc = this._settings.get_property('labelColor');
131+
// Inject CSS custom properties
132+
const css = `color: ${fc};
133+
--vinyl-platter-base: ${pc};
134+
--vinyl-record: ${rc};
135+
--vinyl-label: ${lc};`;
136+
this._canvas.set_style(css);
137+
// Also directly set title color
138+
if (this._title)
139+
this._title.set_style(`color: ${fc};`);
106140
}
107141

108142
_togglePlay() {
109-
const playing = this._settings.get_property('playing');
110-
this._settings.setProperty('playing', !playing);
143+
this._settings.setProperty('playing', !this._settings.get_property('playing'));
111144
}
112145

113146
_setSpeed(rpm) {
@@ -125,23 +158,13 @@ const RecordPlayer = class {
125158
onUpdate() {
126159
if (!this._rate) return;
127160

128-
const playing = this._settings.get_property('playing');
129161
const speed = this._settings.get_property('speed');
130-
const msPerRev = (speed === 45) ? 60000 / 45 : 60000 / 33;
131-
162+
const msPerRev = speed === 45 ? 60000 / 45 : 60000 / 33;
132163
const elapsed = Date.now() - this._startTime;
133-
const revs = elapsed / msPerRev;
134-
this._angle = (revs * 360) % 360;
135-
136-
// Apply rotation via CSS transform using clutter transform
137-
const transform = new Clutter.Transform();
138-
transform.rotate(Z_AXIS, this._angle * Math.PI / 180);
139-
this._record.set_transform(transform);
140-
this._label.set_transform(transform.clone());
141-
}
164+
this._angle = ((elapsed / msPerRev) * 360) % 360;
142165

143-
onLookupStyle() {
144-
this._desklet.set_style('vinyl-desklet');
166+
this._record.rotation_angle_z = this._angle;
167+
this._label.rotation_angle_z = this._angle;
145168
}
146169
};
147170

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"uuid": { "type": "entry", "default": "vinyl-player@AttilaHuns288452", "description": "Desklet UUID" },
3+
"fontColor": { "type": "colorchooser", "default": "#b4afa5", "description": "Font color for the title text" },
4+
"playerColor": { "type": "colorchooser", "default": "#5a4a3a", "description": "Base color for the turntable platter" },
5+
"recordColor": { "type": "colorchooser", "default": "#111111", "description": "Color for the vinyl record" },
6+
"labelColor": { "type": "colorchooser", "default": "#c4b089", "description": "Color for the record center label" }
7+
}
Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,63 @@
1-
/* Vinyl Record Player Desklet */
2-
.vinyl-desklet {
1+
/* Vinyl Record Player Desklet — uses CSS variables set from settings */
2+
.vinyl-canvas {
33
width: 200px;
44
height: 200px;
5-
}
6-
7-
.vinyl-bg {
8-
background-color: rgba(25, 22, 20, 0.85);
9-
border-radius: 12px;
10-
border: 1px solid rgba(80, 75, 70, 0.5);
5+
background: rgba(20, 18, 16, 0.85);
6+
border-radius: 14px;
7+
border: 1px solid rgba(60, 55, 50, 0.5);
118
}
129

1310
.vinyl-platter {
14-
background: linear-gradient(135deg, #5a4a3a 0%, #8b7355 50%, #5a4a3a 100%);
15-
border: 2px solid #3d3228;
16-
box-shadow: 0 0 8px rgba(0, 0, 0, 0.4), inset 0 0 12px rgba(0, 0, 0, 0.3);
11+
background: linear-gradient(135deg,
12+
var(--vinyl-platter-base, #5a4a3a) 0%,
13+
color-mix(in srgb, var(--vinyl-platter-base, #5a4a3a) 80%, white) 50%,
14+
var(--vinyl-platter-base, #5a4a3a) 100%);
15+
border: 2px solid color-mix(in srgb, var(--vinyl-platter-base, #5a4a3a) 60%, black);
16+
border-radius: 50%;
17+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5), inset 0 0 14px rgba(0, 0, 0, 0.3);
1718
}
1819

1920
.vinyl-record {
2021
background: radial-gradient(ellipse at center,
21-
#1a1a1a 0%, #111 30%, #0a0a0a 70%, #1a1a1a 100%);
22-
border: 1px solid #2a2a2a;
22+
var(--vinyl-record, #111) 0%,
23+
color-mix(in srgb, var(--vinyl-record, #111) 70%, black) 60%,
24+
var(--vinyl-record, #111) 100%);
25+
border: 1px solid color-mix(in srgb, var(--vinyl-record, #111) 70%, white);
26+
border-radius: 50%;
2327
box-shadow: 0 0 6px rgba(0, 0, 0, 0.5);
2428
}
2529

2630
.vinyl-label {
2731
background: radial-gradient(ellipse at center,
28-
#d4c5a9 0%, #c4b089 40%, #b8a07a 100%);
29-
border: 1px solid #9a8560;
32+
var(--vinyl-label, #c4b089) 0%,
33+
color-mix(in srgb, var(--vinyl-label, #c4b089) 70%, black) 100%);
34+
border: 1px solid color-mix(in srgb, var(--vinyl-label, #c4b089) 60%, black);
35+
border-radius: 50%;
3036
box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.2);
3137
}
3238

3339
.vinyl-spindle {
34-
background: #888;
40+
background: #999;
3541
border: 1px solid #666;
42+
border-radius: 50%;
3643
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
3744
}
3845

3946
.arm-base {
4047
background: #c0c0c0;
4148
border: 1px solid #888;
49+
border-radius: 50%;
4250
box-shadow: 0 0 2px rgba(0, 0, 0, 0.4);
4351
}
4452

4553
.arm-body {
4654
background: linear-gradient(90deg, #b0b0b0, #d0d0d0, #b0b0b0);
4755
border: 1px solid #888;
56+
border-radius: 2px;
57+
}
58+
59+
.vinyl-title {
60+
font-size: 11px;
61+
font-weight: bold;
62+
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
4863
}

vinyl-player@AttilaHuns288452/info.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"uuid": "vinyl-player@AttilaHuns288452",
33
"name": "Vinyl Record Player",
4-
"description": "A vinyl record player desklet that spins a record on your desktop. Play, pause, and adjust speed.",
4+
"description": "A vinyl record player desklet that spins a record on your desktop. Play, pause, adjust speed, and customize font + player colors.",
55
"version": "1.0.0",
66
"author": "AttilaHuns288452",
77
"license": "GPL-2.0",
@@ -12,4 +12,4 @@
1212
],
1313
"platform": "Linux",
1414
" Cinnamon": ">=5.0"
15-
}
15+
}

0 commit comments

Comments
 (0)