Music player - endlessly plays your music

Related tags

Audio music-player
Overview

Music player

First, if you wonder about what is supposed to be a music player or what makes a music player different from a simple media player, read this: What is a music player

Annoyed by all existing players because some subset of:

  • not open source
  • missing sound format (FLAC, Ogg, ...)
  • bugs (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...)
  • missing output possibility (RAOP, PulseAudio, ...)
  • none or too limited intelligent automatic queue (iTunes calls this DJ mode, others call this PartyShuffle)
  • no library / database

Features of this player:

  • open source (simplified BSD license, see License.txt)
  • simple
  • support of most important sound formats
  • advanced intelligent automatic queue which is the main mode to play music
  • simple music database
  • ReplayGain / audio volume normalization
  • Last.fm scrobbling
  • AcoustID fingerprint
  • Gapless playback
  • MPD backend

MusicPlayer screenshot

About the intelligent automatic queue, what I want (maybe some of these somewhat configurable):

  • continuously always add songs when queue becomes too empty
  • liked songs more often
  • context-based choices, e.g. related songs more likely
  • possibility to easily manually add songs to the list
  • easy way to restrict to a subset of songs (like a genre, a playlist, a filesystem directory, etc.)

About the database:

  • main function: search
  • should be fast and optional for playback, i.e. music can be played even when the database is currently not ready for some reason
  • should automatically be filled by a filesystem directory
  • import like-state from local players like iTunes and also online services like Last.fm

TODO / possible additional missing features:

  • BPM determination and clever DJ-like fading
  • use tags given by Last.fm (mostly more tags)
  • watch music directory for changes (e.g. new files added)
  • other GUI implementations

Comparison to other music players:

Installation:

So far, there is a prebuild MacOSX app bundle in the download section which should just work. Otherwise, to get the source working, you need these requirements (e.g. install on MacOSX via Homebrew):

  • ffmpeg
  • portaudio
  • chromaprint

(Debian/Ubuntu: apt-get install python-dev libsnappy-dev libtool yasm libchromaprint-dev portaudio19-dev libboost-dev. FFmpeg in Debian/Ubuntu is too old (lacks libswresample), so either do add-apt-repository ppa:jon-severinsson/ffmpeg && apt-get update && apt-get install libavformat-dev libswresample-dev or install it from source. Chromaprint depends on FFmpeg, so if you have a custom FFmpeg install, you might also want to install that manually. ./configure && make && sudo make install should work for FFmpeg and PortAudio. You might also want to use --enable-shared for FFmpeg. cmake . && sudo make install for Chromaprint.)

Then call ./compile.py to build the Python modules (it will build the Python modules ffmpeg.so and leveldb.so).

To start the player, just call ./main.py.

The current GUI is Cocoa only. Additional Qt support is planned. The music player also works without any GUI.

