11import GObject from 'gi://GObject' ;
22import St from 'gi://St' ;
33import Gio from 'gi://Gio' ;
4- import Gst from 'gi://Gst' ;
54import { Extension , gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js' ;
65import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js' ;
76import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js' ;
87import * as Main from 'resource:///org/gnome/shell/ui/main.js' ;
98
109import { ensureStorageFile , loadStations , STORAGE_PATH , initTranslations } from './radioUtils.js' ;
11- import { createMetadataItem , updateMetadataDisplay } from './modules/metadataDisplay.js' ;
10+ import { createMetadataItem , updateMetadataDisplay , updatePlaybackStateIcon } from './modules/metadataDisplay.js' ;
1211import { createVolumeItem , onVolumeChanged } from './modules/volumeControl.js' ;
1312import { createScrollableSection , createStationMenuItem , refreshStationsMenu } from './modules/stationMenu.js' ;
14- import { ensurePlayer , handleTagMessage , startMetadataUpdate , stopMetadataUpdate , playStation , updateStationHistory , updatePlaybackControl , togglePlayback , handleMediaPlayPause , handleMediaStop , stopPlayback } from './modules/playbackManager.js' ;
13+ import PlaybackManager from './modules/playbackManager.js' ;
1514import { setupMediaKeys , cleanupMediaKeys } from './modules/mediaKeys.js' ;
1615
1716initTranslations ( _ ) ;
@@ -24,19 +23,13 @@ const Indicator = GObject.registerClass(
2423 this . _stations = stations ?? [ ] ;
2524 this . _openPrefs = openPrefs ;
2625 this . _settings = settings ;
27- this . _player = null ;
28- this . _nowPlaying = null ;
29- this . _playbackState = 'stopped' ;
30- this . _metadataTimer = null ;
31- this . _currentMetadata = {
32- title : null ,
33- artist : null ,
34- albumArt : null ,
35- bitrate : null
36- } ;
37- this . _bus = null ;
38- this . _busHandlerId = null ;
39- this . _pausedAt = null ;
26+
27+ this . _playbackManager = new PlaybackManager ( this . _settings , {
28+ onStateChanged : ( state ) => this . _onStateChanged ( state ) ,
29+ onStationChanged : ( station ) => this . _onStationChanged ( station ) ,
30+ onMetadataUpdate : ( ) => this . _updateMetadataDisplay ( ) ,
31+ onVisibilityChanged : ( visible ) => this . _updateVisibility ( visible )
32+ } ) ;
4033
4134 const iconPath = `${ extensionPath } /icons/yetanotherradio.svg` ;
4235 const iconFile = Gio . File . new_for_path ( iconPath ) ;
@@ -49,7 +42,10 @@ const Indicator = GObject.registerClass(
4942
5043 this . menu . actor . add_style_class_name ( 'yetanotherradio-menu' ) ;
5144
52- this . _metadataItem = createMetadataItem ( ) ;
45+ this . _metadataItem = createMetadataItem (
46+ ( ) => this . _togglePlayback ( ) ,
47+ ( ) => this . _stopPlayback ( )
48+ ) ;
5349 this . _metadataItem . visible = false ;
5450 this . menu . addMenuItem ( this . _metadataItem ) ;
5551
@@ -58,11 +54,6 @@ const Indicator = GObject.registerClass(
5854 this . _volumeItem . visible = false ;
5955 this . menu . addMenuItem ( this . _volumeItem ) ;
6056
61- this . _playbackControlItem = new PopupMenu . PopupMenuItem ( _ ( 'Pause' ) ) ;
62- this . _playbackControlItem . connect ( 'activate' , ( ) => this . _togglePlayback ( ) ) ;
63- this . _playbackControlItem . visible = false ;
64- this . menu . addMenuItem ( this . _playbackControlItem ) ;
65-
6657 this . menu . addMenuItem ( new PopupMenu . PopupSeparatorMenuItem ( ) ) ;
6758
6859 this . _favoritesSection = new PopupMenu . PopupMenuSection ( ) ;
@@ -93,12 +84,32 @@ const Indicator = GObject.registerClass(
9384 this . _refreshStationsMenu ( ) ;
9485 }
9586
87+ _onStateChanged ( state ) {
88+ updatePlaybackStateIcon ( this . _metadataItem , state ) ;
89+ }
90+
91+ _onStationChanged ( station ) {
92+ this . _refreshStationsMenu ( ) ;
93+ }
94+
95+ _updateVisibility ( visible ) {
96+ const showMetadata = this . _settings ?. get_boolean ( 'show-metadata' ) ?? true ;
97+ this . _metadataItem . visible = visible && showMetadata ;
98+ this . _volumeItem . visible = visible ;
99+ }
100+
96101 _onVolumeChanged ( ) {
97- onVolumeChanged ( this . _volumeItem . _volumeSlider , this . _player , this . _volumeItem . _volumeIcon , this . _settings ) ;
102+ onVolumeChanged ( this . _volumeItem . _volumeSlider , this . _volumeItem . _volumeIcon , this . _settings ) ;
103+ this . _playbackManager . setVolume ( this . _volumeItem . _volumeSlider . value ) ;
98104 }
99105
100106 _updateMetadataDisplay ( ) {
101- updateMetadataDisplay ( this . _settings , this . _metadataItem , this . _player , this . _nowPlaying , this . _currentMetadata ) ;
107+ updateMetadataDisplay (
108+ this . _settings ,
109+ this . _metadataItem ,
110+ this . _playbackManager . nowPlaying ,
111+ this . _playbackManager . currentMetadata
112+ ) ;
102113 }
103114
104115 setStations ( stations ) {
@@ -113,7 +124,8 @@ const Indicator = GObject.registerClass(
113124 this . _stationSection ,
114125 this . _scrollableSection ,
115126 this . _hintItem ,
116- ( station ) => this . _createStationMenuItem ( station )
127+ ( station , isNowPlaying ) => this . _createStationMenuItem ( station , isNowPlaying ) ,
128+ this . _playbackManager . nowPlaying
117129 ) ;
118130
119131 const favorites = this . _stations . filter ( s => s . favorite ) ;
@@ -130,136 +142,35 @@ const Indicator = GObject.registerClass(
130142 }
131143 }
132144
133- _createStationMenuItem ( station ) {
134- return createStationMenuItem ( station , ( s ) => this . _playStation ( s ) ) ;
135- }
136-
137- _ensurePlayer ( ) {
138- const { player, bus, busHandlerId } = ensurePlayer (
139- this . _player ,
140- this . _settings ,
141- this . _currentMetadata ,
142- this . _bus ,
143- this . _busHandlerId ,
144- ( message , currentMetadata ) => this . _handleTagMessage ( message ) ,
145- ( ) => this . _stopPlayback ( ) ,
146- ( station ) => this . _playStation ( station )
147- ) ;
148- this . _player = player ;
149- this . _bus = bus ;
150- this . _busHandlerId = busHandlerId ;
151- }
152-
153- _handleTagMessage ( message ) {
154- handleTagMessage ( message , this . _currentMetadata ) ;
155- }
156-
157- _startMetadataUpdate ( ) {
158- this . _metadataTimer = startMetadataUpdate (
159- this . _settings ,
160- this . _metadataTimer ,
161- ( ) => this . _updateMetadataDisplay ( )
162- ) ;
163- }
164-
165- _stopMetadataUpdate ( ) {
166- this . _metadataTimer = stopMetadataUpdate ( this . _metadataTimer ) ;
145+ _createStationMenuItem ( station , isNowPlaying = false ) {
146+ return createStationMenuItem ( station , ( s ) => this . _playStation ( s ) , isNowPlaying ) ;
167147 }
168148
169149 _playStation ( station ) {
170- this . _ensurePlayer ( ) ;
171- const result = playStation (
172- station ,
173- this . _player ,
174- this . _settings ,
175- this . _currentMetadata ,
176- this . _metadataItem ,
177- this . _volumeItem ,
178- this . _playbackControlItem ,
179- ( ) => this . _startMetadataUpdate ( ) ,
180- ( s ) => this . _updateStationHistory ( s ) ,
181- ( state ) => this . _updatePlaybackControl ( state ) ,
182- ( ) => this . _refreshStationsMenu ( )
183- ) ;
184- this . _nowPlaying = result . nowPlaying ;
185- this . _playbackState = result . playbackState ;
186- }
187-
188- _updateStationHistory ( station ) {
189- updateStationHistory ( station ) ;
150+ this . _playbackManager . play ( station ) ;
190151 }
191152
192- _updatePlaybackControl ( state ) {
193- updatePlaybackControl ( state || this . _playbackState , this . _playbackControlItem ) ;
153+ _togglePlayback ( ) {
154+ this . _playbackManager . toggle ( ) ;
194155 }
195156
196- _togglePlayback ( ) {
197- const result = togglePlayback (
198- this . _player ,
199- this . _playbackState ,
200- this . _pausedAt ,
201- this . _nowPlaying ,
202- ( station ) => this . _playStation ( station ) ,
203- ( state ) => this . _updatePlaybackControl ( state )
204- ) ;
205- this . _playbackState = result . playbackState ;
206- this . _pausedAt = result . pausedAt ;
157+ _stopPlayback ( ) {
158+ this . _playbackManager . stop ( ) ;
207159 }
208160
209161 handleMediaPlayPause ( ) {
210- handleMediaPlayPause ( this . _playbackState , ( ) => this . _togglePlayback ( ) ) ;
162+ this . _togglePlayback ( ) ;
211163 }
212164
213165 handleMediaStop ( ) {
214- handleMediaStop ( this . _playbackState , ( ) => this . _stopPlayback ( ) ) ;
215- }
216-
217- _stopPlayback ( ) {
218- const result = stopPlayback (
219- this . _player ,
220- this . _nowPlaying ,
221- this . _playbackState ,
222- this . _pausedAt ,
223- this . _playbackControlItem ,
224- this . _volumeItem ,
225- this . _metadataItem ,
226- ( ) => this . _stopMetadataUpdate ( ) ,
227- this . _currentMetadata ,
228- ( ) => this . _refreshStationsMenu ( )
229- ) ;
230- this . _nowPlaying = result . nowPlaying ;
231- this . _playbackState = result . playbackState ;
232- this . _pausedAt = result . pausedAt ;
166+ this . _stopPlayback ( ) ;
233167 }
234168
235169 destroy ( ) {
236- if ( this . _playbackState !== 'stopped' ) {
237- this . _stopPlayback ( ) ;
238- }
239-
240- this . _stopMetadataUpdate ( ) ;
241-
242- if ( this . _bus ) {
243- if ( this . _busHandlerId ) {
244- this . _bus . disconnect ( this . _busHandlerId ) ;
245- this . _busHandlerId = null ;
246- }
247- this . _bus . remove_signal_watch ( ) ;
248- this . _bus = null ;
249- }
250-
251- if ( this . _player ) {
252- try {
253- this . _player . set_state ( Gst . State . NULL ) ;
254- } catch ( e ) {
255- console . debug ( e ) ;
256- }
257- this . _player = null ;
258- }
170+ this . _playbackManager . destroy ( ) ;
259171
260172 this . _metadataItem = null ;
261173 this . _volumeItem = null ;
262- this . _playbackControlItem = null ;
263174 this . _favoritesSection = null ;
264175 this . _stationSection = null ;
265176 this . _scrollableSection = null ;
0 commit comments