Mopidy is an extensible music server written in Python

Overview

Mopidy

Mopidy is an extensible music server written in Python.

Mopidy plays music from local disk, Spotify, SoundCloud, Google Play Music, and more. You edit the playlist from any phone, tablet, or computer using a variety of MPD and web clients.

Stream music from the cloud

Vanilla Mopidy only plays music from files and radio streams. Through extensions, Mopidy can play music from cloud services like Spotify, SoundCloud, and Google Play Music. With Mopidy's extension support, backends for new music sources can be easily added.

Mopidy is just a server

Mopidy is a Python application that runs in a terminal or in the background on Linux computers or Macs that have network connectivity and audio output. Out of the box, Mopidy is an HTTP server. If you install the Mopidy-MPD extension, it becomes an MPD server too. Many additional frontends for controlling Mopidy are available as extensions.

Pick your favorite client

You and the people around you can all connect their favorite MPD or web client to the Mopidy server to search for music and manage the playlist together. With a browser or MPD client, which is available for all popular operating systems, you can control the music from any phone, tablet, or computer.

Mopidy on Raspberry Pi

The Raspberry Pi is an popular device to run Mopidy on, either using Raspbian, Ubuntu, or Arch Linux. Pimoroni recommends Mopidy for use with their Pirate Audio audio gear for Raspberry Pi. Mopidy is also a significant building block in the Pi Musicbox integrated audio jukebox system for Raspberry Pi.

Mopidy is hackable

Mopidy's extension support and Python, JSON-RPC, and JavaScript APIs make Mopidy a perfect base for your projects. In one hack, a Raspberry Pi was embedded in an old cassette player. The buttons and volume control are wired up with GPIO on the Raspberry Pi, and is used to control playback through a custom Mopidy extension. The cassettes have NFC tags used to select playlists from Spotify.

Getting started

To get started with Mopidy, begin by reading the installation docs.

Project resources