You can also control the player via an interactive Python shell. You can get the shell directly by passing --shell to main.py or you can use tools/shell.py. Via the shell, you can do just anything. By default, the shell exports already the two main objects state and queue. Here some useful actions:

  • import utils: common imports you might need for the other commands
  • state.curSong: returns the current song
  • state.player.playing = True: start playing. or start/stop via state.playPause()
  • state.nextSong(): skips to next song
  • state.queue.shuffle(): shuffles the queue
  • utils.formatTime(sum([s.get("duration", accuracy=0, fastOnly=True)[0] or 0 for s in queue.queue.list])): get the amount of time of all songs in the queue
  • import guiCocoa; reload(guiCocoa): reload Cocoa GUI. this might be useful if it crashed (which shouldn't happen, though)

You can use dir to get a list of attributes of an object. E.g. dir(state) returns list of all state-attributes. This might be useful if you want to figure out what you can do. But it might be easier to just look at the source. And you can use tab-autocompletion, e.g. type state. and press tab.

Also, don't hesitate to play around with the code. You might be interested in the automatic queue handling code.

Authors:

Comments
  • Document OS compatibility

    Document OS compatibility

    The music-player app does not work on OSX 10.6, since it requires the 2.7 version of the Python framework.

    This should probably be documented somewhere in the readme.

    opened by dakrone 14
  • Main Window doesn't appear

    Main Window doesn't appear

    When I start the app, I don't get the main window. If I click "Search Window", it opens up and can be closed normally.

    I've gisted what appears likely to be the relevant error segment in console: https://gist.github.com/4059472 .

    Clicking on "Main Menu" generates the following errors in console: https://gist.github.com/4059502

    OS X 10.8.2

    opened by llimllib 11
  • headless / use as backend

    headless / use as backend

    I'd like to use this project as the backend for Groove Basin instead of MPD because MPD lacks many important things and has some critical bugs.

    Is that on the roadmap?

    opened by andrewrk 9
  • os x 10.9 error running from source

    os x 10.9 error running from source

    I am trying to run it from source as described in readme, I installed all deeps and started compile.py, when I try to run main.py I get this error.

    ./main.py
    note: faulthandler module not available
    MusicPlayer 1.0 from <unknown> git-ref <unknown> on MacOSX (darwin)
    startup on 2014-02-03 09:34:49 +0000
    Module player
    Module queue
    Module tracker
    Module tracker_lastfm
    Module mediakeys
    Module gui
    Module stdinconsole
    Module socketcontrol
    Module mpdBackend
    Module notifications
    Module preloader
    Module songdb
    EXCEPTION
    Traceback (most recent call last):
      File "./main.py", line 138, in <module>
        line: main()
        locals:
          main = <local> <function main at 0x101b78f50>
      File "./main.py", line 95, in main
        line: import gui
        locals:
          gui = <not found>
      File "/Users/ib/Documents/Python/music-player/gui.py", line 6, in <module>
        line: from _gui import *
        locals:
          _gui = <not found>
    ImportError: No module named _gui
    
    opened by ibeex 8
  • songs skipped

    songs skipped

    hey, i noticed that sometimes songs are skipped. the song gets played to up to may 2 sec and then MusicPlayer skips to the next song.

    hello there
    Error, argparse not available. This needs Python >=2.7.
    MusicPlayer 1.0 from 2013-03-12 19:46:21 +0000 git-ref 1d9c2eaed7 on MacOSX (darwin)
    startup on 2013-03-25 09:47:24 +0000
    Module player
    Module queue
    Module tracker
    Module tracker_lastfm
    Module mediakeys
    Module gui
    Module stdinconsole
    Module socketcontrol
    Module mpdBackend
    Module notifications
    Module preloader
    Module songdb
    icon.icns not found
    entering GUI main loop
    AppDelegate didFinishLaunching
    socketcontrol: listening on /var/folders/z3/wpry74bd23d6q0tl_wqn0m8c0000gn/T/com.albertzeyer.MusicPlayer-539-socketcontrol
    * loaded access token
    mpdBackend listening on 127.0.0.1:6600
    setupAfterAppFinishedLaunching ready
    error on updating song: Song(06 Invincible.mp3) , replaygain: too less data
    Error, argparse not available. This needs Python >=2.7.
    ExecingProcess child create search index worker process (pid 547)
    ExecingProcess child create search index worker process (pid 547) finished
    new song: Various - Rock me, 07:11, mp3, 313 kbit/s, 16.5 MB
    new song: Muse - Invincible, 05:00, mp3, 125 kbit/s, 4.58 MB
    new song: freeze-dried Rockers - Dangerous, 04:37, mp3, 187 kbit/s, 6.34 MB
    

    It skipped Muse - Invincible. In the main GUI the song info seems to be garbled. I tested playing in iTunes that worked without a problem.

    BTW what is the Error, argparse not available. This needs Python >=2.7.

    opened by christophmluscher 8
  • avcodec_decode_audio4

    avcodec_decode_audio4

    There is one mp3 in my collection that cant be played and in logg i get this error avcodec_decode_audio4 error at pos 0 but this mp3 can be played with ffplay and mplayer. Can I send you somehow mp3 or?

    Edit: It can be played if I add it manually to queue. But it generated that error when player tried to auto add it to queue and was skipped.

    opened by ibeex 7
  • song drag

    song drag

    if the playlist is filled with lots of songs and a song is dragged within the playlist. the song playing freezes. if the dragged song is released the music playing continues

    this is the error at that moment:

    new song: Lady GaGa - Paparazzi, 03:29, mp3, 62.6 kbit/s, 1.6 MB
    Cocoa GuiObjectView: control is wrong type
    readOutStream: we have 1212 too less samples available (requested 1862)
    readOutStream: we have 1862 too less samples available (requested 1862)
    
    opened by christophmluscher 6
  • Segfaults on my machine when I hit space to play

    Segfaults on my machine when I hit space to play

    ffmpeg 0.10.2-r1 on gentoo amd64

        #0  0x00007ffff7b06a9c in PyErr_Restore () from /usr/lib64/libpython2.7.so.1.0
        #1  0x00007ffff7b06bd7 in PyErr_SetString ()
           from /usr/lib64/libpython2.7.so.1.0
        #2  0x00007fffd836a01f in player_setplaying (player=0x7fffec098010, playing=1)
            at ../ffmpeg.c:1099
        #3  0x00007fffd836b021 in player_setattr (obj=0x7fffec098010, 
            key=0x7ffff7e97ef4 "playing", value=0x7ffff7d90bf0) at ../ffmpeg.c:1420
        #4  0x00007ffff7a9fc0f in PyObject_SetAttr ()
           from /usr/lib64/libpython2.7.so.1.0
        #5  0x00007ffff7af9a2c in PyEval_EvalFrameEx ()
           from /usr/lib64/libpython2.7.so.1.0
        #6  0x00007ffff7afca30 in PyEval_EvalFrameEx ()
           from /usr/lib64/libpython2.7.so.1.0
        #7  0x00007ffff7afca30 in PyEval_EvalFrameEx ()
           from /usr/lib64/libpython2.7.so.1.0
        #8  0x00007ffff7afca30 in PyEval_EvalFrameEx ()
           from /usr/lib64/libpython2.7.so.1.0
        #9  0x00007ffff7afde4d in PyEval_EvalCodeEx ()
           from /usr/lib64/libpython2.7.so.1.0
        #10 0x00007ffff7a89a6c in function_call () from /usr/lib64/libpython2.7.so.1.0
        #11 0x00007ffff7a637e3 in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0
        #12 0x00007ffff7afaffb in PyEval_EvalFrameEx ()
           from /usr/lib64/libpython2.7.so.1.0
        #13 0x00007ffff7afca30 in PyEval_EvalFrameEx ()
           from /usr/lib64/libpython2.7.so.1.0
        #14 0x00007ffff7afca30 in PyEval_EvalFrameEx ()
           from /usr/lib64/libpython2.7.so.1.0
        #15 0x00007ffff7afde4d in PyEval_EvalCodeEx ()
           from /usr/lib64/libpython2.7.so.1.0
        #16 0x00007ffff7a89961 in function_call () from /usr/lib64/libpython2.7.so.1.0
        #17 0x00007ffff7a637e3 in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0
    
    opened by jasom 5
  • ALSA lib error on linux (ubuntu)

    ALSA lib error on linux (ubuntu)

    ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
    ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
    ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
    ALSA lib audio/pcm_bluetooth.c:1614:(audioservice_expect) BT_GET_CAPABILITIES failed : Input/output error(5)
    ALSA lib audio/pcm_bluetooth.c:1614:(audioservice_expect) BT_GET_CAPABILITIES failed : Input/output error(5)
    ALSA lib audio/pcm_bluetooth.c:1614:(audioservice_expect) BT_GET_CAPABILITIES failed : Input/output error(5)
    ALSA lib audio/pcm_bluetooth.c:1614:(audioservice_expect) BT_GET_CAPABILITIES failed : Input/output error(5)
    ALSA lib pcm_dmix.c:957:(snd_pcm_dmix_open) The dmix plugin supports only playback stream
    

    I was trying to run music-player on a linux machine (ubuntu), but i got these errors...

    opened by cava 4
  • AcoustID API key

    AcoustID API key

    It seems that you are using the AcoustID API key from pyacoustid. Please register your own one.

    https://github.com/albertz/music-player/blob/aba56e483a4a98779ed0cb24fe171189aeb0423b/SongEdit.py#L118

    opened by lalinsky 3
  • Main window does not show

    Main window does not show

    I tried the latest build on OS X and the main window refuses to show up.

    First launch, I need to authorize the app on last.fm. I did and then nothing else appear. Only search window can be opened.

    opened by tuananh 3
  • ImportError: No module named compile_utils

    ImportError: No module named compile_utils

    user@ubuntu:~/music-player$ ./compile.py 
    Traceback (most recent call last):
      File "./compile.py", line 8, in <module>
        from compile_utils import *
    ImportError: No module named compile_utils
    
    opened by eternaleclipse 0
  • Installing in windows

    Installing in windows "illegal member initialization: 'PyMutex'"

    When I try to install musicplayer on windows using Microsoft Visual Studio 9.0 I get that error when I call pip install musicplayer Any idea why ? Isn't the plugin compatible with Windows ?

    screenshot from 2016-03-17 20-35-28

    opened by arieltorti 1
  • Hang in CGSGetSurfaceBounds

    Hang in CGSGetSurfaceBounds

    0   MusicPlayer                         0x000000010000568c print_backtrace + 61
    1   MusicPlayer                         0x0000000100008408 _ZN5boost6detail8function26void_function_obj_invoker3IZN18ThreadHangDetector17_backgroundThreadEvEUliPvS4_E_viS4_S4_E6invokeERNS1_15function_bufferEiS4_S4_ + 48
    2   MusicPlayer                         0x0000000100002c10 _ZNK5boost9function3IviPvS1_EclEiS1_S1_ + 28
    3   MusicPlayer                         0x00000001000028ac _ZL25_callstack_signal_handleriP9__siginfoPv + 52
    4   libsystem_platform.dylib            0x00007fff92929f1a _sigtramp + 26
    5   ???                                 0x3ff0000000000000 0x0 + 4607182418800017408
    6   CoreGraphics                        0x00007fff8ee74fa6 _CGSGetSurfaceBounds + 128
    7   CoreGraphics                        0x00007fff8ee74ec6 CGSGetSurfaceBounds + 97
    8   AppKit                              0x00007fff8b7bf4e6 -[NSSurface setFrame:] + 848
    9   AppKit                              0x00007fff8b7bede0 -[NSSurface syncToViewUnconditionally] + 161
    10  AppKit                              0x00007fff8be150ac -[NSView _syncAndDisplaySurfaceIfNecessary:] + 282
    11  CoreFoundation                      0x00007fff938cbcdc __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    12  CoreFoundation                      0x00007fff937bd244 _CFXNotificationPost + 3140
    13  Foundation                          0x00007fff8b21fc31 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
    14  AppKit                              0x00007fff8b856e80 -[NSView _sendSurfaceSyncNotificationAndFlushSurfacesWithRegionToDisplay:] + 87
    15  AppKit                              0x00007fff8b82ba93 -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 4753
    16  AppKit                              0x00007fff8b809e2d -[NSView displayIfNeeded] + 1876
    17  AppKit                              0x00007fff8b8271c5 -[NSWindow displayIfNeeded] + 232
    18  AppKit                              0x00007fff8b864322 _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints + 936
    19  AppKit                              0x00007fff8be2d0e1 __83-[NSWindow _postWindowNeedsDisplayOrLayoutOrUpdateConstraintsUnlessPostingDisabled]_block_invoke1531 + 46
    20  CoreFoundation                      0x00007fff9382cda7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    21  CoreFoundation                      0x00007fff9382cd00 __CFRunLoopDoObservers + 368
    22  CoreFoundation                      0x00007fff9381ee08 __CFRunLoopRun + 872
    23  CoreFoundation                      0x00007fff9381e858 CFRunLoopRunSpecific + 296
    24  HIToolbox                           0x00007fff9435caef RunCurrentEventLoopInMode + 235
    25  HIToolbox                           0x00007fff9435c86a ReceiveNextEventCommon + 431
    26  HIToolbox                           0x00007fff9435c6ab _BlockUntilNextEventMatchingListInModeWithFilter + 71
    27  AppKit                              0x00007fff8b704f81 _DPSNextEvent + 964
    28  AppKit                              0x00007fff8b704730 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 194
    29  AppKit                              0x00007fff8b6f8593 -[NSApplication run] + 594
    30  _guiCocoa.so                        0x00000001083bf2f1 _Z13guiCocoa_mainP7_object + 175
    

    Probably related are these issues from Chrome: here, here, here.

    As far as I understand, the work-around was to use a separate front buffer texture. See here or here and search for http://crbug.com/234428.

    Other maybe related Python threads:

    Thread 0x0000000122bfb000:
      File "mediakeys.py", line 96 in runEventsCapture
      File "utils.py", line 1359 in doCall
      File "threading.py", line 761 in run
      File "threading.py", line 808 in __bootstrap_inner
      File "threading.py", line 781 in __bootstrap
    
    Thread 0x0000000120001000:
      File "utils.py", line 1094 in get
      File "guiCocoa.py", line 371 in getBmpData
      File "utils.py", line 1359 in doCall
      File "threading.py", line 761 in run
      File "threading.py", line 808 in __bootstrap_inner
      File "threading.py", line 781 in __bootstrap
    
    Thread 0x000000011f188000:
      File "utils.py", line 1094 in get
      File "guiCocoa.py", line 371 in getBmpData
      File "utils.py", line 1359 in doCall
      File "threading.py", line 761 in run
      File "threading.py", line 808 in __bootstrap_inner
      File "threading.py", line 781 in __bootstrap
    
    Thread 0x000000011d1f1000:
      File "utils.py", line 1094 in get
      File "guiCocoa.py", line 371 in getBmpData
      File "utils.py", line 1359 in doCall
      File "threading.py", line 761 in run
      File "threading.py", line 808 in __bootstrap_inner
      File "threading.py", line 781 in __bootstrap
    
    Thread 0x0000000111ac4000:
      File "guiCocoa.py", line 401 in playCursorUpdater
      File "utils.py", line 1359 in doCall
      File "threading.py", line 761 in run
      File "threading.py", line 808 in __bootstrap_inner
      File "threading.py", line 781 in __bootstrap
    
    opened by albertz 0
  • star system filter

    star system filter

    idea: only play songs with a certain star rating. for example only play songs with 4 stars, 5 stars or no rating.

    is that practical? just wondering :)

    opened by christophmluscher 5
  • do you have any interest in collaborating on the backend?

    do you have any interest in collaborating on the backend?

    I started a project which is meant to be generic music player backend library, written in pure C: https://github.com/superjoe30/libgroove

    It's still a young project, but it already works quite well.

    It looks like the backend for albertz/music-player and libgroove have much in common. So much, in fact, that I wonder if we might benefit from merging backends.

    For me, it would look like gaining a collaborator/maintainer for libgroove. I'm sure your expertise would improve the library's quality. This is obviously a benefit for me.

    For you, it would be some work to extract your backend, identify missing features in libgroove (which I would happily implement), and transition to using a different API your new backend. That's a con. On the pro side, you'd gain an extra maintainer on your backend (me). You'd be sharing backends, so the burden of maintenance is halved. The idea is that long term, this is more sustainable. As an added bonus, the boost in quality and usage to libgroove would increase the chances that it would get used for additional projects, increasing the "eyeball count" in a snowball effect.

    If you're interested, have a look at src/groove.h and the examples to get a feel for the API so far.

    There's also a demo Qt app which is a thin UI on top of libgroove.

    libgroove is meant to be minimal and generic enough that you could built albertz/music-player on top of it with no problem.

    What do you think?

    opened by andrewrk 2
