Configuration Access
The following class diagram shows the implementation of MusicDBs configuration and state management. Only the more important methods are shown in the diagram. For a list of all methods see the related documentation of the class.
Base Configuration Classes
ini Files
This module handles the reading and writing of ini-files. The definition of names is shown in the ini file example below.
[section] option = value
- class musicdb.lib.cfg.config.Config(filename=None)[source]
- AllowNoneValue(allow=True)[source]
This method enables the possibility to configure (read) a
Nonevalue. In case a value has the string"None", theGet()method returnsNone. The upper case N is important!Default behavior of this class is to return the string
"None"as regular string.- Parameters:
allow (bool) – if
Truenone values are allowed, otherwise the string"None"gets returned as a string- Returns:
None
Example
[test] option = None
cfg = Config("test.ini") x = cfg.Get(str, "test", "option") print(type(x)) # str cfg.AllowNoneValue() x = cfg.Get(str, "test", "option") print(type(x)) # NoneType
- Get(datatype, section, option, default=None, islist=False)[source]
This method reads a value from the configuration. The values in the file are all stored as string. Using the datatype parameter will convert that string into a python data type.
The default parameter can be used to define a value that shall be returned in case the option does not exist. This value can be of a different type than defined by the datatype parameter.
If the value of an option is
"None", and none type is allowed by callingAllowNoneValue(),Nonegets returned.If the islist parameter is set to
True, the read value gets interpreted as comma separated list and split. A list of the striped values (without leading or trailing spaces) gets returned casted to the data type given by the datatype parameter.- Parameters:
datatype – The data type of the value. This can be
bool,int,floatorstr.section (str) – Name of the section to read from
option (str) – Name of the option to read
default – Default value in case the option does not exist
islist (bool) – Interpret the value as a comma separated list
- Returns:
The value of an option
Example
[test] integer = 1000 list = 13, 23, 42
cfg = Config("test.ini") x = cfg.Get(int, "test", "integer") print(x) # 1000 x = cfg.Get(int, "test", "list", [], True) print(x) # [13, 23, 42] x = cfg.Get(int, "test", "noneexisting", 1337) print(x) # 1337
- Load(path=None)[source]
This method loads a configuration file. If the path parameter is not
None, the path given while instantiating the class will be overwritten. If the file was already loaded, it gets reloaded.- Parameters:
path (str) – Absolute path to an ini file
- Returns:
Nothing
- Raises:
AssertionError – If internal path variable and parameter is
None. (No path given)
- OptionAvailable(section, option)[source]
This method can be used to check if an option exists in the configuration file.
- Parameters:
section (str) – Name of the section
option (str) – Name of the option
- Returns:
Trueif the option exists, otherwiseFalse
- RemoveSection(sectionname)[source]
This method removes a section from the configuration file
After setting the option, the
Save()method gets called to store the changes. This is necessary because there is no reliable destructor in python to.- Parameters:
section (str) – Section to remove
- Returns:
Nothing
- Save()[source]
This method saves all set values back to the configuration file.
Changing configuration can be prevented by setting the file attributes to read only.
If writing fails not because of missing write permission, an exception gets raised.
- Set(section, option, value)[source]
This method sets an option. The value gets casted to a string. If the section or option does not exist, it will be created.
After setting the option, the
Save()method gets called to store the changes. This is necessary because there is no reliable destructor in python to.- Parameters:
section (str) – Section to write at
option (str) – Name of the option to set
value – Value to store
- Returns:
Nothing
csv Files
This module handles the reading and writing of csv-files.
- class musicdb.lib.cfg.csv.CSVFile(path)[source]
This class reads Comma Separated Value (CSV) files as used by MusicDB.
The class does not cache the files content. Every read access accesses the actual file. Writing does the file update.
The csv files this class works with must have the following dialect:
first line is a header line
delimiter:
,escapechar:
\quotechar:
"quoting:
csv.QUOTE_NONNUMERICline break:
\n
It is allowed to modify the CSV files with external programs, but not guaranteed that MusicDB will not overwrite the changes. It is recommended to only read the files outside of MusicDB. Do not change the layout of the files!
- Parameters:
path (str) – Absolute path of the csv file the class works with
- Read()[source]
This method reads the file and returns its a table represented as a list of dictionaries. The dictionary has a key for each column in the header of the file. So each entry in the list represents one row of the file, and each entry in the dictionary represents one cell or column in that row.
Example
name, id a, 1 b, 2 c, 3
table = csv.Read() print(table)
[ {'name': 'a', 'id': 1}, {'name': 'b', 'id': 2}, {'name': 'c', 'id': 3} ]
- Returns:
A list of dictionaries with one entry or each cell. When the file does not exist,
Nonegets returned.- Raises:
StopIteration – When the CSV file is empty
- Write(table, header=None)[source]
Write rows into the csv file. The first row will be the header of the table.
If there is no header given, the keys of the first dictionary will be used. The header also filters the values to store.
If the table is empty, a header is required.
Example
[ {'name': 'a', 'id': 1, 'temp': 'x'}, {'name': 'b', 'id': 2, 'temp': 'y'}, {'name': 'c', 'id': 3, 'temp': 'z'} ]
print(table) csv.Write(table, ["name", "id"]) # When using #csv.Write(table) # also the temp values would be stored
name, id a, 1 b, 2 c, 3
- Parameters:
table (list) – A list with dictionaries of values for each column
header (list) – The header of the CSV file. Each entry must also be a key in the
tabledictionary! IfNone, then all keys of the dictionaries will be used.
- Returns:
None- Raises:
TypeError – when
tableis not a listValueError – when the
tablelist has not at least one entry and there is no header specifiedTypeError – when the
tablelist elements are not dictionariesTypeError – when
headeris not a list and notNone
MusicDB Configuration File
Detail of the MusicDB Configuration can be found under MusicDB Configuration.
All sections and options can be accessed by their names: MusicDBConfig(...).section.option.
Details of the configurations possible for MusicDB can be found in MusicDB Configuration.
To create a new entry for the MusicDB Configuration the following steps must be done:
Set the section and option in the configuration file as well as in the template in the share directory
In case a new section shall be created, create an empty class for this section inside this module
Read the option in the constructor of the
MusicDBConfigclass
For example, the following option shall be added:
[newmod] enable = True
The option must be read inside the MusicDBConfig __init__ method.
The read value must be written into an attribute named as the option, inside an instance of the dummy class named liked the section:
self.newmod = SECTION() self.newmod.enable = self.Get(bool, "newmod", "enable", False)
Now, the new option is available in the configuration object created using this class:
cfg = MusicDBConfig("musicdb.ini") if cfg.newmod.enable: print("newmod enabled!")
- class musicdb.lib.cfg.musicdb.MusicDBConfig(path='/etc/musicdb.ini')[source]
This class provides the access to the MusicDB configuration file.
By default, the configuration will be read from
/etc/musicdb.ini.- Parameters:
path (str) – Optional alternative configuration path. Default is
/etc/musicdb.ini
- GetDirectory(section, option, default)[source]
This method gets a string from the configuration file and checks if it is an existing directory. If not it prints a warning. The “invalid” path will be returned anyway, because it may be OK that the directory does not exist yet.
- Parameters:
section (str) – Section of an ini-file
option (str) – Option inside the section of an ini-file
default (str) – Default directory path if option is not set in the file
- Returns:
The value of the option set in the config-file or the default value.
- GetFile(section, option, default)[source]
This method gets a string from the configuration file and checks if it is an existing file. If not it prints a warning. The “invalid” path will be returned anyway, because it may be OK that the file does not exist yet.
- Parameters:
section (str) – Section of an ini-file
option (str) – Option inside the section of an ini-file
default (str) – Default file path if option is not set in the file
- Returns:
The value of the option set in the config-file or the default value.
WebUI Configuration File
This module takes care of the WebUI configuration.
The following sections and keys are available:
[meta] version=3 [WebUI] videomode=disabled lyrics=enabled [MainMenu] showstreamplayer=False showsystemstatus=True [ArtistsView] showrelease=True [GenreSelectionView] showother=True [Stream] url=http://127.0.0.1:8000/stream username= password= [debug] blurartwork=false
- [meta]->version (integer):
Version of the configuration scheme
- [WebUI]->videomode (string:
"enabled","disabled"): Defines if the video mode should be present in the WebUI or not. This includes, but is not limited to, the buttons of the main menu
- [WebUI]->lyrics (string:
"enabled","disabled"): Defines if lyrics should be present in the WebUI or not. This includes, but is not limited to, the lyrics state buttons in the Song Lists of the albums
- [MainMenu]->showstreamplayer (boolean):
If True, then the MusicDB audio stream player is shown in the main menu. This player can them be used to connect to the audio stream from the WebUI.
- [MainMenu]->showsystemstatus (boolean):
If True, the MusicDB system status is shown in the main menu. It shows if the connection between the MusicDB Server and Icecast is up and if data gets streamed. These information are not mandatory to know but help you to quickly identify issues with the audio stream.
- [ArtistsView]->showrelease (boolean):
If true, the release date of an album is shown next to its name. If false, the release date will not be shown. In any case, the albums of an artist are sorted by their release date.
- [GenreSelectionView]->showother (boolean):
If true, the default genre “Other” will be listed.
- [Stream]->url,username,password (strings):
Access data to the audio stream that gets managed by MusicDB. If the stream is not protected by the authentication methods of Icecast, no user name or password is required.
- [debug]->blurartwork (boolean):
If true, all artworks are blurred. This is useful to avoid copyright violations on screenshots that shall be public available
- class musicdb.lib.cfg.webui.WebUIConfig(path)[source]
This class holds the configuration for the WebUI.
- Parameters:
path – Absolute path to the WebUI configuration file
External Storage Configuration File
This class reads the configuration of an external music storage.
All sections and options can be accessed by their names: ExternConfig(...).section.option.
If values get changed, they will not be stored!
Example
[meta]
version = 1
cfg = ExternConfig("test.ini")
print(cfg.meta.version)
MusicDB State Files
This module takes care that the state of MusicDB will persist over several sessions.
This is not done automatically by the MDBState class.
Each read or write process to the files that hold the state will be triggered by the classes who manage the related information.
The state is stored in several files in a sub-directory state inside the MusicDB data directory.
More details can be found in MusicDB Data Files and Directories.
All files inside the state directory are managed by the MDBState class.
The content of those files should not be changed by any user because its content gets not validated.
- class musicdb.lib.cfg.mdbstate.MDBState(path, musicdb=None)[source]
This class holds the MusicDB internal state.
The following table shows which method is responsible for which file in the MusicDB State Directory.
File Name
Read Method
Write Method
songqueue.csv
videoqueue.csv
artistblacklist.csv
albumblacklist.csv
songblacklist.csv
videoblacklist.csv
Additional this class allows to access the file
state.iniin the MusicDB State Directory. The file can be accessed viaSet()andGet(). The sectionmetais reserved for thisMDBStateclass.Another section is
MusicDBthat represents the state of the MusicDB WebUI (and possibly backend in future). One key isuimodethat can be set viaSetUIMode()and read viaGetUIMode(). The value for this key is a string and can be"audio"or"video". The value represents if the user interface is in audio-mode to manage an audio stream or video-mode to present music videos.The method
GetGenreFilterList()accesses a sectionalbumfiler. Each key in this section represents a main genre (all characters lower case) tag and can have the valueTrueorFalse. If a genre is not listed in this section, it is assumed to have the valueFalse. As soon as the genre gets activated via the WebUIs genre selection interface, it appears in the albumfiler-list.The method
GetSubgenreFilterList()returns a list of selected sub genres for a certain genre, similar to theGetGenreFilterList(). It accesses a sectionSubgenreFilter:$genrewhere$genreis the main genre name. The sections are created and updated viaUpdateSubgenreFilterList().- Parameters:
path – Absolute path to the MusicDB state directory
musicdb – Instance of the MusicDB Database (can be None)
- GetActiveTagIDs()[source]
Returns a list of tag IDs of active genres and their active sub genres. Only sub genres of active genres are considered. If no sub genre is active, but the main genre is, then the main genre ID is included. This can be the case when there is no sub genre existing for a main genre.
Example
filter = mdbstate.GetActiveTagIDs() print(filter) # [1, 13, 42]
- Returns:
A list of genre and sub genre tag IDs
- GetAllSubgenreFilterLists()[source]
Returns a dictionary with lists of selected sub genres. Each key in the dictionary is a main genre name as returned by
musicdb.lib.db.MusicDatabase.GetAllTags(). Behind each key, a list of selected sub genres is stored. If no sub genre is selected, the list is empty. The lists come fromGetSubgenreFilterList().Each main genre is considered, not only the selected ones that would have been returned by
GetGenreFilterList().Example
filter = mdbstate.GetAllSubgenreFilterLists() print(filter["Metal"]) # ['Death Metal','Black Metal']
- Returns:
A dict with lists of selected sub genres for each main genre
- GetGenreFilterList()[source]
This method returns a list of the activated genre The list consists of the names of the genres as configured by the user. That are the names returned by
musicdb.lib.db.musicdb.MusicDatabase.GetAllTags().The available genres get compared to the ones set in the state.ini file inside the MusicDB State directory. If a genre is not defined in the configuration file, its default value is
Falseand so it is not active. Before the comparison, the state file gets reloaded so that external changes get applied directly.See
UpdateGenreFilterList()for changing the state of the genres.Example
filter = mdbstate.GetGenreFilterList() print(filter) # ['Metal','NDH'] # Metal and NDH are active, other available genres are not enabled.
- Returns:
A list of main genre names that are activated
- GetSubgenreFilterList(genre)[source]
This method returns a list of the activated sub genre for a certain genre. The list consists of the names of the genres as configured by the user. That are the names returned by
musicdb.lib.db.musicdb.MusicDatabase.GetAllTags().The available sub genres get compared to the ones set in the state.ini file inside the MusicDB State directory. If a sub genre is not defined in the configuration file, its default value is
Trueand so it is active. Before the comparison, the state file gets reloaded so that external changes get applied directly.The output is independent from the state of the main genre.
See
UpdateSubgenreFilterList()for changing the state of the sub genres.Example
filter = mdbstate.GetSubgenreFilterList("Metal") print(filter) # ['Death Metal','Black Metal']
- Parameters:
genre (str) – Name of a genre for that the sub genres will be checked
- Returns:
A list of sub genre names that are activated
- GetUIMode()[source]
This method simply returns the content of
[MusicDB]->uimodein the state.ini file. In case the value is invalid or not set,"audio"gets returned.Valid strings are
"audio"or"video"- Returns:
A string
"audio"or"video"
- LoadBlacklists(songbllen, albumbllen, artistbllen, videobllen)[source]
This method returns a dictionary with the blacklist used by
musicdb.mdbapi.randy.Randy. The blacklists are managed by theBlacklistInterfaceclass. This method also handles the blacklist length by adding empty entries or cutting off exceeding ones.- Parameters:
songbllen (int) – Number of entries the blacklist shall have
albumbllen (int) – Number of entries the blacklist shall have
artistbllen (int) – Number of entries the blacklist shall have
videobllen (int) – Number of entries the blacklist shall have
- Returns:
A dictionary with the blacklists as expected by
musicdb.mdbapi.randy.Randy
- LoadSongQueue()[source]
This method reads the song queue from the state directory.
The method returns the queue as needed inside
musicdb.mdbapi.songqueue.SongQueue(): A list of dictionaries, each containing theentryidandsongidas integers andisrandomas boolean.The UUIDs of the queue entries remain.
- Returns:
A stored song queue
- LoadVideoQueue()[source]
This method reads the video queue from the state directory.
The method returns the queue as needed inside
musicdb.mdbapi.videoqueue.VideoQueue(): A list of dictionaries, each containing theentryidandvideoidas integers andisrandomas boolean.The UUIDs of the queue entries remain.
- Returns:
A stored video queue
- ReadList(listname)[source]
Reads a list from the mdbstate directory. The
listnameargument defines which file gets read:config.directories.state + "/listname.csv".This method should only be used by class internal methods. When a file can not be accessed, an empty list gets returned. So deleting a file is an option to reset an internal state of MusicDB.
- Parameters:
listname (str) – Name of the list to read without trailing .csv
- Returns:
A list of rows from the file. When reading the list fails, an empty list gets returned.
- SaveBlacklists(blacklists)[source]
This method stores the blacklist in the related CSV files. The data structure of the dictionary is expected to be the same,
musicdb.mdbapi.blacklist.BlacklistInterfaceuses.- Parameters:
blacklist (dict) – A dictionary of blacklists.
- Returns:
Nothing
- SaveSongQueue(queue)[source]
This method saves a song queue. The data structure of the queue must be exact as the one expected when the queue shall be loaded.
- Parameters:
queue (dictionary) – The song queue to save.
- Returns:
Nothing
- SaveVideoQueue(queue)[source]
This method saves a video queue. The data structure of the queue must be exact as the one expected when the queue shall be loaded.
- Parameters:
queue (dictionary) – The video queue to save.
- Returns:
Nothing
- SetUIMode(mode)[source]
Sets the UI mode in the state.ini file. Before writing the data
modegets checked if it contains a valid value. If mode is an invalid argument, an exception gets raised.- Parameters:
mode (str) –
"audio"or"video"mode- Returns:
None- Raises:
TypeError – When mode is not of type string
ValueError – When mode contains an invalid string
- UpdateGenreFilterList(genre, enable)[source]
Sets the enable-state of a genre to the value of the parameter
enable.The value is stored in the state.ini file under the category
"GenreFilter". SeeGetGenreFilterList()for reading out the information.- Parameters:
genre (str) – Name of a genre to enable or disable
enable (bool) – Enable or disable genre
- Returns:
Nothing
- UpdateSubgenreFilterList(genre, subgenre, enable)[source]
Sets the enable-state of a genre to the value of the parameter
enable.The value is stored in the state.ini file under the category
SubgenreFilter:$genre. SeeGetSubgenreFilterList()for reading out the information.- Parameters:
genre (str) – Name of a main genre
subgenre (str) – Name of a sub genre to enable or disable
enable (bool) – Enable or disable sub genre
- Returns:
Nothing
- WriteList(listname, rows, header=None)[source]
This method write a list of rows into the related file. The
listnameargument defines which file gets written:config.directories.state + "/listname.csv".When there is no header given (list of column names), the keys of the rows-dictionaries are used.
This method should only be used by class internal methods.
- Parameters:
listname (str) – Name of the list to read without trailing .csv
rows (list) – The list that shall be stored
header (list) – Optional list with column names as string.
- Returns:
Trueon success, otherwiseFalse
Randy Configuration
This module takes care that the configuration of the random song selection algorithm (Randy) will persist over several sessions.
This is not done automatically by the RandyConfiguration class.
Each read or write process to the files that hold the state will be triggered by the classes who manage the related information.
The configuration is stored in a files randy.ini in a sub-directory config inside the MusicDB data directory.
More details can be found in MusicDB Data Files and Directories.
Possible configurations
- NoDisabled (boolean):
If
trueno disabled songs will be chosen- NoHated (boolean):
If
trueno hated songs will be chosen- NoHidden (boolean):
If
Trueno hidden albums will be considered- Nobadfile (boolean):
If
Trueno songs marked as “bad file” will be selected- NoLiveMusic (boolean):
If
Trueno songs marked as “live recording” will be selected- MinSongLength (number ∈ ℕ):
Determines the minimum length of a song in seconds to be in the set of possible songs
- MaxSongLength (number ∈ ℕ):
Determines the maximum length of a song in seconds to be in the set of possible songs
- SongListLength (number ∈ ℕ):
Blacklist length for songs (
0to disable the blacklist)- AlbumListLength (number ∈ ℕ):
Blacklist length for albums (
0to disable the blacklist)- ArtistListLength (number ∈ ℕ):
Blacklist length for artists (
0to disable the blacklist)- VideoListLength (number ∈ ℕ):
Blacklist length for videos (
0to disable the blacklist)- MaxAge (time in hours as integer):
The highest age an entry in one of the three blacklist can have until it gets automatically removed.
- MaxTries (number ∈ ℕ):
Maximum amount of tries to find a valid random songs. This prevents spending infinite amount of time getting a song even if the data base does not provide enough songs.
- class musicdb.lib.cfg.randy.RandyConfiguration(configpath)[source]
This class holds the Randy configuration.
- Parameters:
configpath – Absolute path to the Randy configuration file.
- LoadConfig()[source]
This method loads the current randy configuration and returns them in a dictionary.
This method is mainly available to provide the Randy configuration to the WebUI.
- Returns:
dict with the whole WebUI configuration
WebSocket API Key File
This module takes care of the WebSocket API Key
The key will be stored in the MusicDB data directory inside the config sub directory.
- class musicdb.lib.cfg.wsapikey.WebSocketAPIKey(config)[source]
This class manages the WebSocket API Key. Use the method
Read()to get the API key.If the key is missing, it will be generated. A new key gets also be set in the WebUI JavaScript configuration file
config.js.To generate a new key, delete the
wsapikey.txtfrom the MusicDB Configuration Directory.- Parameters:
config – Instance of the
MusicDBConifgclass
- CreateIfMissing()[source]
This method creates a new WebSocket API Key if none has been created yet.
If the WebSocke API Key file exists nothing will be done. If it is missing, it will be created including a new WebSocket API Key.
It also updates a new generated WebUI
config.jsfile. It is expected that theconfig.jsfile exists.The WebUI JavaScript configuration must already exist. If that file already has a key, it will not be replaced. If no key exists yet (a dummy key
WSAPIKEYis expected in place) the key will be set.For creating the key,
opensslis used:openssl rand -base64 -out $path 32
- Returns:
Trueon success or if the key already exists, otherwiseFalse
- Read()[source]
Reads the WebSocket API Key and returns it as string. If it does not exist, it will be created via
CreateIfMissing().Raises an exception if the key file cannot be created.
- Returns:
The WebSocket API Key as string.