0
# Core Controllers
1
2
Mopidy's core system provides centralized business logic controllers for managing all aspects of music playback, library access, playlist management, and audio control. These controllers form the main API surface for interacting with Mopidy programmatically.
3
4
## Capabilities
5
6
### Core Actor System
7
8
The main Core actor coordinates all system components and provides the primary interface for Mopidy functionality.
9
10
```python { .api }
11
class Core(pykka.ThreadingActor):
12
"""
13
Main core actor that coordinates all Mopidy functionality.
14
15
Parameters:
16
- config: Mopidy configuration
17
- mixer: Audio mixer instance
18
- backends: List of configured backends
19
- audio: Audio actor instance
20
"""
21
def __init__(self, config, mixer, backends, audio): ...
22
23
# Controller properties
24
@property
25
def playback(self) -> PlaybackController: ...
26
27
@property
28
def library(self) -> LibraryController: ...
29
30
@property
31
def tracklist(self) -> TracklistController: ...
32
33
@property
34
def playlists(self) -> PlaylistsController: ...
35
36
@property
37
def mixer(self) -> MixerController: ...
38
39
@property
40
def history(self) -> HistoryController: ...
41
```
42
43
### Playback Control
44
45
Comprehensive playback control including play/pause/stop, seeking, volume, and playback state management.
46
47
```python { .api }
48
class PlaybackController:
49
"""Controls music playback including play, pause, stop, and seeking."""
50
51
def play(self, tl_track=None, tlid=None):
52
"""
53
Start playback.
54
55
Parameters:
56
- tl_track (TlTrack, optional): Track to play (deprecated, use tlid)
57
- tlid (int, optional): TLID of track to play, or None for current
58
59
Returns:
60
- TlTrack or None: The track that was played
61
"""
62
...
63
64
def pause(self):
65
"""
66
Pause playback.
67
68
Returns:
69
- bool: True if successful
70
"""
71
...
72
73
def stop(self):
74
"""
75
Stop playback and clear current track.
76
77
Returns:
78
- bool: True if successful
79
"""
80
...
81
82
def resume(self):
83
"""
84
Resume playback from paused state.
85
86
Returns:
87
- bool: True if successful
88
"""
89
...
90
91
def seek(self, time_position):
92
"""
93
Seek to specific position in current track.
94
95
Parameters:
96
- time_position (int): Position in milliseconds
97
98
Returns:
99
- bool: True if successful
100
"""
101
...
102
103
def get_time_position(self):
104
"""
105
Get current playback position.
106
107
Returns:
108
- int: Position in milliseconds
109
"""
110
...
111
112
def get_state(self):
113
"""
114
Get current playback state.
115
116
Returns:
117
- PlaybackState: Current state (playing, paused, stopped)
118
"""
119
...
120
121
def set_state(self, new_state):
122
"""
123
Set the playback state.
124
125
Parameters:
126
- new_state (PlaybackState): Must be PLAYING, PAUSED, or STOPPED
127
128
Note: This is primarily for internal use and testing
129
"""
130
...
131
132
def next(self):
133
"""
134
Change to next track in tracklist.
135
136
Returns:
137
- TlTrack or None: Next track that was switched to
138
"""
139
...
140
141
def previous(self):
142
"""
143
Change to previous track in tracklist.
144
145
Returns:
146
- TlTrack or None: Previous track that was switched to
147
"""
148
...
149
150
def get_current_tl_track(self):
151
"""
152
Get currently playing or paused track.
153
154
Returns:
155
- TlTrack or None: Current track
156
"""
157
...
158
159
def get_current_track(self):
160
"""
161
Get currently playing or paused track.
162
163
Returns:
164
- Track or None: Current track
165
"""
166
...
167
168
def get_current_tlid(self):
169
"""
170
Get TLID of currently playing or paused track.
171
172
Returns:
173
- int or None: Current track TLID
174
"""
175
...
176
177
def get_stream_title(self):
178
"""
179
Get stream title for radio streams.
180
181
Returns:
182
- str or None: Stream title if available
183
"""
184
...
185
186
class PlaybackState:
187
"""Playback state constants."""
188
STOPPED = "stopped"
189
PLAYING = "playing"
190
PAUSED = "paused"
191
```
192
193
Usage example:
194
```python
195
from mopidy.core import Core
196
197
# Assume core is a Core instance
198
core.playback.play() # Start playback
199
core.playback.pause() # Pause
200
core.playback.seek(30000) # Seek to 30 seconds
201
state = core.playback.get_state() # Get current state
202
```
203
204
### Library Access
205
206
Library browsing, searching, and track lookup across all configured backends.
207
208
```python { .api }
209
class LibraryController:
210
"""Provides library browsing and searching across backends."""
211
212
def browse(self, uri, **kwargs):
213
"""
214
Browse library at given URI.
215
216
Parameters:
217
- uri (str): URI to browse
218
- **kwargs: Backend-specific options
219
220
Returns:
221
- list[Ref]: List of references at the URI
222
"""
223
...
224
225
def search(self, query=None, uris=None, exact=False):
226
"""
227
Search library across backends.
228
229
Parameters:
230
- query (dict, optional): Search query by field
231
- uris (list[str], optional): URIs to search within
232
- exact (bool): Whether to match exactly
233
234
Returns:
235
- list[SearchResult]: Search results from backends
236
"""
237
...
238
239
def lookup(self, uris=None):
240
"""
241
Lookup tracks by URI.
242
243
Parameters:
244
- uris (list[str]): URIs to lookup
245
246
Returns:
247
- dict[str, list[Track]]: Mapping of URI to tracks
248
"""
249
...
250
251
def refresh(self, uri=None):
252
"""
253
Refresh library cache.
254
255
Parameters:
256
- uri (str, optional): Specific URI to refresh
257
258
Returns:
259
- bool: True if successful
260
"""
261
...
262
263
def get_distinct(self, field, query=None):
264
"""
265
Get distinct values for a field.
266
267
Parameters:
268
- field (str): Field name ('artist', 'album', etc.)
269
- query (dict, optional): Query to filter by
270
271
Returns:
272
- set[str]: Distinct values
273
"""
274
...
275
276
def get_images(self, uris):
277
"""
278
Get images for given URIs.
279
280
Parameters:
281
- uris (list[str]): URIs to get images for
282
283
Returns:
284
- dict[str, list[Image]]: Mapping of URI to images
285
"""
286
...
287
```
288
289
Usage example:
290
```python
291
# Browse root directory
292
refs = core.library.browse("file:///")
293
294
# Search for tracks
295
results = core.library.search({"artist": ["Beatles"], "album": ["Abbey Road"]})
296
297
# Lookup specific tracks
298
tracks = core.library.lookup(["spotify:track:123", "local:track:song.mp3"])
299
```
300
301
### Tracklist Management
302
303
Manage the current tracklist including adding, removing, and reordering tracks.
304
305
```python { .api }
306
class TracklistController:
307
"""Manages the current tracklist of tracks to be played."""
308
309
def add(self, tracks=None, at_position=None, uris=None):
310
"""
311
Add tracks to tracklist.
312
313
Parameters:
314
- tracks (list[Track], optional): Tracks to add
315
- at_position (int, optional): Position to insert at
316
- uris (list[str], optional): URIs to add (alternative to tracks)
317
318
Returns:
319
- list[TlTrack]: Added tracklist tracks
320
"""
321
...
322
323
def remove(self, criteria):
324
"""
325
Remove tracks from tracklist.
326
327
Parameters:
328
- criteria (dict): Removal criteria (tlid, uri, etc.)
329
330
Returns:
331
- list[TlTrack]: Removed tracks
332
"""
333
...
334
335
def clear(self):
336
"""
337
Clear all tracks from tracklist.
338
339
Returns:
340
- bool: True if successful
341
"""
342
...
343
344
def move(self, start, end, to_position):
345
"""
346
Move tracks within tracklist.
347
348
Parameters:
349
- start (int): Start position
350
- end (int): End position
351
- to_position (int): Destination position
352
353
Returns:
354
- bool: True if successful
355
"""
356
...
357
358
def shuffle(self, start=None, end=None):
359
"""
360
Shuffle tracks in tracklist.
361
362
Parameters:
363
- start (int, optional): Start position
364
- end (int, optional): End position
365
366
Returns:
367
- bool: True if successful
368
"""
369
...
370
371
def get_tl_tracks(self):
372
"""
373
Get all tracklist tracks.
374
375
Returns:
376
- list[TlTrack]: All tracklist tracks
377
"""
378
...
379
380
def get_tracks(self):
381
"""
382
Get all tracks.
383
384
Returns:
385
- list[Track]: All tracks
386
"""
387
...
388
389
def get_length(self):
390
"""
391
Get tracklist length.
392
393
Returns:
394
- int: Number of tracks
395
"""
396
...
397
398
def get_version(self):
399
"""
400
Get tracklist version (increments on changes).
401
402
Returns:
403
- int: Version number
404
"""
405
...
406
407
def index(self, tl_track=None, tlid=None):
408
"""
409
Get index of tracklist track.
410
411
Parameters:
412
- tl_track (TlTrack, optional): Track to find
413
- tlid (int, optional): TLID to find (alternative to tl_track)
414
415
Returns:
416
- int or None: Index of track
417
"""
418
...
419
420
def filter(self, criteria):
421
"""
422
Filter the tracklist by the given criteria.
423
424
Each rule in the criteria consists of a model field and a list of
425
values to compare it against. If the model field matches any of the
426
values, it may be returned.
427
428
Parameters:
429
- criteria (dict): Filter criteria (uri, name, etc.)
430
431
Returns:
432
- list[TlTrack]: Filtered tracks
433
"""
434
...
435
436
def get_consume(self):
437
"""
438
Get consume mode status.
439
440
Returns:
441
- bool: True if consume mode is enabled
442
"""
443
...
444
445
def set_consume(self, value):
446
"""
447
Set consume mode.
448
449
Parameters:
450
- value (bool): Enable/disable consume mode
451
452
Returns:
453
- bool: True if successful
454
"""
455
...
456
457
def get_random(self):
458
"""
459
Get random mode status.
460
461
Returns:
462
- bool: True if random mode is enabled
463
"""
464
...
465
466
def set_random(self, value):
467
"""
468
Set random mode.
469
470
Parameters:
471
- value (bool): Enable/disable random mode
472
473
Returns:
474
- bool: True if successful
475
"""
476
...
477
478
def get_repeat(self):
479
"""
480
Get repeat mode status.
481
482
Returns:
483
- bool: True if repeat mode is enabled
484
"""
485
...
486
487
def set_repeat(self, value):
488
"""
489
Set repeat mode.
490
491
Parameters:
492
- value (bool): Enable/disable repeat mode
493
494
Returns:
495
- bool: True if successful
496
"""
497
...
498
499
def get_single(self):
500
"""
501
Get single mode status.
502
503
Returns:
504
- bool: True if single mode is enabled
505
"""
506
...
507
508
def set_single(self, value):
509
"""
510
Set single mode.
511
512
Parameters:
513
- value (bool): Enable/disable single mode
514
515
Returns:
516
- bool: True if successful
517
"""
518
...
519
520
def get_eot_tlid(self):
521
"""
522
The TLID of the track that will be played after the current track.
523
524
Not necessarily the same TLID as returned by get_next_tlid.
525
526
Returns:
527
- int or None: TLID of end-of-track track
528
"""
529
...
530
531
def eot_track(self, tl_track):
532
"""
533
The track that will be played after the given track.
534
535
Not necessarily the same track as next_track.
536
537
Note: This method is deprecated in favor of get_eot_tlid.
538
539
Parameters:
540
- tl_track (TlTrack or None): The reference track
541
542
Returns:
543
- TlTrack or None: End-of-track track
544
"""
545
...
546
547
def get_next_tlid(self):
548
"""
549
The TLID of the track that will be played if calling next().
550
551
For normal playback this is the next track in the tracklist. If repeat
552
is enabled the next track can loop around the tracklist. When random is
553
enabled this should be a random track.
554
555
Returns:
556
- int or None: TLID of next track
557
"""
558
...
559
560
def next_track(self, tl_track):
561
"""
562
The track that will be played if calling next().
563
564
Note: This method is deprecated in favor of get_next_tlid.
565
566
Parameters:
567
- tl_track (TlTrack or None): The reference track
568
569
Returns:
570
- TlTrack or None: Next track
571
"""
572
...
573
574
def get_previous_tlid(self):
575
"""
576
Returns the TLID of the track that will be played if calling previous().
577
578
For normal playback this is the previous track in the tracklist. If
579
random and/or consume is enabled it should return the current track.
580
581
Returns:
582
- int or None: TLID of previous track
583
"""
584
...
585
586
def previous_track(self, tl_track):
587
"""
588
Returns the track that will be played if calling previous().
589
590
Note: This method is deprecated in favor of get_previous_tlid.
591
592
Parameters:
593
- tl_track (TlTrack or None): The reference track
594
595
Returns:
596
- TlTrack or None: Previous track
597
"""
598
...
599
600
def slice(self, start, end):
601
"""
602
Get slice of tracklist.
603
604
Parameters:
605
- start (int): Start index
606
- end (int): End index
607
608
Returns:
609
- list[TlTrack]: Slice of tracks
610
"""
611
...
612
613
# Playback options
614
def get_consume(self):
615
"""Get consume mode state."""
616
...
617
618
def set_consume(self, value):
619
"""Set consume mode."""
620
...
621
622
def get_random(self):
623
"""Get random mode state."""
624
...
625
626
def set_random(self, value):
627
"""Set random mode."""
628
...
629
630
def get_repeat(self):
631
"""Get repeat mode state."""
632
...
633
634
def set_repeat(self, value):
635
"""Set repeat mode."""
636
...
637
638
def get_single(self):
639
"""Get single mode state."""
640
...
641
642
def set_single(self, value):
643
"""Set single mode."""
644
...
645
```
646
647
Usage example:
648
```python
649
# Add tracks to tracklist
650
tl_tracks = core.tracklist.add([track1, track2, track3])
651
652
# Set playback modes
653
core.tracklist.set_random(True)
654
core.tracklist.set_repeat(True)
655
656
# Get current tracklist
657
all_tracks = core.tracklist.get_tl_tracks()
658
```
659
660
### Playlist Management
661
662
Manage stored playlists including creation, modification, and deletion across backends.
663
664
```python { .api }
665
class PlaylistsController:
666
"""Manages stored playlists across backends."""
667
668
def as_list(self):
669
"""
670
Get all playlists.
671
672
Returns:
673
- list[Playlist]: All available playlists
674
"""
675
...
676
677
def get_items(self, uri):
678
"""
679
Get playlist items.
680
681
Parameters:
682
- uri (str): Playlist URI
683
684
Returns:
685
- list[Ref]: Playlist items
686
"""
687
...
688
689
def create(self, name, uri_scheme=None):
690
"""
691
Create new playlist.
692
693
Parameters:
694
- name (str): Playlist name
695
- uri_scheme (str, optional): URI scheme to use
696
697
Returns:
698
- Playlist or None: Created playlist
699
"""
700
...
701
702
def save(self, playlist):
703
"""
704
Save playlist changes.
705
706
Parameters:
707
- playlist (Playlist): Playlist to save
708
709
Returns:
710
- Playlist or None: Saved playlist
711
"""
712
...
713
714
def delete(self, uri):
715
"""
716
Delete playlist.
717
718
Parameters:
719
- uri (str): Playlist URI
720
721
Returns:
722
- bool: True if successful
723
"""
724
...
725
726
def lookup(self, uri):
727
"""
728
Lookup playlist by URI.
729
730
Parameters:
731
- uri (str): Playlist URI
732
733
Returns:
734
- Playlist or None: Found playlist
735
"""
736
...
737
738
def refresh(self, uri_scheme=None):
739
"""
740
Refresh playlists cache.
741
742
Parameters:
743
- uri_scheme (str, optional): Specific scheme to refresh
744
745
Returns:
746
- bool: True if successful
747
"""
748
...
749
750
def get_uri_schemes(self):
751
"""
752
Get available playlist URI schemes.
753
754
Returns:
755
- list[str]: Available URI schemes
756
"""
757
...
758
```
759
760
Usage example:
761
```python
762
# List all playlists
763
playlists = core.playlists.as_list()
764
765
# Create new playlist
766
playlist = core.playlists.create("My New Playlist")
767
768
# Add tracks and save
769
updated_playlist = playlist.replace(tracks=(track1, track2))
770
core.playlists.save(updated_playlist)
771
```
772
773
### Audio Mixer Control
774
775
Control audio volume and muting across the system.
776
777
```python { .api }
778
class MixerController:
779
"""Controls audio volume and muting."""
780
781
def get_volume(self):
782
"""
783
Get current volume level.
784
785
Returns:
786
- int or None: Volume level (0-100)
787
"""
788
...
789
790
def set_volume(self, volume):
791
"""
792
Set volume level.
793
794
Parameters:
795
- volume (int): Volume level (0-100)
796
797
Returns:
798
- bool: True if successful
799
"""
800
...
801
802
def get_mute(self):
803
"""
804
Get mute state.
805
806
Returns:
807
- bool or None: True if muted
808
"""
809
...
810
811
def set_mute(self, mute):
812
"""
813
Set mute state.
814
815
Parameters:
816
- mute (bool): True to mute
817
818
Returns:
819
- bool: True if successful
820
"""
821
...
822
```
823
824
### Playback History
825
826
Track and manage playback history for recently played tracks.
827
828
```python { .api }
829
class HistoryController:
830
"""Manages playback history of recently played tracks."""
831
832
def get_length(self):
833
"""
834
Get history length.
835
836
Returns:
837
- int: Number of history entries
838
"""
839
...
840
841
def get_history(self):
842
"""
843
Get playback history.
844
845
Returns:
846
- list[tuple[int, Ref]]: History entries (timestamp, track_ref)
847
"""
848
...
849
```
850
851
### Event Listener
852
853
Base class for receiving notifications about system events and state changes.
854
855
```python { .api }
856
class CoreListener:
857
"""Base class for receiving core system events."""
858
859
def track_playback_paused(self, tl_track, time_position):
860
"""Called when track playback is paused."""
861
...
862
863
def track_playback_resumed(self, tl_track, time_position):
864
"""Called when track playback is resumed."""
865
...
866
867
def track_playback_started(self, tl_track):
868
"""Called when track playback starts."""
869
...
870
871
def track_playback_ended(self, tl_track, time_position):
872
"""Called when track playback ends."""
873
...
874
875
def playback_state_changed(self, old_state, new_state):
876
"""Called when playback state changes."""
877
...
878
879
def tracklist_changed(self):
880
"""Called when tracklist is modified."""
881
...
882
883
def playlists_loaded(self):
884
"""Called when playlists are loaded."""
885
...
886
887
def volume_changed(self, volume):
888
"""Called when volume changes."""
889
...
890
891
def mute_changed(self, mute):
892
"""Called when mute state changes."""
893
...
894
```
895
896
Usage example:
897
```python
898
class MyListener(CoreListener):
899
def track_playback_started(self, tl_track):
900
print(f"Now playing: {tl_track.track.name}")
901
902
def volume_changed(self, volume):
903
print(f"Volume changed to: {volume}")
904
905
# Register listener (implementation depends on setup)
906
listener = MyListener()
907
```