Music player and music library manager for Linux, Windows, and macOS

Ex Falso / Quod Libet - A Music Library / Editor / Player Quod Libet is a music management program. It provides several different ways to view your au

Quod Libet 1.2k Jan 7, 2023
SU Music Player — The first open-source PyTgCalls based Pyrogram bot to play music in voice chats

SU Music Player — The first open-source PyTgCalls based Pyrogram bot to play music in voice chats Note Neither this, or PyTgCalls are fully

SU Projects 58 Jan 2, 2023
This is an OverPowered Vc Music Player! Will work for you and play music in Voice Chatz

VcPlayer This is an OverPowered Vc Music Player! Will work for you and play music in Voice Chatz Telegram Voice-Chat Bot [PyTGCalls] ⇝ Requirements ⇜

null 1 Dec 20, 2021
XA Music Player - Telegram Music Bot

XA Music Player Requirements ?? FFmpeg (Latest) NodeJS nodesource.com (NodeJS 17+) Python (3.10+) PyTgCalls (Lastest) MongoDB (3.12.1) 2nd Telegram Ac

RexAshh 3 Jun 30, 2022
❤️ Hi There Im Cozmo Music Bot A next gen powerful telegram group Music bot for get your Songs and music @Venuja_Sadew

?? Cozmo MUSIC ?? Cozmo Music is a Music powerfull bot for playing music on telegram voice chat groups. Requirements FFmpeg NodeJS nodesource.com Pyth