Latest PyPI version CI build status Read the Docs build status Test coverage Chat on Zulip
Comments
  • Look into adding a gstreamer fifo sink

    Look into adding a gstreamer fifo sink

    This keeps coming up as people really seem to like ncmpcpp's visualizer

    Trick for making a reliable FIFO sink is twofold. You need to use non-blocking writes, which means opening the write socket will fail unless there is a reader, hence you need a reader as well. Secondly if the buffer fills up because the external reader falls behind or there is none, your internal reader needs to clear the buffer.

    Following code captures the basic gist of this, but still needs some more work with respect to error handling.

    import errno
    import os
    import stat
    
    LINUX_FIFO_BUFFER_SIZE = 65536
    
    
    class FifoStreamer(object):                                                     
        def __init__(self, location):                                               
            self.location = location                                                
            self.reader = None                                                      
            self.writer = None                                                      
    
        def create(self):                                                           
            try:                                                                    
                mode = os.stat(self.location).st_mode                               
                if not stat.S_ISFIFO(mode):                                         
                    raise Exception('File exists but is not a FIFO')                
            except OSError as e:                                                    
                if e.errno == errno.ENOENT:                                         
                    os.mkfifo(self.location)                                        
                else:                                                               
                    raise                                                           
    
            # TODO: wrap in could not open reader / writer?
            self.reader = os.open(self.location, os.O_NONBLOCK | os.O_RDONLY)       
            self.writer = os.open(self.location, os.O_NONBLOCK | os.O_WRONLY)       
    
        def close(self):                                                            
            # TODO: make closing robust
            os.close(self.writer)                                                   
            os.close(self.reader)                                                   
    
        def write(self, data):                                                      
            while data:                                                             
                try:                                                                
                    written = os.write(self.writer, data)                           
                    data = data[written:]                                           
                except OSError as e:                                                
                    if e.errno == errno.EINTR:                                      
                        continue                                                    
                    elif e.errno in (errno.EAGAIN, errno.EWOULDBLOCK):              
                        self.flush()                                                
                    else:                                                           
                        raise                                                       
    
        def flush(self):                                                            
            while True:                                                             
                try:                                                                    
                    if not os.read(self.reader, LINUX_FIFO_BUFFER_SIZE):                             
                        break                                                       
                except OSError as e:                                                
                    if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK):                
                        break                                                       
                    elif e.errno == errno.EINTR:                                    
                        continue                                                    
                    else:                                                           
                        raise 
    

    The code above now needs to be integrated with GStreamer do actually do it's thing. Assuming 0.10 this is actually very much doable, reason I am hesitant is that we are planing a move to 1.x and the gir binding are not suited for making elements in python. In the case of this code in 1.x the problem boils down to not being able to create the pad templates that BaseSink expect to find. Creating this as a plain element might be doable, but you would need to re-implement way to much of the handling BaseSink makes sure you get right.

    import gobject                                                                  
    
    import pygst                                                                    
    pygst.require('0.10')                                                           
    import gst                                                             
    
    
    class FifoSink(gst.BaseSink):                                                   
        __gstdetails__ = (                                                          
            'FifoSink',                                                             
            'Sink',                                                                 
            'Sink designed to handle FIFO output.',                        
            'Mopidy')                                                               
    
        __gsttemplates__ = (gst.PadTemplate('sink', gst.PAD_SINK, gst.PAD_ALWAYS,   
                                            gst.caps_new_any()),)                   
    
        # TODO: don't allow changing location in flight, i.e. create getter/setter
        location = gobject.property(type=str)                                       
    
        def __init__(self):                                                         
            gst.BaseSink.__init__(self)                                             
            self.streamer = None                                                    
    
        def do_start(self):                                                                                               
            self.streamer = FifoStreamer(self.location)                             
            self.streamer.create()                                                  
            return True                                                             
    
        def do_stop(self):                                                          
            self.streamer.close()                                                   
            return True                                                             
    
        def do_render(self, buf):                                                   
            try:                                                                    
                self.streamer.write(bytes(buf))                                     
                return gst.FLOW_OK                                                  
            except OSError as e:                                                    
                self.error("Failed: %s", e)                                         
                return gst.FLOW_ERROR                                               
    
    
    gobject.type_register(FifoSink)                                                 
    gst.element_register(                                                           
        FifoSink, 'fifosink', gst.RANK_MARGINAL)                                    
    
    if __name__ == '__main__':                                                      
        import gobject                                                              
        gobject.threads_init()                                                      
    
        output = """                                                                
    capsfilter caps="audio/x-raw-int,width=16,rate=44100,channels=1" ! 
    tee name=t 
    t. ! queue ! alsasink                                                           
    t. ! queue ! fifosink location=/tmp/test2.fifo                                  
    """                                                                             
    
        sink = gst.parse_bin_from_description(                                      
            output, ghost_unconnected_pads=True)                                    
    
        playbin = gst.element_factory_make('playbin2')                              
        playbin.set_property('audio_sink', sink) 
    

    Note that one problem I ran into testing this was actually forgetting to match the audio format expected by ncmpcpp, so make sure mono/stereo do indeed match up.

    C-enhancement A-audio 
    opened by adamcik 73
  • core: Persist mopidy state between runs. Fix #310

    core: Persist mopidy state between runs. Fix #310

    I implemented writing/reading the core state to/from disk. Please review and comment.

    Instead of using a get_state() method (as recommended in #310), the core controller themselves knows what to export/import.

    Done:

    • moved json export/import write_library()/load_library() from mopidy/local to mopidy/models
    • new core methods save_state(), load_state()
    • save_state(), load_state() accessible via rpc
    • save state to disk at stop
    • load state from disk at start
    • new config: core.restore_state ("off", "load", "play")
    • update documentation
    • Persist following properties:
    mopidy.core.tracklist
        _tl_tracks
        _next_tlid
        get_consume()
        get_random()
        get_repeat()
        get_single()
    mopidy.core.history
        _history
    mopidy.core.playlist
        get_current_tl_track()
        get_time_position()
    mopidy.core.mixer
        get_volume()
    

    Todo:

    • seek to play position does not work. Timing issue.
    • use extra thread to load state from disk at start?
    C-enhancement A-core 
    opened by dublok 51
  • Stop using appsrc for spotify playback.

    Stop using appsrc for spotify playback.

    All playback should be done via gstreamer elements that support the uri interface gstreamer supports. This would greatly simplify a lot of issues as we could fall back to simply always passing the uri to the uridecodebin as is instead of doing funny things like using an appsrc for spotify. I have more thoughts about this and the recent comments in #40 and #38 fit into this.

    Major hurdle right no is that though I know how to write gstreamer elements in python (and C for that matter) it is not yet clear how to implement the URI interface via the python bindings. This might just be a gobject issue more than a gstreamer one, but I'm still looking.

    C-enhancement A-audio 
    opened by adamcik 47
  • javascript objects dissappear

    javascript objects dissappear

    When using the webclient with 0.16 (adapted for changes from the changelog), I get an error stating that the mopidy.playback and mopidy.tracklist objects are not defined. This happens not instantly, but after using the webclient for a while. After that, the Mopidy object is created, but there is no playback or tracklist object. The same behaviour in multiple browsers and on multiple systems. After restarting mopidy, the objects are back again, this is the object in the browser: http://pastebin.com/DW9t0mcD

    C-bug A-http 
    opened by woutervanwijk 43
  • Next track is loaded in currently playing track / Mopidy never changes track

    Next track is loaded in currently playing track / Mopidy never changes track

    I'm having an issue where the track never changes track. The next track just starts playing after the current track ends, but continues past the total time of the current track. Eventually, it realizes that the track it finished and just stops playing. This happens no matter what output or mixer I use. It might be hard to picture what I'm saying, so attached is a picture of what it looks like from ncmpcpp.

    Note: mopidy is currently playing the next track, Unsre Stärke heißt zu schwach, despite displaying the previous track, Verstummt!

    2016-06-13-141459_1146x63_scrot

    Unfortunately, I can't track down relevant data from the mopidy log. It seems to simply not realize that the track has changed, thus it does not log any change there.

    Note that I can manually change the track with mpc next etc. Also, if it reaches the end of the playlist while still displaying the first song selected, it will end normally with this in the log:

    DEBUG 2016-06-13 14:13:34,350 [29984:MpdSession-13] mopidy.mpd.session Request from [::ffff:50.76.48.109]:5684: idle

    Version: Mopidy 2.0.0

    Extensions tested:

    • Mopidy-GMusic (1.0.0)
    • Mopidy-SoundCloud (2.0.2)
    • Mopidy-Youtube (2.0.2)

    Edit: It eventually gets to this:

    DEBUG    2016-06-13 14:47:26,482 [29984:MpdSession-18] mopidy.mpd.session
      Request from [::ffff:50.76.48.109]:25131: status
    DEBUG    2016-06-13 14:47:26,486 [29984:MpdSession-18] mopidy.mpd.session
      Response to [::ffff:50.76.48.109]:25131: 
        volume: 100
        repeat: 0
        random: 0
        single: 0
        consume: 0
        playlist: 7
        playlistlength: 4
        xfade: 0
        state: play
        song: 0
        songid: 3
        time: 523:215
        elapsed: 523.607
        bitrate: 320
        OK
    DEBUG    2016-06-13 14:47:26,582 [29984:MainThread] mopidy.audio.gst
      Got TAG bus message: tags={'audio-codec': [u'MPEG-1 Layer 3 (MP3)'], 'bitrate': [320000], 'has-crc': [False], 'channel-mode': [u'stereo']}
    DEBUG    2016-06-13 14:47:26,584 [29984:MainThread] mopidy.audio.gst
      Got TAG bus message: tags={'audio-codec': [u'MPEG-1 Layer 3 (MP3)'], 'bitrate': [320000], 'channel-mode': [u'joint-stereo']}
    DEBUG    2016-06-13 14:47:26,620 [29984:MpdSession-18] mopidy.mpd.session
      Request from [::ffff:50.76.48.109]:25131: idle
    DEBUG    2016-06-13 14:47:26,791 [29984:MainThread] mopidy.audio.gst
      Got TAG bus message: tags={'audio-codec': [u'MPEG-1 Layer 3 (MP3)'], 'minimum-bitrate': [320031], 'bitrate': [320000], 'maximum-bitrate': [320031], 'channel-mode': [u'joint-stereo']}
    DEBUG    2016-06-13 14:47:26,843 [29984:MainThread] mopidy.audio.gst
      Got TAG bus message: tags={'audio-codec': [u'MPEG-1 Layer 3 (MP3)'], 'minimum-bitrate': [319725], 'bitrate': [320000], 'maximum-bitrate': [320031], 'channel-mode': [u'joint-stereo']}
    DEBUG    2016-06-13 14:47:27,624 [29984:MpdSession-18] mopidy.mpd.session
      Request from [::ffff:50.76.48.109]:25131: noidle
    DEBUG    2016-06-13 14:47:27,627 [29984:MpdSession-18] mopidy.mpd.session
      Response to [::ffff:50.76.48.109]:25131: OK
    DEBUG    2016-06-13 14:47:27,755 [29984:MpdSession-18] mopidy.mpd.session
      Request from [::ffff:50.76.48.109]:25131: status
    DEBUG    2016-06-13 14:47:27,759 [29984:MpdSession-18] mopidy.mpd.session
      Response to [::ffff:50.76.48.109]:25131: 
        volume: 100
        repeat: 0
        random: 0
        single: 0
        consume: 0
        playlist: 7
        playlistlength: 4
        xfade: 0
        state: play
        song: 0
        songid: 3
        time: 2:215
        elapsed: 2.194
        bitrate: 320
        OK
    

    where the song that it started playing initially just restarts.

    C-bug A-core 
    opened by jludwig 39
  • Apparent memory leak during normal MP3 playback

    Apparent memory leak during normal MP3 playback

    I have what appears to be a memory leak on a Mopidy installation on a RasPi, booting and running over NFS. Initially I thought the problem was that I had no swap set up, so I added some, but it continues to happen.

    The extremely odd thing about this is that the NFS root image is identical to three other RasPi servers handling sound systems in other rooms of the house, but those other three systems have run for weeks without exhibiting any issues. The failing unit freezes up nearly once a day. The only difference among all four servers is the exact content of the music library, but all libraries are pretty small...less than 2k songs, far less in some cases. All songs are in MP3 format, in case it makes a difference.

    Here's a screenshot of top that I had left running to see the system state when it freezes. Note the insane load and 0k free swap, and the fact that kswapd is pegging the CPU, but also that mopidy is the one using all the memory. Normally the mopidy process is down around 5-6% mem usage.

    image

    I'm already using a local SQLite db. I can run a local scan from the command line with no issues.

    After the above screenshot, I power-cycled the RasPi and got back into a top session so I could pay more attention to it. The %MEM value reported has slowly crept upward from about 5% to 42%, where it is now. I expect it will continue to rise if I do nothing.

    In contrast, one of the stable RasPi audio servers has been running for over two weeks solid and playing audio for at least 72 hours without stopping, and the mopidy process is at 6.7% usage. It even has a slightly larger library.

    ...and after a while longer, the memory use did indeed continue to creep upwards (at 50% when I acted), and I ran sudo service mopidy force-reload as a test to see if that would help. It did--mopidy memory usage dropped down near zero for a moment, and then back to the expected ~5%. No full service restart needed, though I assume that also would have done the same.

    The different RasPis involved all report Raspberry Pi 3 Model B Rev 1.2 from the output of cat /sys/firmware/devicetree/base/model. They are running over NFS mounted root folders that are exact copies of each other, except for the hostname. The contents of /etc/mopidy/mopidy.conf are identical. The memory usage takes many hours to grow significantly, but it will eventually eat up all available RAM and swap space.

    I have confirmed as well that the memory use stops increasing when audio is stopped (not sure about paused though). The following set of graphs shows RAM and SWAP usage on the problem system over a 24-hour period, including two full PLAY-STOP cycles (hours long) with one final PLAY event at the end to confirm. I did another force-reload immediately after this to avoid a complete system freeze and drop RAM/swap usage back down to normal levels.

    image

    You can see how the RAM is eaten up first (from 50% to 80%) during the first cycle, then shortly after the second cycle starts, it eats the last bit of safe RAM (from 80% to 85%) and then switches to consuming swap (from 20% to 80%) until stopped. Finally, it ticks up again at a consistent rate about 15 minutes before the end of the graph, which is where I started playback again.

    Note, as far as I can tell, pausing playback in the Mopidy/moped web interface has the same effect as stopping it in this regard, i.e. it stops eating memory.

    Host platform is Raspbian on a RasPi 3B v1.2:

    Linux lucas-audio 4.19.66-v7+ #1253 SMP Thu Aug 15 11:49:46 BST 2019 armv7l GNU/Linux
    

    It is possible that this issue is related to either #1750 (most likely) or #1648 (less likely).

    C-bug A-audio 
    opened by jrowberg 37
  • ASX playlists are not correctly typefound

    ASX playlists are not correctly typefound

    For some radio stations the Tunein API provides a URL to a playlist file which needs to be downloaded and parsed in order to extract the actual stream URIs (e.g. http://www.bbc.co.uk/radio/listen/live/r2.asx). The code to do this already exists in https://github.com/mopidy/mopidy/tree/develop/mopidy/audio for scanning local playlists but I wanted to reuse this for these remote playlists. I know the stream extension just provides Scanner.scan() with a playable stream URI and it's happy, but I when I try to give it a remote playlist URI (like the BBC one above) it can't handle it. Unfortunately I don't have the exact exception message to hand.

    I don't understand what goes on inside gstreamer than doesn't differentiate between playing local and remote music files, but does have a problem with remote vs local playlist files. Why can't it just use the various playlist handlers that are registered?

    I could fetch the playlist data myself, wrap it in a file like object and give that to Scanner.scan() - similar to what the tests do - or call the parse_asx|pls|m3u functions directly. Failing that I could just duplicate the playlist parsing code in the extension but that's horrible. What's the best thing to do here?

    C-enhancement A-audio 
    opened by kingosticks 34
  • Early Python 2.6.x doesn't play nice with unicode_literals

    Early Python 2.6.x doesn't play nice with unicode_literals

    Mopidy won't start on my SLES11-SP2 (Python 2.6) and openSUSE 11.4 (Python 2.7) systems.

    When starting Mopidy, it fails with the following error:

    erik@faust:~$  mopidy
    Traceback (most recent call last):
      File "/usr/local/bin/mopidy", line 5, in <module>
        main()
      File "/usr/local/lib64/python2.6/site-packages/mopidy/__main__.py", line 48, in main
        options = parse_options()
      File "/usr/local/lib64/python2.6/site-packages/mopidy/__main__.py", line 85, in parse_options
        help='show GStreamer help options')
      File "/usr/lib64/python2.6/optparse.py", line 1012, in add_option
        raise TypeError, "invalid arguments"
    TypeError: invalid arguments
    erik@faust:~$  python --version
    Python 2.6
    erik@faust:~$  uname -a
    Linux faust 3.0.13-0.27-default #1 SMP Wed Feb 15 13:33:49 UTC 2012 (d73692b) x86_64 x86_64 x86_64 GNU/Linux
    erik@faust:~$  cat /etc/SuSE-release 
    SUSE Linux Enterprise Server 11 (x86_64)
    VERSION = 11
    PATCHLEVEL = 2
    erik@faust:~$  
    

    I believe it has something to do with unicode string handling, but I'm no Python expert, so I got stuck.

    C-bug 
    opened by edooper 34
  • [Solved] USB: Distorted Audio via gstreamer to alsa on Raspberry Pi

    [Solved] USB: Distorted Audio via gstreamer to alsa on Raspberry Pi

    Hello all,

    I've been playing with mopidy on my my Rpi. I am trying to play music from Spotify through mopidy via Alsa, while a squeezelite client is also active. Thus, I activated dmix from Alsa to enable simultaneous use of the USB DAC by more than one app. Pulseaudio was giving me all kinds of headaches in this combination.

    What I noticed is that squeezelite has not problems with Audio quality going through dmix, wherease mopidy produces crackling sounds and dropouts. squeezelite did the same thing until I adjusted the alsa buffer to 160ms. So basicallly my setup works, but the audio quality of mopidy is not so great.

    • Is there any method to specify an (alsa) buffer for the gstreamer pipeline?
    • Or can you sent to alsa directly without gstreamer?

    I suspect some problem along the mopidy-spotify -> gstreamer -> alsa -> dmix pipeline - possibly a too small buffer or up-sample problem.

    I'd like to avoid using pulseaudio because I couldn't get it to work in my setup. I have not tried jackd1, but I am not sure if squeezelite would play ball.

    A-audio 
    opened by Gymnae 33
  • "Segmentation fault" on startup on Raspberry Pi

    I installed the latest version of mopidy from git on a Rasbperry Pi (Debian Squeeze for ARM). Before, I installed the following dependencies:

    • Pykka 0.14 (via pip install pykka)
    • gstreamer 0.10 (via apt-get install ...)
    • libspotify 12.1.51 eabi-armv6t (downloaded from spotify and successfully built)
    • pyspotify 1.7 (latest from git)

    Then I installed Mopidy 0.7.2 (latest from git).

    When I start Mopidy I run into a segmentation fault:

    INFO     Starting Mopidy 0.7.2 on Linux-3.1.9+-armv6l-with-debian-6.0.4 CPython 2.6.6
    INFO     Mopidy uses SPOTIFY(R) CORE
    INFO     MPD server running at [127.0.0.1]:6600
    INFO     Disabled: mopidy.frontends.lastfm.LastfmFrontend (No module named pylast)
    INFO     Disabled: mopidy.frontends.mpris.MprisFrontend (No module named dbus)
    INFO     Connected to Spotify
    Segmentation fault
    

    What's going wrong here? Is it a general bug or something with the versions I use? The apt repo doesn't seem to work for Debian/ARM.

    opened by ghost 33
  • Mopidy segfaults when switching tracks on Arch Linux

    Mopidy segfaults when switching tracks on Arch Linux

    I tried to use gdb to find out the cause, and it said:

    Program received signal SIGSEGV, Segmentation fault.
    0x00007f5e56cae4d5 in g_mutex_lock () from /usr/lib/libglib-2.0.so.0
    
    C-bug 
    opened by aereaux 32
  • Support for a

    Support for a "forced refresh" option for playlists

    Since fetching playlists from a remote backend can be an expensive operation, several mopidy extensions (e.g. mopidy-spotify and mopidy-tidal) implement some form of caching as a trade-off.

    mopidy-spotify loads playlist contents only at startup: it slows down mopidy's startup, but it makes sure that loading playlists later is snappy, even if that comes at the cost of losing playlist updates until the app is restarted.

    mopidy-tidal, on the other hand, performs a "lazy initialization" - it loads the playlists from upstream only when core.playlists.as_list is called the first time. It can also be configured with a time-based setting for expiring the cached playlists, so users can tune it to find their own trade-off between playlists "freshness" and performance.

    I think that things could be simplified a lot on the extensions side (and the user experience would also benefit from it) if the core could simply allow a client to pass something like a force_refresh=True flag to core.playlists.as_list, or a separate core.playlists.refresh method. It may break the mpd compatibility, but mpd AFAIK doesn't support the concept of playlists caching anyways.

    Extensions that perform caching of playlists could then react separately on those requests to invalidate their caches, while other backends would simply ignore them.

    Clients like Iris could then be used by users to manually trigger a refresh when they know that some playlists have been updated and they want to sync those changes. Right now Iris provides a "Refresh" button in the Playlists menu, but that simply calls core.playlists.as_list, which doesn't really have any effect on backends that perform caching.

    opened by BlackLight 1
  • support for live soundcard switch

    support for live soundcard switch

    Hi, It would be great to have (like mpd), support of multiple soundcard and switch in live with mpd client or http interface... We are lot of people using multiple dacs, use bitperfect to play directly on this dacs. Switch from one to another actually request to have multiple mopidy instance (or sed + restart). Thx

    opened by metasystem 0
  • Mopidy web server stops responding after visiting youtube playlist

    Mopidy web server stops responding after visiting youtube playlist

    Describe the bug Mopidy web server stops responding completely after visiting youtube playlist

    How to reproduce Visit youtube videos playlist

    Expected behaviour Expected to survive

    Environment Please complete the following information:

    • Operating system (e.g. Raspberry Pi OS Buster)
    • Running Mopidy as a service
    • Your config (output of sudo mopidyctl config)
    sudo mopidyctl config
    Running "/usr/bin/mopidy --config /usr/share/mopidy/conf.d:/etc/mopidy/mopidy.conf config" as user mopidy
    [core]
    cache_dir = /var/cache/mopidy
    config_dir = /etc/mopidy
    data_dir = /var/lib/mopidy
    max_tracklist_length = 10000
    restore_state = false
    
    [logging]
    verbosity = 0
    format = %(levelname)-8s [%(threadName)s] %(name)s %(message)s
    color = false
    config_file = 
    
    [audio]
    mixer = software
    mixer_volume = 100
    output = pulsesink server=127.0.0.1
    buffer_time = 
    
    [proxy]
    scheme = 
    hostname = 
    port = 
    username = 
    password = 
    
    [ytmusic]
    enabled = false  ; Extension disabled by self check.
    
    [youtube]
    enabled = true
    allow_cache = 
    youtube_api_key = 
    search_results = 15
    playlist_max_videos = 20
    api_enabled = false
    channel_id = 
    musicapi_enabled = false
    musicapi_cookie = 
    autoplay_enabled = false
    strict_autoplay = false
    max_autoplay_length = 600
    max_degrees_of_separation = 3
    youtube_dl_package = yt_dlp
    
    [soundcloud]
    enabled = false  ; Extension disabled due to config errors.
    explore_songs = 25
    auth_token =   ; Must be set.
    
    [pandora]
    enabled = false  ; Extension disabled due to config errors.
    api_host = tuner.pandora.com/services/json/
    partner_encryption_key =   ; Must be set.
    partner_decryption_key =   ; Must be set.
    partner_username = android
    partner_password =   ; Must be set.
    partner_device = android-generic
    username =   ; Must be set.
    password =   ; Must be set.
    preferred_audio_quality = highQuality
    sort_order = a-z
    auto_setup = true
    cache_time_to_live = 86400
    event_support_enabled = false
    double_click_interval = 2.50
    on_pause_resume_click = thumbs_up
    on_pause_next_click = thumbs_down
    on_pause_previous_click = sleep
    on_pause_resume_pause_click = delete_station
    
    [musicbox_webclient]
    enabled = true
    musicbox = false
    websocket_host = 
    websocket_port = 
    on_track_click = PLAY_ALL
    
    [iris]
    enabled = true
    country = NZ
    locale = en_NZ
    verify_certificates = true
    snapcast_enabled = true
    snapcast_host = localhost
    snapcast_port = 1780
    snapcast_ssl = false
    snapcast_stream = Default
    spotify_authorization_url = https://jamesbarnsley.co.nz/iris/auth_spotify.php
    lastfm_authorization_url = https://jamesbarnsley.co.nz/iris/auth_lastfm.php
    genius_authorization_url = https://jamesbarnsley.co.nz/iris/auth_genius.php
    data_dir = $XDG_DATA_DIR/iris
    
    [file]
    enabled = true
    media_dirs = 
      $XDG_MUSIC_DIR|Music
      ~/|Home
    excluded_file_extensions = 
      .directory
      .html
      .jpeg
      .jpg
      .log
      .nfo
      .pdf
      .png
      .txt
      .zip
    show_dotfiles = false
    follow_symlinks = false
    metadata_timeout = 1000
    
    [http]
    enabled = true
    hostname = ::
    port = 6680
    zeroconf = Mopidy HTTP server on $hostname
    allowed_origins = 
    csrf_protection = true
    default_app = mopidy
    
    [m3u]
    enabled = true
    base_dir = 
    default_encoding = latin-1
    default_extension = .m3u8
    playlists_dir = 
    
    [softwaremixer]
    enabled = true
    
    [stream]
    enabled = true
    protocols = 
      http
      https
      mms
      rtmp
      rtmps
      rtsp
    metadata_blacklist = 
    timeout = 5000
    
    [tunein]
    enabled = true
    timeout = 5000
    filter = 
    
    [mpd]
    enabled = true
    hostname = ::
    port = 6600
    password = 
    max_connections = 20
    connection_timeout = 60
    zeroconf = Mopidy MPD server on $hostname
    command_blacklist = 
      listall
      listallinfo
    default_playlist_scheme = m3u
    
    
    • Software versions (output of sudo mopidyctl deps)
    
    sudo mopidyctl deps
    Running "/usr/bin/mopidy --config /usr/share/mopidy/conf.d:/etc/mopidy/mopidy.conf deps" as user mopidy
    Executable: /usr/bin/mopidy
    Platform: Linux-5.10.103-v8+-aarch64-with-debian-10.12
    Python: CPython 3.7.3 from /usr/lib/python3.7
    Mopidy: 3.3.0 from /usr/lib/python3/dist-packages
    Mopidy-TuneIn: 1.1.0 from /usr/lib/python3/dist-packages
    Mopidy-MusicBox-Webclient: 3.1.0 from /usr/local/lib/python3.7/dist-packages
      setuptools: 40.8.0 from /usr/lib/python3/dist-packages
      Mopidy: 3.3.0 from /usr/lib/python3/dist-packages
      Pykka: 2.0.3 from /usr/lib/python3/dist-packages
    Mopidy-MPD: 3.3.0 from /usr/lib/python3/dist-packages
    Mopidy-Pandora: 1.1.1 from /usr/local/lib/python3.7/dist-packages
      pydora: 2.1.1 from /usr/local/lib/python3.7/dist-packages
        blowfish: 0.6.1 from /usr/local/lib/python3.7/dist-packages
        requests: 2.28.0 from /usr/local/lib/python3.7/dist-packages
          idna: 2.6 from /usr/lib/python3/dist-packages
          charset-normalizer: 2.0.12 from /usr/local/lib/python3.7/dist-packages
          urllib3: 1.24.1 from /usr/lib/python3/dist-packages
          certifi: 2018.8.24 from /usr/lib/python3/dist-packages
      cachetools: 5.2.0 from /usr/local/lib/python3.7/dist-packages
      setuptools: 40.8.0 from /usr/lib/python3/dist-packages
      requests: 2.28.0 from /usr/local/lib/python3.7/dist-packages
        idna: 2.6 from /usr/lib/python3/dist-packages
        charset-normalizer: 2.0.12 from /usr/local/lib/python3.7/dist-packages
        urllib3: 1.24.1 from /usr/lib/python3/dist-packages
        certifi: 2018.8.24 from /usr/lib/python3/dist-packages
      Mopidy: 3.3.0 from /usr/lib/python3/dist-packages
      Pykka: 2.0.3 from /usr/lib/python3/dist-packages
    Mopidy-Iris: 3.64.0 from /usr/local/lib/python3.7/dist-packages
      setuptools: 40.8.0 from /usr/lib/python3/dist-packages
      Mopidy: 3.3.0 from /usr/lib/python3/dist-packages
      Pykka: 2.0.3 from /usr/lib/python3/dist-packages
    Mopidy-YouTube: 3.5 from /usr/local/lib/python3.7/dist-packages
      requests: 2.28.0 from /usr/local/lib/python3.7/dist-packages
        idna: 2.6 from /usr/lib/python3/dist-packages
        charset-normalizer: 2.0.12 from /usr/local/lib/python3.7/dist-packages
        urllib3: 1.24.1 from /usr/lib/python3/dist-packages
        certifi: 2018.8.24 from /usr/lib/python3/dist-packages
      cachetools: 5.2.0 from /usr/local/lib/python3.7/dist-packages
      beautifulsoup4: 4.11.1 from /usr/local/lib/python3.7/dist-packages
        soupsieve: 2.3.2.post1 from /usr/local/lib/python3.7/dist-packages
      Mopidy: 3.3.0 from /usr/lib/python3/dist-packages
      setuptools: 40.8.0 from /usr/lib/python3/dist-packages
      Pykka: 2.0.3 from /usr/lib/python3/dist-packages
    mopidy-ytmusic: 0.3.5 from /usr/local/lib/python3.7/dist-packages
      ytmusicapi: 0.19.2 from /usr/local/lib/python3.7/dist-packages
        requests: 2.28.0 from /usr/local/lib/python3.7/dist-packages
          idna: 2.6 from /usr/lib/python3/dist-packages
          charset-normalizer: 2.0.12 from /usr/local/lib/python3.7/dist-packages
          urllib3: 1.24.1 from /usr/lib/python3/dist-packages
          certifi: 2018.8.24 from /usr/lib/python3/dist-packages
      Mopidy: 3.3.0 from /usr/lib/python3/dist-packages
      pytube: 12.1.0 from /usr/local/lib/python3.7/dist-packages
    Mopidy-SoundCloud: 3.0.1 from /usr/local/lib/python3.7/dist-packages
      setuptools: 40.8.0 from /usr/lib/python3/dist-packages
      requests: 2.28.0 from /usr/local/lib/python3.7/dist-packages
        idna: 2.6 from /usr/lib/python3/dist-packages
        charset-normalizer: 2.0.12 from /usr/local/lib/python3.7/dist-packages
        urllib3: 1.24.1 from /usr/lib/python3/dist-packages
        certifi: 2018.8.24 from /usr/lib/python3/dist-packages
      Mopidy: 3.3.0 from /usr/lib/python3/dist-packages
      Pykka: 2.0.3 from /usr/lib/python3/dist-packages
    GStreamer: 1.14.4.0 from /usr/lib/python3/dist-packages/gi
      Detailed information: 
        Python wrapper: python-gi 3.30.4
        Relevant elements:
          Found:
            uridecodebin
            souphttpsrc
            appsrc
            alsasink
            osssink
            oss4sink
            pulsesink
            id3demux
            id3v2mux
            lamemp3enc
            mpegaudioparse
            mpg123audiodec
            vorbisdec
            vorbisenc
            vorbisparse
            oggdemux
            oggmux
            oggparse
            flacdec
            flacparse
            shout2send
          Not found:
            flump3dec
            mad
    
    
    
    • Any specific hardware (e.g. an exotic USB soundcard)

    Additional context

    Error:

    Started getting mopidy_youtube list_videos error ""

    status:

    
    Jul 09 15:04:54 lysmarine sh[3599]: INFO     [YouTubeBackend-3] mopidy_youtube file caching not enabled
    Jul 09 15:04:54 lysmarine sh[3599]: INFO     [YouTubeBackend-3] mopidy_youtube using jAPI
    Jul 09 15:04:54 lysmarine sh[3599]: INFO     [Audio-2] mopidy.audio.actor Audio output set to "pulsesink server=127.0.0.1"
    Jul 09 15:04:54 lysmarine sh[3599]: INFO     [MainThread] mopidy.commands Starting Mopidy core
    Jul 09 15:04:54 lysmarine sh[3599]: INFO     [MainThread] mopidy.commands Starting Mopidy frontends: YouTubeAutoplayer, YouTub
    Jul 09 15:04:54 lysmarine sh[3599]: INFO     [IrisFrontend-11] mopidy_iris.core Starting Iris 3.64.0
    Jul 09 15:04:54 lysmarine sh[3599]: INFO     [HttpFrontend-13] mopidy.http.actor HTTP server running at [::]:6680
    Jul 09 15:04:54 lysmarine sh[3599]: INFO     [MainThread] mopidy_mpd.actor MPD server running at [::]:6600
    Jul 09 15:04:54 lysmarine sh[3599]: INFO     [MainThread] mopidy.commands Starting GLib mainloop
    Jul 09 15:05:32 lysmarine sh[3599]: ERROR    [ThreadPoolExecutor-1_0] mopidy_youtube list_videos error ""
    
    
    opened by mgrouch 2
  • Improve handling of

    Improve handling of "media_dirs" file extension config

    This moves almost all of the processing for the media_dirs file setting into the config system, with the aim of making it more robust while also resolving some bugs. The only thing left for the file library backend to do manually now is verify that the input directories actually exist as folders.

    The main bug this solves is an issue of whitespace handling around paths, as detailed in #1965.

    To make this possible, the Path config type has been altered to return pathlib objects rather than strings.

    opened by djmattyg007 3
  • mopidy does not release occupied memory

    mopidy does not release occupied memory

    After mopidy adds and plays mp3, deletes the corresponding playlist and calls the clear instruction through the client, and the memory occupied by mopidy will not be released。

    How to release the memory occupied by mopidy? image

    root@uranus:/home/ubuntu# mopidy deps Executable: /usr/bin/mopidy Platform: Linux-4.14.98-aarch64-with-glibc2.29 Python: CPython 3.8.10 from /usr/lib/python3.8 Mopidy: 3.0.1 from /usr/lib/python3/dist-packages Mopidy-MPD: 3.2.0 from /usr/local/lib/python3.8/dist-packages Mopidy: 3.0.1 from /usr/lib/python3/dist-packages Pykka: 2.0.2 from /usr/lib/python3/dist-packages setuptools: 45.2.0 from /usr/lib/python3/dist-packages Mopidy-Iris: 3.62.0 from /usr/local/lib/python3.8/dist-packages Mopidy: 3.0.1 from /usr/lib/python3/dist-packages Pykka: 2.0.2 from /usr/lib/python3/dist-packages setuptools: 45.2.0 from /usr/lib/python3/dist-packages Mopidy-Local: 3.2.1 from /usr/local/lib/python3.8/dist-packages Mopidy: 3.0.1 from /usr/lib/python3/dist-packages Pykka: 2.0.2 from /usr/lib/python3/dist-packages setuptools: 45.2.0 from /usr/lib/python3/dist-packages uritools: 4.0.0 from /usr/local/lib/python3.8/dist-packages GStreamer: 1.16.2.0 from /usr/lib/python3/dist-packages/gi Detailed information: Python wrapper: python-gi 3.36.0 Relevant elements: Found: uridecodebin souphttpsrc appsrc alsasink osssink oss4sink pulsesink id3demux id3v2mux lamemp3enc mpegaudioparse mpg123audiodec vorbisdec vorbisenc vorbisparse oggdemux oggmux oggparse flacdec flacparse shout2send Not found: flump3dec mad

    root@uranus:/home/ubuntu# mopidy config [core] cache_dir = $XDG_CACHE_DIR/mopidy config_dir = $XDG_CONFIG_DIR/mopidy data_dir = $XDG_DATA_DIR/mopidy max_tracklist_length = 10000 restore_state = false

    [logging] verbosity = 0 format = %(levelname)-8s %(asctime)s [%(process)d:%(threadName)s] %(name)s\n %(message)s color = true config_file =

    [audio] mixer = software mixer_volume = output = autoaudiosink buffer_time =

    [proxy] scheme = hostname = port = username = password =

    [mpd] enabled = true hostname = 127.0.0.1 port = 6600 password = max_connections = 20 connection_timeout = 60 zeroconf = Mopidy MPD server on $hostname command_blacklist = listall listallinfo default_playlist_scheme = m3u

    [local] enabled = false ; Extension disabled due to config errors. max_search_results = 100 media_dir = ; Must be set. scan_timeout = 1000 scan_flush_threshold = 100 scan_follow_symlinks = false included_file_extensions = excluded_file_extensions = .cue .directory .html .jpeg .jpg .log .nfo .pdf .png .txt .zip directories = Albums local:directory?type=album Artists local:directory?type=artist Composers local:directory?type=artist&role=composer Genres local:directory?type=genre Performers local:directory?type=artist&role=performer Release Years local:directory?type=date&format=%25Y Tracks local:directory?type=track Last Week's Updates local:directory?max-age=604800 Last Month's Updates local:directory?max-age=2592000 timeout = 10 use_artist_sortname = false album_art_files = *.jpg *.jpeg *.png

    [iris] enabled = true country = NZ locale = en_NZ verify_certificates = true snapcast_enabled = true snapcast_host = localhost snapcast_port = 1780 snapcast_ssl = false snapcast_stream = Default spotify_authorization_url = https://jamesbarnsley.co.nz/iris/auth_spotify.php lastfm_authorization_url = https://jamesbarnsley.co.nz/iris/auth_lastfm.php genius_authorization_url = https://jamesbarnsley.co.nz/iris/auth_genius.php data_dir = $XDG_DATA_DIR/iris

    [file] enabled = true media_dirs = $XDG_MUSIC_DIR|Music ~/|Home excluded_file_extensions = .directory .html .jpeg .jpg .log .nfo .pdf .png .txt .zip show_dotfiles = false follow_symlinks = false metadata_timeout = 1000

    [http] enabled = true hostname = 127.0.0.1 port = 6680 zeroconf = Mopidy HTTP server on $hostname allowed_origins = csrf_protection = true default_app = mopidy

    [m3u] enabled = true base_dir = default_encoding = latin-1 default_extension = .m3u8 playlists_dir =

    [softwaremixer] enabled = true

    [stream] enabled = true protocols = http https mms rtmp rtmps rtsp metadata_blacklist = timeout = 5000

    opened by yfj86912 5
Releases(v3.4.1)
  • v3.4.1(Dec 7, 2022)

  • v3.4.0(Nov 28, 2022)

  • v3.3.0(Apr 28, 2022)

  • v3.2.0(Jul 8, 2021)

  • v3.1.1(Dec 26, 2020)

  • v3.1.0(Dec 15, 2020)

  • v3.0.2(Jun 18, 2020)

  • v0.19.3(Aug 13, 2014)

    Bug fix release.

    • Audio: Fix negative track length for radio streams. (Fixes: #662, PR: #796)
    • Audio: Tell GStreamer to not pick Jack sink. (Fixes: #604)
    • Zeroconf: Fix discovery by adding .local to the announced hostname. (PR: #795)
    • Zeroconf: Fix intermittent DBus/Avahi exception.
    • Extensions: Fail early if trying to setup an extension which doesn’t implement the mopidy.ext.Extension.setup() method. (Fixes: #813)
    Source code(tar.gz)
    Source code(zip)
  • v0.19.2(Aug 13, 2014)

    Bug fix release, directly from the Mopidy development sprint at EuroPython 2014 in Berlin.

    • Audio: Make audio/mixer_volume work on the software mixer again. This was broken with the mixer changes in 0.19.0. (Fixes: #791)
    • HTTP frontend: When using Tornado 4.0, allow WebSocket requests from other hosts. (Fixes: #788)
    • MPD frontend: Fix crash when MPD commands are called with the wrong number of arguments. This was broken with the MPD command changes in 0.19.0. (Fixes: #789)
    Source code(tar.gz)
    Source code(zip)
  • v0.19.1(Aug 13, 2014)

    Bug fix release.

    • Dependencies: Mopidy now requires Tornado >= 2.3, instead of >= 3.1. This should make Mopidy continue to work on Debian/Raspbian stable, where Tornado 2.3 is the newest version available.
    • HTTP frontend: Add missing string interpolation placeholder.
    • Development: mopidy --version and mopidy.core.Core.get_version() now returns the correct version when Mopidy is run from a Git repo other than Mopidy’s own. (Related to #706)
    Source code(tar.gz)
    Source code(zip)
  • v0.19.0(Jul 21, 2014)

    The focus of 0.19 have been on improving the MPD implementation, replacing GStreamer mixers with our own mixer API, and on making web clients installable with pip, like any other Mopidy extension.

    Since the release of 0.18, we’ve closed or merged 53 issues and pull requests through about 445 commits by 12 people, including five new guys. Thanks to everyone that has contributed!

    Dependencies

    • Mopidy now requires Tornado >= 3.1.
    • Mopidy no longer requires CherryPy or ws4py. Previously, these were optional dependencies required for the HTTP frontend to work.

    Backend API

    • Breaking change: Imports of the backend API from mopidy.backends no longer works. The new API introuced in v0.18 is now required. Most extensions already use the new API location.

    Commands

    • The mopidy-convert-config tool for migrating the setings.py configuration file used by Mopidy up until 0.14 to the new config file format has been removed after over a year of trusty service. If you still need to convert your old settings.py configuration file, do so using and older release, like Mopidy 0.18, or migrate the configuration to the new format by hand.

    Configuration

    • Add optional=True support to mopidy.config.Boolean.

    Logging

    • Fix proper decoding of exception messages that depends on the user’s locale.
    • Colorize logs depending on log level. This can be turned off with the new logging/color configuration. (Fixes: #772)

    Extension support

    • Breaking change: Removed the Extension methods that were deprecated in 0.18: get_backend_classes(), get_frontend_classes(), and register_gstreamer_elements(). Use mopidy.ext.Extension.setup() instead, as most extensions already do.

    Audio

    • Breaking change: Removed support for GStreamer mixers. GStreamer 1.x does not support volume control, so we changed to use software mixing by default in v0.17.0. Now, we’re removing support for all other GStreamer mixers and are reintroducing mixers as something extensions can provide independently of GStreamer. (Fixes: #665, PR: #760)
    • Breaking change: Changed the audio/mixer config value to refer to Mopidy mixer extensions instead of GStreamer mixers. The default value, software, still has the same behavior. All other values will either no longer work or will at the very least require you to install an additional extension.
    • Changed the audio/mixer_volume config value behavior from affecting GStreamer mixers to affecting Mopidy mixer extensions instead. The end result should be the same without any changes to this config value.
    • Deprecated the audio/mixer_track config value. This config value is no longer in use. Mixer extensions that need additional configuration handle this themselves.
    • Use Proxy configuration when streaming media from the Internet. (Partly fixing #390)
    • Fix proper decoding of exception messages that depends on the user’s locale.
    • Fix recognition of ASX and XSPF playlists with tags in all caps or with carriage return line endings. (Fixes: #687)
    • Support simpler ASX playlist variant with elements without children.
    • Added target_state attribute to the audio layer’s state_changed() event. Currently, it is None except when we’re paused because of buffering. Then the new field exposes our target state after buffering has completed.

    Mixers

    • Added new mopidy.mixer.Mixer API which can be implemented by extensions.
    • Created a bundled extension, Mopidy-SoftwareMixer, for controlling volume in software in GStreamer’s pipeline. This is Mopidy’s default mixer. To use this mixer, set the audio/mixer config value to software.
    • Created an external extension, Mopidy-ALSAMixer, for controlling volume with hardware through ALSA. To use this mixer, install the extension, and set the audio/mixer config value to alsamixer.

    HTTP frontend

    • CherryPy and ws4py have been replaced with Tornado. This will hopefully reduce CPU usage on OS X (#445) and improve error handling in corner cases, like when returning from suspend (#718).
    • Added support for packaging web clients as Mopidy extensions and installing them using pip. See the HTTP server side API for details. (Fixes: #440)
    • Added web page at /mopidy/ which lists all web clients installed as Mopidy extensions. (Fixes: #440)
    • Added support for extending the HTTP frontend with additional server side functionality. See HTTP server side API for details.
    • Exposed the core API using HTTP POST requests with JSON-RPC payloads at /mopidy/rpc. This is the same JSON-RPC interface as is exposed over the WebSocket at /mopidy/ws, so you can run any core API command.
    • The HTTP POST interfaces does not give you access to events from Mopidy, like the WebSocket does. The WebSocket interface is still recommended for web clients. The HTTP POST interface may be easier to use for simpler programs, that just needs to query the currently playing track or similar. See HTTP POST API for details.
    • If Zeroconf is enabled, we now announce the _mopidy-http._tcp service in addition to _http._tcp. This is to make it easier to automatically find Mopidy’s HTTP server among other Zeroconf-published HTTP servers on the local network.

    Mopidy.js client library

    This version has been released to npm as Mopidy.js v0.4.0.

    • Update Mopidy.js to use when.js 3. If you maintain a Mopidy client, you should review the differences between when.js 2 and 3 and the when.js debugging guide.
    • All of Mopidy.js’ promise rejection values are now of the Error type. This ensures that all JavaScript VMs will show a useful stack trace if a rejected promise’s value is used to throw an exception. To allow catch clauses to handle different errors differently, server side errors are of the type Mopidy.ServerError, and connection related errors are of the type Mopidy.ConnectionError.
    • Add support for method calls with by-name arguments. The old calling convention, by-position-only, is still the default, but this will change in the future. A warning is logged to the console if you don’t explicitly select a calling convention. See the Mopidy.js JavaScript library docs for details.

    MPD frontend

    • Proper command tokenization for MPD requests. This replaces the old regex based system with an MPD protocol specific tokenizer responsible for breaking requests into pieces before the handlers have at them. (Fixes: #591 and #592)
    • Updated command handler system. As part of the tokenizer cleanup we’ve updated how commands are registered and making it simpler to create new handlers.
    • Simplified a bunch of handlers. All the “browse” type commands now use a common browse helper under the hood for less repetition. Likewise the query handling of “search” commands has been somewhat simplified.
    • Adds placeholders for missing MPD commands, preparing the way for bumping the protocol version once they have been added.
    • Respond to all pending requests before closing connection. (PR: #722)
    • Stop incorrectly catching LookupError in command handling. (Fixes: #741)
    • Browse support for playlists and albums has been added. (PR: #749, #754)
    • The lsinfo command now returns browse results before local playlists. This is helpful as not all clients sort the returned items. (PR: #755)
    • Browse now supports different entries with identical names. (PR: #762)
    • Search terms that are empty or consists of only whitespace are no longer included in the search query sent to backends. (PR: #758)

    Local backend

    • The JSON local library backend now logs a friendly message telling you about mopidy local scan if you don’t have a local library cache. (Fixes: #711)
    • The local scan command now use multiple threads to walk the file system and check files’ modification time. This speeds up scanning, escpecially when scanning remote file systems over e.g. NFS. the local scan command now creates necessary folders if they don’t already exist. Previously, this was only done by the Mopidy server, so doing a local scan before running the server the first time resulted in a crash. (Fixes: #703)
    • Fix proper decoding of exception messages that depends on the user’s locale.

    Stream backend

    • Add config value stream/metadata_blacklist to blacklist certain URIs we should not open to read metadata from before they are opened for playback. This is typically needed for services that invalidate URIs after a single use. (Fixes: #660)
    Source code(tar.gz)
    Source code(zip)
  • v0.18.3(May 7, 2014)

  • v0.18.2(May 7, 2014)

    Bug fix release.

    • We now log warnings for wrongly configured extensions, and clearly label them in mopidy config, but does no longer stop Mopidy from starting because of misconfigured extensions. (Fixes: #682)
    • Fix a crash in the server side WebSocket handler caused by connection problems with clients. (Fixes: #428, #571)
    • Fix the time_position field of the track_playback_ended event, which has been always 0 since v0.18.0. This made scrobbles by Mopidy-Scrobbler not be persisted by Last.fm, because Mopidy reported that you listened to 0 seconds of each track. (Fixes: #674)
    • Fix the log setup so that it is possible to increase the amount of logging from a specific logger using the loglevels config section. (Fixes: #684)
    • Serialization of Playlist models with the last_modified field set to a datetime.datetime instance did not work. The type of mopidy.models.Playlist.last_modified has been redefined from a datetime.datetime instance to the number of milliseconds since Unix epoch as an integer. This makes serialization of the time stamp simpler.
    • Minor refactor of the MPD server context so that Mopidy’s MPD protocol implementation can easier be reused. (Fixes: #646)
    • Network and signal handling has been updated to play nice on Windows systems.
    Source code(tar.gz)
    Source code(zip)
  • v0.18.1(May 7, 2014)

    Bug fix release.

    • Disable extension instead of crashing if a dependency has the wrong version. (Fixes: #657)
    • Make logging work to both console, debug log file, and any custom logging setup from logging/config_file at the same time. (Fixes: #661)
    Source code(tar.gz)
    Source code(zip)
  • v0.18.0(May 7, 2014)

    The focus of 0.18 have been on two fronts: the local library and browsing.

    First, the local library’s old tag cache file used for storing the track metadata scanned from your music collection has been replaced with a far simpler implementation using JSON as the storage format. At the same time, the local library have been made replaceable by extensions, so you can now create extensions that use your favorite database to store the metadata.

    Second, we’ve finally implemented the long awaited “file system” browsing feature that you know from MPD. It is supported by both the MPD frontend and the local and Spotify backends. It is also used by the new Mopidy-Dirble extension to provide you with a directory of Internet radio stations from all over the world.

    Since the release of 0.17, we’ve closed or merged 49 issues and pull requests through about 285 commits by 11 people, including six new guys. Thanks to everyone that has contributed!

    Core API

    • Add mopidy.core.Core.version() for HTTP clients to manage compatibility between API versions. (Fixes: #597)
    • Add mopidy.models.Ref class for use as a lightweight reference to other model types, containing just an URI, a name, and an object type. It is barely used for now, but its use will be extended over time.
    • Add mopidy.core.LibraryController.browse() method for browsing a virtual file system of tracks. Backends can implement support for this by implementing mopidy.backend.LibraryProvider.browse().
    • Events emitted on play/stop, pause/resume, next/previous and on end of track has been cleaned up to work consistently. See the message of commit 1d108752f64fc31ba96e75b415cda5ffb7a23df8 for the full details. (Fixes: #629)

    Backend API

    • Move the backend API classes from mopidy.backends.base to mopidy.backend and remove the Base prefix from the class names:
      • From mopidy.backends.base.Backend to mopidy.backend.Backend
      • From mopidy.backends.base.BaseLibraryProvider to mopidy.backend.LibraryProvider
      • From mopidy.backends.base.BasePlaybackProvider to mopidy.backend.PlaybackProvider
      • From mopidy.backends.base.BasePlaylistsProvider to mopidy.backend.PlaylistsProvider
      • From mopidy.backends.listener.BackendListener to mopidy.backend.BackendListener
      • Imports from the old locations still works, but are deprecated.
    • Add mopidy.backend.LibraryProvider.browse(), which can be implemented by backends that wants to expose directories of tracks in Mopidy’s virtual file system.

    Frontend API

    • The dummy backend used for testing many frontends have moved from mopidy.backends.dummy to mopidy.backend.dummy.

    Commands

    • Reduce amount of logging from dependencies when using mopidy -v. (Fixes: #593)
    • Add support for additional logging verbosity levels with mopidy -vv and mopidy -vvv which increases the amount of logging from dependencies. (Fixes: #593)

    Configuration

    • The default for the mopidy --config option has been updated to include $XDG_CONFIG_DIRS in addition to $XDG_CONFIG_DIR. (Fixes #431)
    • Added support for deprecating config values in order to allow for graceful removal of the no longer used config value local/tag_cache_file.

    Extension support

    • Switched to using a registry model for classes provided by extension. This allows extensions to be extended by other extensions, as needed by for example pluggable libraries for the local backend. See mopidy.ext.Registry for details. (Fixes #601)
    • Added the new method mopidy.ext.Extension.setup(). This method replaces the now deprecated get_backend_classes(), get_frontend_classes(), and register_gstreamer_elements().

    Audio

    • Added audio/mixer_volume to set the initial volume of mixers. This is especially useful for setting the software mixer volume to something else than the default 100%. (Fixes: #633)

    Local backend

    Note: After upgrading to Mopidy 0.18 you must run mopidy local scan to reindex your local music collection. This is due to the change of storage format.

    • Added support for browsing local directories in Mopidy’s virtual file system.
    • Finished the work on creating pluggable libraries. Users can now reconfigure Mopidy to use alternate library providers of their choosing for local files. (Fixes issue #44, partially resolves #397, and causes a temporary regression of #527.)
    • Switched default local library provider from a “tag cache” file that closely resembled the one used by the original MPD server to a compressed JSON file. This greatly simplifies our library code and reuses our existing model serialization code, as used by the HTTP API and web clients.
    • Removed our outdated and bug-ridden “tag cache” local library implementation.
    • Added the config value local/library to select which library to use. It defaults to json, which is the only local library bundled with Mopidy.
    • Added the config value local/data_dir to have a common config for where to store local library data. This is intended to avoid every single local library provider having to have it’s own config value for this.
    • Added the config value local/scan_flush_threshold to control how often to tell local libraries to store changes when scanning local music.

    Streaming backend

    • Add live lookup of URI metadata. (Fixes #540)
    • Add support for extended M3U playlist, meaning that basic track metadata stored in playlists will be used by Mopidy.

    HTTP frontend

    • Upgrade Mopidy.js dependencies and add support for using Mopidy.js with Browserify. This version has been released to npm as Mopidy.js v0.2.0. (Fixes: #609)

    MPD frontend

    • Make the lsinfo, listall, and listallinfo commands support browsing of Mopidy’s virtual file system. (Fixes: #145)
    • Empty commands now return a ACK [5@0] {} No command given error instead of OK. This is consistent with the original MPD server implementation.

    Internal changes

    • Events from the audio actor, backends, and core actor are now emitted asyncronously through the GObject event loop. This should resolve the issue that has blocked the merge of the EOT-vs-EOS fix for a long time.
    Source code(tar.gz)
    Source code(zip)
Owner
Mopidy
The extensible music server
Mopidy
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
A small project where I identify notes and key harmonies in a piece of music and use them further to recreate and generate the same piece of music through Python

A small project where I identify notes and key harmonies in a piece of music and use them further to recreate and generate the same piece of music through Python

null 5 Oct 7, 2022
We built this fully functioning Music player in Python. The music player allows you to play/pause and switch to different songs easily.

We built this fully functioning Music player in Python. The music player allows you to play/pause and switch to different songs easily.

null 1 Nov 19, 2021
Music player - endlessly plays your music

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

Albert Zeyer 482 Dec 19, 2022
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
Oliva music bot help to play vc music

OLIVA V2 ?? Requirements ?? FFmpeg NodeJS nodesource.com Python 3.7+ PyTgCalls Commands ?? For all in group /play - reply to youtube url or song file

SOUL々H҉A҉C҉K҉E҉R҉ 2 Oct 22, 2021
Royal Music You can play music and video at a time in vc

Royals-Music Royal Music You can play music and video at a time in vc Commands SOON String STRING_SESSION Deployment ?? Credits • ??ᴏᴍʏᴀ⃝??ᴇᴇᴛ • ??ғғɪ

null 2 Nov 23, 2021
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
This Is Telegram Music UserBot To Play Music Without Being Admin

This Is Telegram Music UserBot To Play Music Without Being Admin

Krishna Kumar 36 Sep 13, 2022
Just-Music - Spotify API Driven Music Web app, that allows to listen and control and share songs

Just Music... Just Music Is A Web APP That Allows Users To Play Song Using Spoti

Ayush Mishra 3 May 1, 2022
Xbot-Music - Bot Play Music and Video in Voice Chat Group Telegram

XBOT-MUSIC A Telegram Music+video Bot written in Python using Pyrogram and Py-Tg

Fariz 2 Jan 20, 2022
Noinoi music is smoothly playing music on voice chat of telegram.

NOINOI MUSIC BOT ✨ Features Music & Video stream support MultiChat support Playlist & Queue support Skip, Pause, Resume, Stop feature Music & Video do

null 2 Feb 13, 2022
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
Mina - A Telegram Music Bot 5 mandatory Assistant written in Python using Pyrogram and Py-Tgcalls

Mina - A Telegram Music Bot 5 mandatory Assistant written in Python using Pyrogram and Py-Tgcalls

null 3 Feb 7, 2022
Minimal command-line music player written in Python

pyms Minimal command-line music player written in Python. Designed with elegance and minimalism. Resizes dynamically with your terminal. Dependencies

null 12 Sep 23, 2022
Python library for audio and music analysis

librosa A python package for music and audio analysis. Documentation See https://librosa.org/doc/ for a complete reference manual and introductory tut

librosa 5.6k Jan 6, 2023