Venuja Sadew 3 Jan 8, 2022
A python script that can play .mp3 URLs upon the ringing or motion detection of a Ring doorbell. The sound plays through Sonos speakers.

Ring x Sonos A python script that plays .mp3 files whenever a doorbell is rung or a doorbell detects motion. Features Music! Authors @braden Running T

braden 0 Nov 12, 2021
A rofi-blocks script that searches youtube and plays the selected audio on mpv.

rofi-ytm A rofi-blocks script that searches youtube and plays the selected audio on mpv. To use the script, run the following command rofi -modi block

Cliford 26 Dec 21, 2022
Okaeri-Music is a telegram music bot project, allow you to play music on voice chat group telegram.

Okaeri-Music is a telegram bot project that's allow you to play music on telegram voice chat group

Wahyusaputra 1 Dec 22, 2021
Okaeri-Music is a telegram music bot project, allow you to play music on voice chat group telegram.

??️ PROJECT MUSIC,THIS IS MAINTAINED Okaeri-Music is a telegram bot project that's allow you to play music on telegram voice chat group Features ?? Th

Okaeri-Project 2 Dec 23, 2021
NovaMusic is a music sharing robot. Users can get music and music lyrics using inline queries.

A music sharing telegram robot using Redis database and Telebot python library using Redis database.

Hesam Norin 7 Oct 21, 2022
:notes: Cross-platform music player

Exaile Exaile is a music player with a simple interface and powerful music management capabilities. Features include automatic fetching of album art,

Exaile 327 Dec 19, 2022
A Music Player Bot for Discord Servers

A Music Player Bot for Discord Servers

Halil Acar 2 Oct 25, 2021
Stevan KZ 1 Oct 27, 2021
An 8D music player made to enjoy Halloween this year!🤘

HAPPY HALLOWEEN buddy! Split Player Hello There! Welcome to SplitPlayer... Supposed To Be A 8DPlayer.... You Decide.... It can play the ordinary audio

Akshat Kumar Singh 1 Nov 4, 2021
A music player designed for a University Project.

A music player designed for a University Project. Very flexibe and easy to use, a real life working application with user friendly controls. Hope u enjoy!!

Aditya Johorey 1 Nov 19, 2021
A Quick Music Player Made Fully in Python

Quick Music Player Made Fully In Python. Pure Python, cross platform, single function module with no dependencies for playing sounds. Installation & S

null 1 Dec 24, 2021
Vixtify - Python Controlled Music Player

Strumm Sound Playlist : Click me to listen Welcome to GitHub Pages You can use the editor on GitHub to maintain and preview the content for your websi

Vicky Kumar 2 Feb 3, 2022
Anki vector Music ❤ is the best and only Telegram VC player with playlists, Multi Playback, Channel play and more

Anki Vector Music ?? A bot that can play music on Telegram Group and Channel Voice Chats Available on telegram as @Anki Vector Music Features ?? Thumb

Damantha Jasinghe 12 Nov 12, 2022
Klangbecken: The RaBe Endless Music Player

Klangbecken Klangbecken is the minimalistic endless music player for Radio Bern RaBe based on liquidsoap. It supports configurable and editable playli

Radio Bern RaBe 8 Oct 9, 2021