mirror of
https://github.com/rembo10/headphones.git
synced 2026-05-19 18:15:31 +01:00
1332 lines
58 KiB
Python
1332 lines
58 KiB
Python
# This file is part of Headphones.
|
|
#
|
|
# Headphones is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Headphones is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with Headphones. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# NZBGet support added by CurlyMo <curlymoo1@gmail.com> as a part of XBian - XBMC on the Raspberry Pi
|
|
|
|
from __future__ import with_statement
|
|
|
|
import os, sys, subprocess
|
|
|
|
import threading
|
|
import webbrowser
|
|
import sqlite3
|
|
import itertools
|
|
|
|
from lib.apscheduler.scheduler import Scheduler
|
|
from lib.configobj import ConfigObj
|
|
|
|
import cherrypy
|
|
|
|
from headphones import versioncheck, logger, version
|
|
from headphones.common import *
|
|
|
|
FULL_PATH = None
|
|
PROG_DIR = None
|
|
|
|
ARGS = None
|
|
SIGNAL = None
|
|
|
|
SYS_PLATFORM = None
|
|
SYS_ENCODING = None
|
|
|
|
VERBOSE = 1
|
|
DAEMON = False
|
|
CREATEPID = False
|
|
PIDFILE= None
|
|
|
|
SCHED = Scheduler()
|
|
|
|
INIT_LOCK = threading.Lock()
|
|
__INITIALIZED__ = False
|
|
started = False
|
|
|
|
DATA_DIR = None
|
|
|
|
CONFIG_FILE = None
|
|
CFG = None
|
|
CONFIG_VERSION = None
|
|
|
|
DB_FILE = None
|
|
|
|
LOG_DIR = None
|
|
LOG_LIST = []
|
|
|
|
CACHE_DIR = None
|
|
|
|
HTTP_PORT = None
|
|
HTTP_HOST = None
|
|
HTTP_USERNAME = None
|
|
HTTP_PASSWORD = None
|
|
HTTP_ROOT = None
|
|
HTTP_PROXY = False
|
|
LAUNCH_BROWSER = False
|
|
|
|
ENABLE_HTTPS = False
|
|
HTTPS_CERT = None
|
|
HTTPS_KEY = None
|
|
|
|
API_ENABLED = False
|
|
API_KEY = None
|
|
|
|
GIT_PATH = None
|
|
GIT_USER = None
|
|
GIT_BRANCH = None
|
|
DO_NOT_OVERRIDE_GIT_BRANCH = False
|
|
INSTALL_TYPE = None
|
|
CURRENT_VERSION = None
|
|
LATEST_VERSION = None
|
|
COMMITS_BEHIND = None
|
|
|
|
CHECK_GITHUB = False
|
|
CHECK_GITHUB_ON_STARTUP = False
|
|
CHECK_GITHUB_INTERVAL = None
|
|
|
|
MUSIC_DIR = None
|
|
DESTINATION_DIR = None
|
|
LOSSLESS_DESTINATION_DIR = None
|
|
FOLDER_FORMAT = None
|
|
FILE_FORMAT = None
|
|
FILE_UNDERSCORES = False
|
|
PATH_TO_XML = None
|
|
PREFERRED_QUALITY = None
|
|
PREFERRED_BITRATE = None
|
|
PREFERRED_BITRATE_HIGH_BUFFER = None
|
|
PREFERRED_BITRATE_LOW_BUFFER = None
|
|
PREFERRED_BITRATE_ALLOW_LOSSLESS = False
|
|
DETECT_BITRATE = False
|
|
ADD_ARTISTS = False
|
|
CORRECT_METADATA = False
|
|
MOVE_FILES = False
|
|
RENAME_FILES = False
|
|
CLEANUP_FILES = False
|
|
ADD_ALBUM_ART = False
|
|
ALBUM_ART_FORMAT = None
|
|
EMBED_ALBUM_ART = False
|
|
EMBED_LYRICS = False
|
|
REPLACE_EXISTING_FOLDERS = False
|
|
NZB_DOWNLOADER = None # 0: sabnzbd, 1: nzbget, 2: blackhole
|
|
TORRENT_DOWNLOADER = None # 0: blackhole, 1: transmission, 2: utorrent
|
|
DOWNLOAD_DIR = None
|
|
BLACKHOLE = None
|
|
BLACKHOLE_DIR = None
|
|
USENET_RETENTION = None
|
|
INCLUDE_EXTRAS = False
|
|
EXTRAS = None
|
|
AUTOWANT_UPCOMING = False
|
|
AUTOWANT_ALL = False
|
|
KEEP_TORRENT_FILES = False
|
|
PREFER_TORRENTS = None # 0: nzbs, 1: torrents, 2: no preference
|
|
OPEN_MAGNET_LINKS = False
|
|
|
|
SEARCH_INTERVAL = 360
|
|
LIBRARYSCAN = False
|
|
LIBRARYSCAN_INTERVAL = 300
|
|
DOWNLOAD_SCAN_INTERVAL = 5
|
|
UPDATE_DB_INTERVAL = 24
|
|
MB_IGNORE_AGE = 365
|
|
|
|
SAB_HOST = None
|
|
SAB_USERNAME = None
|
|
SAB_PASSWORD = None
|
|
SAB_APIKEY = None
|
|
SAB_CATEGORY = None
|
|
|
|
NZBGET_USERNAME = None
|
|
NZBGET_PASSWORD = None
|
|
NZBGET_CATEGORY = None
|
|
NZBGET_HOST = None
|
|
|
|
HEADPHONES_INDEXER = False
|
|
|
|
TRANSMISSION_HOST = None
|
|
TRANSMISSION_USERNAME = None
|
|
TRANSMISSION_PASSWORD = None
|
|
|
|
UTORRENT_HOST = None
|
|
UTORRENT_USERNAME = None
|
|
UTORRENT_PASSWORD = None
|
|
|
|
NEWZNAB = False
|
|
NEWZNAB_HOST = None
|
|
NEWZNAB_APIKEY = None
|
|
NEWZNAB_ENABLED = False
|
|
EXTRA_NEWZNABS = []
|
|
|
|
NZBSORG = False
|
|
NZBSORG_UID = None
|
|
NZBSORG_HASH = None
|
|
|
|
NZBSRUS = False
|
|
NZBSRUS_UID = None
|
|
NZBSRUS_APIKEY = None
|
|
|
|
OMGWTFNZBS = False
|
|
OMGWTFNZBS_UID = None
|
|
OMGWTFNZBS_APIKEY = None
|
|
|
|
PREFERRED_WORDS = None
|
|
IGNORED_WORDS = None
|
|
REQUIRED_WORDS = None
|
|
|
|
LASTFM_USERNAME = None
|
|
|
|
LOSSY_MEDIA_FORMATS = ["mp3", "aac", "ogg", "ape", "m4a", "asf", "wma"]
|
|
LOSSLESS_MEDIA_FORMATS = ["flac"]
|
|
MEDIA_FORMATS = LOSSY_MEDIA_FORMATS + LOSSLESS_MEDIA_FORMATS
|
|
|
|
ALBUM_COMPLETION_PCT = None # This is used in importer.py to determine how complete an album needs to be - to be considered "downloaded". Percentage from 0-100
|
|
|
|
TORRENTBLACKHOLE_DIR = None
|
|
NUMBEROFSEEDERS = 10
|
|
ISOHUNT = None
|
|
KAT = None
|
|
MININOVA = None
|
|
PIRATEBAY = None
|
|
PIRATEBAY_PROXY_URL = None
|
|
WAFFLES = None
|
|
WAFFLES_UID = None
|
|
WAFFLES_PASSKEY = None
|
|
RUTRACKER = None
|
|
RUTRACKER_USER = None
|
|
RUTRACKER_PASSWORD = None
|
|
WHATCD = None
|
|
WHATCD_USERNAME = None
|
|
WHATCD_PASSWORD = None
|
|
DOWNLOAD_TORRENT_DIR = None
|
|
|
|
INTERFACE = None
|
|
FOLDER_PERMISSIONS = None
|
|
FILE_PERMISSIONS = None
|
|
|
|
MUSIC_ENCODER = False
|
|
ENCODERFOLDER = None
|
|
ENCODER_PATH = None
|
|
ENCODER = None
|
|
XLDPROFILE = None
|
|
BITRATE = None
|
|
SAMPLINGFREQUENCY = None
|
|
ADVANCEDENCODER = None
|
|
ENCODEROUTPUTFORMAT = None
|
|
ENCODERQUALITY = None
|
|
ENCODERVBRCBR = None
|
|
ENCODERLOSSLESS = False
|
|
ENCODER_MULTICORE = False
|
|
ENCODER_MULTICORE_COUNT = 0
|
|
DELETE_LOSSLESS_FILES = False
|
|
GROWL_ENABLED = True
|
|
GROWL_HOST = None
|
|
GROWL_PASSWORD = None
|
|
GROWL_ONSNATCH = True
|
|
PROWL_ENABLED = True
|
|
PROWL_PRIORITY = 1
|
|
PROWL_KEYS = None
|
|
PROWL_ONSNATCH = True
|
|
XBMC_ENABLED = False
|
|
XBMC_HOST = None
|
|
XBMC_USERNAME = None
|
|
XBMC_PASSWORD = None
|
|
XBMC_UPDATE = False
|
|
XBMC_NOTIFY = False
|
|
LMS_ENABLED = False
|
|
LMS_HOST = None
|
|
PLEX_ENABLED = False
|
|
PLEX_SERVER_HOST = None
|
|
PLEX_CLIENT_HOST = None
|
|
PLEX_USERNAME = None
|
|
PLEX_PASSWORD = None
|
|
PLEX_UPDATE = False
|
|
PLEX_NOTIFY = False
|
|
NMA_ENABLED = False
|
|
NMA_APIKEY = None
|
|
NMA_PRIORITY = None
|
|
NMA_ONSNATCH = None
|
|
PUSHALOT_ENABLED = False
|
|
PUSHALOT_APIKEY = None
|
|
PUSHALOT_ONSNATCH = None
|
|
SYNOINDEX_ENABLED = False
|
|
PUSHOVER_ENABLED = True
|
|
PUSHOVER_PRIORITY = 1
|
|
PUSHOVER_KEYS = None
|
|
PUSHOVER_ONSNATCH = True
|
|
PUSHOVER_APITOKEN = None
|
|
PUSHBULLET_ENABLED = True
|
|
PUSHBULLET_APIKEY = None
|
|
PUSHBULLET_DEVICEID = None
|
|
PUSHBULLET_ONSNATCH = True
|
|
TWITTER_ENABLED = False
|
|
TWITTER_ONSNATCH = False
|
|
TWITTER_USERNAME = None
|
|
TWITTER_PASSWORD = None
|
|
TWITTER_PREFIX = None
|
|
MIRRORLIST = ["musicbrainz.org","headphones","custom"]
|
|
MIRROR = None
|
|
CUSTOMHOST = None
|
|
CUSTOMPORT = None
|
|
CUSTOMSLEEP = None
|
|
HPUSER = None
|
|
HPPASS = None
|
|
SONGKICK_ENABLED = False
|
|
SONGKICK_APIKEY = None
|
|
SONGKICK_LOCATION = None
|
|
SONGKICK_FILTER_ENABLED = False
|
|
|
|
CACHE_SIZEMB = 32
|
|
JOURNAL_MODE = None
|
|
|
|
UMASK = None
|
|
|
|
def CheckSection(sec):
|
|
""" Check if INI section exists, if not create it """
|
|
try:
|
|
CFG[sec]
|
|
return True
|
|
except:
|
|
CFG[sec] = {}
|
|
return False
|
|
|
|
################################################################################
|
|
# Check_setting_int #
|
|
################################################################################
|
|
def check_setting_int(config, cfg_name, item_name, def_val):
|
|
try:
|
|
my_val = int(config[cfg_name][item_name])
|
|
except:
|
|
my_val = def_val
|
|
try:
|
|
config[cfg_name][item_name] = my_val
|
|
except:
|
|
config[cfg_name] = {}
|
|
config[cfg_name][item_name] = my_val
|
|
logger.debug("%s -> %s", item_name, my_val)
|
|
return my_val
|
|
|
|
################################################################################
|
|
# Check_setting_str #
|
|
################################################################################
|
|
def check_setting_str(config, cfg_name, item_name, def_val, log=True):
|
|
try:
|
|
my_val = config[cfg_name][item_name]
|
|
except:
|
|
my_val = def_val
|
|
try:
|
|
config[cfg_name][item_name] = my_val
|
|
except:
|
|
config[cfg_name] = {}
|
|
config[cfg_name][item_name] = my_val
|
|
|
|
logger.debug("%s -> %s", item_name, my_val if log else "******")
|
|
return my_val
|
|
|
|
def initialize():
|
|
|
|
with INIT_LOCK:
|
|
|
|
global __INITIALIZED__, FULL_PATH, PROG_DIR, VERBOSE, DAEMON, SYS_PLATFORM, DATA_DIR, CONFIG_FILE, CFG, CONFIG_VERSION, LOG_DIR, CACHE_DIR, \
|
|
HTTP_PORT, HTTP_HOST, HTTP_USERNAME, HTTP_PASSWORD, HTTP_ROOT, HTTP_PROXY, LAUNCH_BROWSER, API_ENABLED, API_KEY, GIT_PATH, GIT_USER, GIT_BRANCH, DO_NOT_OVERRIDE_GIT_BRANCH, \
|
|
CURRENT_VERSION, LATEST_VERSION, CHECK_GITHUB, CHECK_GITHUB_ON_STARTUP, CHECK_GITHUB_INTERVAL, MUSIC_DIR, DESTINATION_DIR, \
|
|
LOSSLESS_DESTINATION_DIR, PREFERRED_QUALITY, PREFERRED_BITRATE, DETECT_BITRATE, ADD_ARTISTS, CORRECT_METADATA, MOVE_FILES, \
|
|
RENAME_FILES, FOLDER_FORMAT, FILE_FORMAT, FILE_UNDERSCORES, CLEANUP_FILES, INCLUDE_EXTRAS, EXTRAS, AUTOWANT_UPCOMING, AUTOWANT_ALL, KEEP_TORRENT_FILES, PREFER_TORRENTS, OPEN_MAGNET_LINKS, \
|
|
ADD_ALBUM_ART, ALBUM_ART_FORMAT, EMBED_ALBUM_ART, EMBED_LYRICS, REPLACE_EXISTING_FOLDERS, DOWNLOAD_DIR, BLACKHOLE, BLACKHOLE_DIR, USENET_RETENTION, SEARCH_INTERVAL, \
|
|
TORRENTBLACKHOLE_DIR, NUMBEROFSEEDERS, ISOHUNT, KAT, PIRATEBAY, PIRATEBAY_PROXY_URL, MININOVA, WAFFLES, WAFFLES_UID, WAFFLES_PASSKEY, \
|
|
RUTRACKER, RUTRACKER_USER, RUTRACKER_PASSWORD, WHATCD, WHATCD_USERNAME, WHATCD_PASSWORD, DOWNLOAD_TORRENT_DIR, \
|
|
LIBRARYSCAN, LIBRARYSCAN_INTERVAL, DOWNLOAD_SCAN_INTERVAL, UPDATE_DB_INTERVAL, MB_IGNORE_AGE, SAB_HOST, SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, \
|
|
NZBGET_USERNAME, NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_HOST, HEADPHONES_INDEXER, NZBMATRIX, TRANSMISSION_HOST, TRANSMISSION_USERNAME, TRANSMISSION_PASSWORD, \
|
|
UTORRENT_HOST, UTORRENT_USERNAME, UTORRENT_PASSWORD, NEWZNAB, NEWZNAB_HOST, NEWZNAB_APIKEY, NEWZNAB_ENABLED, EXTRA_NEWZNABS, \
|
|
NZBSORG, NZBSORG_UID, NZBSORG_HASH, NZBSRUS, NZBSRUS_UID, NZBSRUS_APIKEY, OMGWTFNZBS, OMGWTFNZBS_UID, OMGWTFNZBS_APIKEY, \
|
|
NZB_DOWNLOADER, TORRENT_DOWNLOADER, PREFERRED_WORDS, REQUIRED_WORDS, IGNORED_WORDS, LASTFM_USERNAME, \
|
|
INTERFACE, FOLDER_PERMISSIONS, FILE_PERMISSIONS, ENCODERFOLDER, ENCODER_PATH, ENCODER, XLDPROFILE, BITRATE, SAMPLINGFREQUENCY, \
|
|
MUSIC_ENCODER, ADVANCEDENCODER, ENCODEROUTPUTFORMAT, ENCODERQUALITY, ENCODERVBRCBR, ENCODERLOSSLESS, ENCODER_MULTICORE, ENCODER_MULTICORE_COUNT, DELETE_LOSSLESS_FILES, \
|
|
GROWL_ENABLED, GROWL_HOST, GROWL_PASSWORD, GROWL_ONSNATCH, PROWL_ENABLED, PROWL_PRIORITY, PROWL_KEYS, PROWL_ONSNATCH, PUSHOVER_ENABLED, PUSHOVER_PRIORITY, PUSHOVER_KEYS, PUSHOVER_ONSNATCH, PUSHOVER_APITOKEN, MIRRORLIST, \
|
|
TWITTER_ENABLED, TWITTER_ONSNATCH, TWITTER_USERNAME, TWITTER_PASSWORD, TWITTER_PREFIX, \
|
|
PUSHBULLET_ENABLED, PUSHBULLET_APIKEY, PUSHBULLET_DEVICEID, PUSHBULLET_ONSNATCH, \
|
|
MIRROR, CUSTOMHOST, CUSTOMPORT, CUSTOMSLEEP, HPUSER, HPPASS, XBMC_ENABLED, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, XBMC_UPDATE, \
|
|
XBMC_NOTIFY, LMS_ENABLED, LMS_HOST, NMA_ENABLED, NMA_APIKEY, NMA_PRIORITY, NMA_ONSNATCH, SYNOINDEX_ENABLED, ALBUM_COMPLETION_PCT, PREFERRED_BITRATE_HIGH_BUFFER, \
|
|
PREFERRED_BITRATE_LOW_BUFFER, PREFERRED_BITRATE_ALLOW_LOSSLESS, CACHE_SIZEMB, JOURNAL_MODE, UMASK, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \
|
|
PLEX_ENABLED, PLEX_SERVER_HOST, PLEX_CLIENT_HOST, PLEX_USERNAME, PLEX_PASSWORD, PLEX_UPDATE, PLEX_NOTIFY, PUSHALOT_ENABLED, PUSHALOT_APIKEY, \
|
|
PUSHALOT_ONSNATCH, SONGKICK_ENABLED, SONGKICK_APIKEY, SONGKICK_LOCATION, SONGKICK_FILTER_ENABLED
|
|
|
|
|
|
if __INITIALIZED__:
|
|
return False
|
|
|
|
# Make sure all the config sections exist
|
|
CheckSection('General')
|
|
CheckSection('SABnzbd')
|
|
CheckSection('NZBget')
|
|
CheckSection('Transmission')
|
|
CheckSection('uTorrent')
|
|
CheckSection('Headphones')
|
|
CheckSection('Newznab')
|
|
CheckSection('NZBsorg')
|
|
CheckSection('NZBsRus')
|
|
CheckSection('omgwtfnzbs')
|
|
CheckSection('Waffles')
|
|
CheckSection('Rutracker')
|
|
CheckSection('What.cd')
|
|
CheckSection('Growl')
|
|
CheckSection('Prowl')
|
|
CheckSection('Pushover')
|
|
CheckSection('PushBullet')
|
|
CheckSection('XBMC')
|
|
CheckSection('LMS')
|
|
CheckSection('Plex')
|
|
CheckSection('NMA')
|
|
CheckSection('Pushalot')
|
|
CheckSection('Synoindex')
|
|
CheckSection('Twitter')
|
|
CheckSection('Songkick')
|
|
CheckSection('Advanced')
|
|
|
|
# Set global variables based on config file or use defaults
|
|
CONFIG_VERSION = check_setting_str(CFG, 'General', 'config_version', '0')
|
|
|
|
try:
|
|
HTTP_PORT = check_setting_int(CFG, 'General', 'http_port', 8181)
|
|
except:
|
|
HTTP_PORT = 8181
|
|
|
|
if HTTP_PORT < 21 or HTTP_PORT > 65535:
|
|
HTTP_PORT = 8181
|
|
|
|
HTTP_HOST = check_setting_str(CFG, 'General', 'http_host', '0.0.0.0')
|
|
HTTP_USERNAME = check_setting_str(CFG, 'General', 'http_username', '')
|
|
HTTP_PASSWORD = check_setting_str(CFG, 'General', 'http_password', '')
|
|
HTTP_ROOT = check_setting_str(CFG, 'General', 'http_root', '/')
|
|
HTTP_PROXY = bool(check_setting_int(CFG, 'General', 'http_proxy', 0))
|
|
ENABLE_HTTPS = bool(check_setting_int(CFG, 'General', 'enable_https', 0))
|
|
HTTPS_CERT = check_setting_str(CFG, 'General', 'https_cert', os.path.join(DATA_DIR, 'server.crt'))
|
|
HTTPS_KEY = check_setting_str(CFG, 'General', 'https_key', os.path.join(DATA_DIR, 'server.key'))
|
|
LAUNCH_BROWSER = bool(check_setting_int(CFG, 'General', 'launch_browser', 1))
|
|
API_ENABLED = bool(check_setting_int(CFG, 'General', 'api_enabled', 0))
|
|
API_KEY = check_setting_str(CFG, 'General', 'api_key', '')
|
|
GIT_PATH = check_setting_str(CFG, 'General', 'git_path', '')
|
|
GIT_USER = check_setting_str(CFG, 'General', 'git_user', 'rembo10')
|
|
GIT_BRANCH = check_setting_str(CFG, 'General', 'git_branch', 'master')
|
|
DO_NOT_OVERRIDE_GIT_BRANCH = check_setting_int(CFG, 'General', 'do_not_override_git_branch', 0)
|
|
LOG_DIR = check_setting_str(CFG, 'General', 'log_dir', '')
|
|
CACHE_DIR = check_setting_str(CFG, 'General', 'cache_dir', '')
|
|
|
|
CHECK_GITHUB = bool(check_setting_int(CFG, 'General', 'check_github', 1))
|
|
CHECK_GITHUB_ON_STARTUP = bool(check_setting_int(CFG, 'General', 'check_github_on_startup', 1))
|
|
CHECK_GITHUB_INTERVAL = check_setting_int(CFG, 'General', 'check_github_interval', 360)
|
|
|
|
MUSIC_DIR = check_setting_str(CFG, 'General', 'music_dir', '')
|
|
DESTINATION_DIR = check_setting_str(CFG, 'General', 'destination_dir', '')
|
|
LOSSLESS_DESTINATION_DIR = check_setting_str(CFG, 'General', 'lossless_destination_dir', '')
|
|
PREFERRED_QUALITY = check_setting_int(CFG, 'General', 'preferred_quality', 0)
|
|
PREFERRED_BITRATE = check_setting_str(CFG, 'General', 'preferred_bitrate', '')
|
|
PREFERRED_BITRATE_HIGH_BUFFER = check_setting_int(CFG, 'General', 'preferred_bitrate_high_buffer', '')
|
|
PREFERRED_BITRATE_LOW_BUFFER = check_setting_int(CFG, 'General', 'preferred_bitrate_low_buffer', '')
|
|
PREFERRED_BITRATE_ALLOW_LOSSLESS = bool(check_setting_int(CFG, 'General', 'preferred_bitrate_allow_lossless', 0))
|
|
DETECT_BITRATE = bool(check_setting_int(CFG, 'General', 'detect_bitrate', 0))
|
|
ADD_ARTISTS = bool(check_setting_int(CFG, 'General', 'auto_add_artists', 1))
|
|
CORRECT_METADATA = bool(check_setting_int(CFG, 'General', 'correct_metadata', 0))
|
|
MOVE_FILES = bool(check_setting_int(CFG, 'General', 'move_files', 0))
|
|
RENAME_FILES = bool(check_setting_int(CFG, 'General', 'rename_files', 0))
|
|
FOLDER_FORMAT = check_setting_str(CFG, 'General', 'folder_format', 'Artist/Album [Year]')
|
|
FILE_FORMAT = check_setting_str(CFG, 'General', 'file_format', 'Track Artist - Album [Year] - Title')
|
|
FILE_UNDERSCORES = bool(check_setting_int(CFG, 'General', 'file_underscores', 0))
|
|
CLEANUP_FILES = bool(check_setting_int(CFG, 'General', 'cleanup_files', 0))
|
|
ADD_ALBUM_ART = bool(check_setting_int(CFG, 'General', 'add_album_art', 0))
|
|
ALBUM_ART_FORMAT = check_setting_str(CFG, 'General', 'album_art_format', 'folder')
|
|
EMBED_ALBUM_ART = bool(check_setting_int(CFG, 'General', 'embed_album_art', 0))
|
|
EMBED_LYRICS = bool(check_setting_int(CFG, 'General', 'embed_lyrics', 0))
|
|
REPLACE_EXISTING_FOLDERS = bool(check_setting_int(CFG, 'General', 'replace_existing_folders', 0))
|
|
NZB_DOWNLOADER = check_setting_int(CFG, 'General', 'nzb_downloader', 0)
|
|
TORRENT_DOWNLOADER = check_setting_int(CFG, 'General', 'torrent_downloader', 0)
|
|
DOWNLOAD_DIR = check_setting_str(CFG, 'General', 'download_dir', '')
|
|
BLACKHOLE = bool(check_setting_int(CFG, 'General', 'blackhole', 0))
|
|
BLACKHOLE_DIR = check_setting_str(CFG, 'General', 'blackhole_dir', '')
|
|
USENET_RETENTION = check_setting_int(CFG, 'General', 'usenet_retention', '1500')
|
|
INCLUDE_EXTRAS = bool(check_setting_int(CFG, 'General', 'include_extras', 0))
|
|
EXTRAS = check_setting_str(CFG, 'General', 'extras', '')
|
|
AUTOWANT_UPCOMING = bool(check_setting_int(CFG, 'General', 'autowant_upcoming', 1))
|
|
AUTOWANT_ALL = bool(check_setting_int(CFG, 'General', 'autowant_all', 0))
|
|
KEEP_TORRENT_FILES = bool(check_setting_int(CFG, 'General', 'keep_torrent_files', 0))
|
|
PREFER_TORRENTS = check_setting_int(CFG, 'General', 'prefer_torrents', 0)
|
|
OPEN_MAGNET_LINKS = bool(check_setting_int(CFG, 'General', 'open_magnet_links', 0))
|
|
|
|
SEARCH_INTERVAL = check_setting_int(CFG, 'General', 'search_interval', 1440)
|
|
LIBRARYSCAN = bool(check_setting_int(CFG, 'General', 'libraryscan', 1))
|
|
LIBRARYSCAN_INTERVAL = check_setting_int(CFG, 'General', 'libraryscan_interval', 300)
|
|
DOWNLOAD_SCAN_INTERVAL = check_setting_int(CFG, 'General', 'download_scan_interval', 5)
|
|
UPDATE_DB_INTERVAL = check_setting_int(CFG, 'General', 'update_db_interval', 24)
|
|
MB_IGNORE_AGE = check_setting_int(CFG, 'General', 'mb_ignore_age', 365)
|
|
|
|
TORRENTBLACKHOLE_DIR = check_setting_str(CFG, 'General', 'torrentblackhole_dir', '')
|
|
NUMBEROFSEEDERS = check_setting_str(CFG, 'General', 'numberofseeders', '10')
|
|
ISOHUNT = bool(check_setting_int(CFG, 'General', 'isohunt', 0))
|
|
KAT = bool(check_setting_int(CFG, 'General', 'kat', 0))
|
|
PIRATEBAY = bool(check_setting_int(CFG, 'General', 'piratebay', 0))
|
|
PIRATEBAY_PROXY_URL = check_setting_str(CFG, 'General', 'piratebay_proxy_url', '')
|
|
MININOVA = bool(check_setting_int(CFG, 'General', 'mininova', 0))
|
|
DOWNLOAD_TORRENT_DIR = check_setting_str(CFG, 'General', 'download_torrent_dir', '')
|
|
|
|
WAFFLES = bool(check_setting_int(CFG, 'Waffles', 'waffles', 0))
|
|
WAFFLES_UID = check_setting_str(CFG, 'Waffles', 'waffles_uid', '')
|
|
WAFFLES_PASSKEY = check_setting_str(CFG, 'Waffles', 'waffles_passkey', '')
|
|
|
|
RUTRACKER = bool(check_setting_int(CFG, 'Rutracker', 'rutracker', 0))
|
|
RUTRACKER_USER = check_setting_str(CFG, 'Rutracker', 'rutracker_user', '')
|
|
RUTRACKER_PASSWORD = check_setting_str(CFG, 'Rutracker', 'rutracker_password', '')
|
|
|
|
WHATCD = bool(check_setting_int(CFG, 'What.cd', 'whatcd', 0))
|
|
WHATCD_USERNAME = check_setting_str(CFG, 'What.cd', 'whatcd_username', '')
|
|
WHATCD_PASSWORD = check_setting_str(CFG, 'What.cd', 'whatcd_password', '')
|
|
|
|
SAB_HOST = check_setting_str(CFG, 'SABnzbd', 'sab_host', '')
|
|
SAB_USERNAME = check_setting_str(CFG, 'SABnzbd', 'sab_username', '')
|
|
SAB_PASSWORD = check_setting_str(CFG, 'SABnzbd', 'sab_password', '')
|
|
SAB_APIKEY = check_setting_str(CFG, 'SABnzbd', 'sab_apikey', '')
|
|
SAB_CATEGORY = check_setting_str(CFG, 'SABnzbd', 'sab_category', '')
|
|
|
|
NZBGET_USERNAME = check_setting_str(CFG, 'NZBget', 'nzbget_username', 'nzbget')
|
|
NZBGET_PASSWORD = check_setting_str(CFG, 'NZBget', 'nzbget_password', '')
|
|
NZBGET_CATEGORY = check_setting_str(CFG, 'NZBget', 'nzbget_category', '')
|
|
NZBGET_HOST = check_setting_str(CFG, 'NZBget', 'nzbget_host', '')
|
|
|
|
HEADPHONES_INDEXER = bool(check_setting_int(CFG, 'Headphones', 'headphones_indexer', 0))
|
|
|
|
TRANSMISSION_HOST = check_setting_str(CFG, 'Transmission', 'transmission_host', '')
|
|
TRANSMISSION_USERNAME = check_setting_str(CFG, 'Transmission', 'transmission_username', '')
|
|
TRANSMISSION_PASSWORD = check_setting_str(CFG, 'Transmission', 'transmission_password', '')
|
|
|
|
UTORRENT_HOST = check_setting_str(CFG, 'uTorrent', 'utorrent_host', '')
|
|
UTORRENT_USERNAME = check_setting_str(CFG, 'uTorrent', 'utorrent_username', '')
|
|
UTORRENT_PASSWORD = check_setting_str(CFG, 'uTorrent', 'utorrent_password', '')
|
|
|
|
NEWZNAB = bool(check_setting_int(CFG, 'Newznab', 'newznab', 0))
|
|
NEWZNAB_HOST = check_setting_str(CFG, 'Newznab', 'newznab_host', '')
|
|
NEWZNAB_APIKEY = check_setting_str(CFG, 'Newznab', 'newznab_apikey', '')
|
|
NEWZNAB_ENABLED = bool(check_setting_int(CFG, 'Newznab', 'newznab_enabled', 1))
|
|
|
|
# Need to pack the extra newznabs back into a list of tuples
|
|
flattened_newznabs = check_setting_str(CFG, 'Newznab', 'extra_newznabs', [], log=False)
|
|
EXTRA_NEWZNABS = list(itertools.izip(*[itertools.islice(flattened_newznabs, i, None, 3) for i in range(3)]))
|
|
|
|
NZBSORG = bool(check_setting_int(CFG, 'NZBsorg', 'nzbsorg', 0))
|
|
NZBSORG_UID = check_setting_str(CFG, 'NZBsorg', 'nzbsorg_uid', '')
|
|
NZBSORG_HASH = check_setting_str(CFG, 'NZBsorg', 'nzbsorg_hash', '')
|
|
|
|
NZBSRUS = bool(check_setting_int(CFG, 'NZBsRus', 'nzbsrus', 0))
|
|
NZBSRUS_UID = check_setting_str(CFG, 'NZBsRus', 'nzbsrus_uid', '')
|
|
NZBSRUS_APIKEY = check_setting_str(CFG, 'NZBsRus', 'nzbsrus_apikey', '')
|
|
|
|
OMGWTFNZBS = bool(check_setting_int(CFG, 'omgwtfnzbs', 'omgwtfnzbs', 0))
|
|
OMGWTFNZBS_UID = check_setting_str(CFG, 'omgwtfnzbs', 'omgwtfnzbs_uid', '')
|
|
OMGWTFNZBS_APIKEY = check_setting_str(CFG, 'omgwtfnzbs', 'omgwtfnzbs_apikey', '')
|
|
|
|
PREFERRED_WORDS = check_setting_str(CFG, 'General', 'preferred_words', '')
|
|
IGNORED_WORDS = check_setting_str(CFG, 'General', 'ignored_words', '')
|
|
REQUIRED_WORDS = check_setting_str(CFG, 'General', 'required_words', '')
|
|
|
|
LASTFM_USERNAME = check_setting_str(CFG, 'General', 'lastfm_username', '')
|
|
|
|
INTERFACE = check_setting_str(CFG, 'General', 'interface', 'default')
|
|
FOLDER_PERMISSIONS = check_setting_str(CFG, 'General', 'folder_permissions', '0755')
|
|
FILE_PERMISSIONS = check_setting_str(CFG, 'General', 'file_permissions', '0644')
|
|
|
|
ENCODERFOLDER = check_setting_str(CFG, 'General', 'encoderfolder', '')
|
|
ENCODER_PATH = check_setting_str(CFG, 'General', 'encoder_path', '')
|
|
ENCODER = check_setting_str(CFG, 'General', 'encoder', 'ffmpeg')
|
|
XLDPROFILE = check_setting_str(CFG, 'General', 'xldprofile', '')
|
|
BITRATE = check_setting_int(CFG, 'General', 'bitrate', 192)
|
|
SAMPLINGFREQUENCY= check_setting_int(CFG, 'General', 'samplingfrequency', 44100)
|
|
MUSIC_ENCODER = bool(check_setting_int(CFG, 'General', 'music_encoder', 0))
|
|
ADVANCEDENCODER = check_setting_str(CFG, 'General', 'advancedencoder', '')
|
|
ENCODEROUTPUTFORMAT = check_setting_str(CFG, 'General', 'encoderoutputformat', 'mp3')
|
|
ENCODERQUALITY = check_setting_int(CFG, 'General', 'encoderquality', 2)
|
|
ENCODERVBRCBR = check_setting_str(CFG, 'General', 'encodervbrcbr', 'cbr')
|
|
ENCODERLOSSLESS = bool(check_setting_int(CFG, 'General', 'encoderlossless', 1))
|
|
ENCODER_MULTICORE = bool(check_setting_int(CFG, 'General', 'encoder_multicore', 0))
|
|
ENCODER_MULTICORE_COUNT = max(0, check_setting_int(CFG, 'General', 'encoder_multicore_count', 0))
|
|
DELETE_LOSSLESS_FILES = bool(check_setting_int(CFG, 'General', 'delete_lossless_files', 1))
|
|
|
|
GROWL_ENABLED = bool(check_setting_int(CFG, 'Growl', 'growl_enabled', 0))
|
|
GROWL_HOST = check_setting_str(CFG, 'Growl', 'growl_host', '')
|
|
GROWL_PASSWORD = check_setting_str(CFG, 'Growl', 'growl_password', '')
|
|
GROWL_ONSNATCH = bool(check_setting_int(CFG, 'Growl', 'growl_onsnatch', 0))
|
|
|
|
PROWL_ENABLED = bool(check_setting_int(CFG, 'Prowl', 'prowl_enabled', 0))
|
|
PROWL_KEYS = check_setting_str(CFG, 'Prowl', 'prowl_keys', '')
|
|
PROWL_ONSNATCH = bool(check_setting_int(CFG, 'Prowl', 'prowl_onsnatch', 0))
|
|
PROWL_PRIORITY = check_setting_int(CFG, 'Prowl', 'prowl_priority', 0)
|
|
|
|
XBMC_ENABLED = bool(check_setting_int(CFG, 'XBMC', 'xbmc_enabled', 0))
|
|
XBMC_HOST = check_setting_str(CFG, 'XBMC', 'xbmc_host', '')
|
|
XBMC_USERNAME = check_setting_str(CFG, 'XBMC', 'xbmc_username', '')
|
|
XBMC_PASSWORD = check_setting_str(CFG, 'XBMC', 'xbmc_password', '')
|
|
XBMC_UPDATE = bool(check_setting_int(CFG, 'XBMC', 'xbmc_update', 0))
|
|
XBMC_NOTIFY = bool(check_setting_int(CFG, 'XBMC', 'xbmc_notify', 0))
|
|
|
|
LMS_ENABLED = bool(check_setting_int(CFG, 'LMS', 'lms_enabled', 0))
|
|
LMS_HOST = check_setting_str(CFG, 'LMS', 'lms_host', '')
|
|
|
|
PLEX_ENABLED = bool(check_setting_int(CFG, 'Plex', 'plex_enabled', 0))
|
|
PLEX_SERVER_HOST = check_setting_str(CFG, 'Plex', 'plex_server_host', '')
|
|
PLEX_CLIENT_HOST = check_setting_str(CFG, 'Plex', 'plex_client_host', '')
|
|
PLEX_USERNAME = check_setting_str(CFG, 'Plex', 'plex_username', '')
|
|
PLEX_PASSWORD = check_setting_str(CFG, 'Plex', 'plex_password', '')
|
|
PLEX_UPDATE = bool(check_setting_int(CFG, 'Plex', 'plex_update', 0))
|
|
PLEX_NOTIFY = bool(check_setting_int(CFG, 'Plex', 'plex_notify', 0))
|
|
|
|
NMA_ENABLED = bool(check_setting_int(CFG, 'NMA', 'nma_enabled', 0))
|
|
NMA_APIKEY = check_setting_str(CFG, 'NMA', 'nma_apikey', '')
|
|
NMA_PRIORITY = check_setting_int(CFG, 'NMA', 'nma_priority', 0)
|
|
NMA_ONSNATCH = bool(check_setting_int(CFG, 'NMA', 'nma_onsnatch', 0))
|
|
|
|
PUSHALOT_ENABLED = bool(check_setting_int(CFG, 'Pushalot', 'pushalot_enabled', 0))
|
|
PUSHALOT_APIKEY = check_setting_str(CFG, 'Pushalot', 'pushalot_apikey', '')
|
|
PUSHALOT_ONSNATCH = bool(check_setting_int(CFG, 'Pushalot', 'pushalot_onsnatch', 0))
|
|
|
|
SYNOINDEX_ENABLED = bool(check_setting_int(CFG, 'Synoindex', 'synoindex_enabled', 0))
|
|
|
|
PUSHOVER_ENABLED = bool(check_setting_int(CFG, 'Pushover', 'pushover_enabled', 0))
|
|
PUSHOVER_KEYS = check_setting_str(CFG, 'Pushover', 'pushover_keys', '')
|
|
PUSHOVER_ONSNATCH = bool(check_setting_int(CFG, 'Pushover', 'pushover_onsnatch', 0))
|
|
PUSHOVER_PRIORITY = check_setting_int(CFG, 'Pushover', 'pushover_priority', 0)
|
|
PUSHOVER_APITOKEN = check_setting_str(CFG, 'Pushover', 'pushover_apitoken', '')
|
|
|
|
PUSHBULLET_ENABLED = bool(check_setting_int(CFG, 'PushBullet', 'pushbullet_enabled', 0))
|
|
PUSHBULLET_APIKEY = check_setting_str(CFG, 'PushBullet', 'pushbullet_apikey', '')
|
|
PUSHBULLET_DEVICEID = check_setting_str(CFG, 'PushBullet', 'pushbullet_deviceid', '')
|
|
PUSHBULLET_ONSNATCH = bool(check_setting_int(CFG, 'PushBullet', 'pushbullet_onsnatch', 0))
|
|
|
|
TWITTER_ENABLED = bool(check_setting_int(CFG, 'Twitter', 'twitter_enabled', 0))
|
|
TWITTER_ONSNATCH = bool(check_setting_int(CFG, 'Twitter', 'twitter_onsnatch', 0))
|
|
TWITTER_USERNAME = check_setting_str(CFG, 'Twitter', 'twitter_username', '')
|
|
TWITTER_PASSWORD = check_setting_str(CFG, 'Twitter', 'twitter_password', '')
|
|
TWITTER_PREFIX = check_setting_str(CFG, 'Twitter', 'twitter_prefix', 'Headphones')
|
|
|
|
SONGKICK_ENABLED = bool(check_setting_int(CFG, 'Songkick', 'songkick_enabled', 1))
|
|
SONGKICK_APIKEY = check_setting_str(CFG, 'Songkick', 'songkick_apikey', 'nd1We7dFW2RqxPw8')
|
|
SONGKICK_LOCATION = check_setting_str(CFG, 'Songkick', 'songkick_location', '')
|
|
SONGKICK_FILTER_ENABLED = bool(check_setting_int(CFG, 'Songkick', 'songkick_filter_enabled', 0))
|
|
|
|
MIRROR = check_setting_str(CFG, 'General', 'mirror', 'musicbrainz.org')
|
|
CUSTOMHOST = check_setting_str(CFG, 'General', 'customhost', 'localhost')
|
|
CUSTOMPORT = check_setting_int(CFG, 'General', 'customport', 5000)
|
|
CUSTOMSLEEP = check_setting_int(CFG, 'General', 'customsleep', 1)
|
|
HPUSER = check_setting_str(CFG, 'General', 'hpuser', '')
|
|
HPPASS = check_setting_str(CFG, 'General', 'hppass', '')
|
|
|
|
CACHE_SIZEMB = check_setting_int(CFG,'Advanced','cache_sizemb',32)
|
|
JOURNAL_MODE = check_setting_int(CFG,'Advanced', 'journal_mode', 'wal')
|
|
|
|
ALBUM_COMPLETION_PCT = check_setting_int(CFG, 'Advanced', 'album_completion_pct', 80)
|
|
|
|
# update folder formats in the config & bump up config version
|
|
if CONFIG_VERSION == '0':
|
|
from headphones.helpers import replace_all
|
|
file_values = { 'tracknumber': 'Track', 'title': 'Title','artist' : 'Artist', 'album' : 'Album', 'year' : 'Year' }
|
|
folder_values = { 'artist' : 'Artist', 'album':'Album', 'year' : 'Year', 'releasetype' : 'Type', 'first' : 'First', 'lowerfirst' : 'first' }
|
|
FILE_FORMAT = replace_all(FILE_FORMAT, file_values)
|
|
FOLDER_FORMAT = replace_all(FOLDER_FORMAT, folder_values)
|
|
|
|
CONFIG_VERSION = '1'
|
|
|
|
if CONFIG_VERSION == '1':
|
|
|
|
from headphones.helpers import replace_all
|
|
|
|
file_values = { 'Track': '$Track',
|
|
'Title': '$Title',
|
|
'Artist': '$Artist',
|
|
'Album': '$Album',
|
|
'Year': '$Year',
|
|
'track': '$track',
|
|
'title': '$title',
|
|
'artist': '$artist',
|
|
'album': '$album',
|
|
'year': '$year'
|
|
}
|
|
folder_values = { 'Artist': '$Artist',
|
|
'Album': '$Album',
|
|
'Year': '$Year',
|
|
'Type': '$Type',
|
|
'First': '$First',
|
|
'artist': '$artist',
|
|
'album': '$album',
|
|
'year': '$year',
|
|
'type': '$type',
|
|
'first': '$first'
|
|
}
|
|
FILE_FORMAT = replace_all(FILE_FORMAT, file_values)
|
|
FOLDER_FORMAT = replace_all(FOLDER_FORMAT, folder_values)
|
|
|
|
CONFIG_VERSION = '2'
|
|
|
|
if CONFIG_VERSION == '2':
|
|
|
|
# Update the config to use direct path to the encoder rather than the encoder folder
|
|
if ENCODERFOLDER:
|
|
ENCODER_PATH = os.path.join(ENCODERFOLDER, ENCODER)
|
|
CONFIG_VERSION = '3'
|
|
|
|
if CONFIG_VERSION == '3':
|
|
#Update the BLACKHOLE option to the NZB_DOWNLOADER format
|
|
if BLACKHOLE:
|
|
NZB_DOWNLOADER = 2
|
|
CONFIG_VERSION = '4'
|
|
|
|
# Enable Headphones Indexer if they have a VIP account
|
|
if CONFIG_VERSION == '4':
|
|
if HPUSER and HPPASS:
|
|
HEADPHONES_INDEXER = True
|
|
CONFIG_VERSION = '5'
|
|
|
|
if not LOG_DIR:
|
|
LOG_DIR = os.path.join(DATA_DIR, 'logs')
|
|
|
|
if not os.path.exists(LOG_DIR):
|
|
try:
|
|
os.makedirs(LOG_DIR)
|
|
except OSError:
|
|
if VERBOSE:
|
|
sys.stderr.write('Unable to create the log directory. Logging to screen only.\n')
|
|
|
|
# Start the logger, silence console logging if we need to
|
|
logger.initLogger(verbose=VERBOSE)
|
|
|
|
if not CACHE_DIR:
|
|
# Put the cache dir in the data dir for now
|
|
CACHE_DIR = os.path.join(DATA_DIR, 'cache')
|
|
if not os.path.exists(CACHE_DIR):
|
|
try:
|
|
os.makedirs(CACHE_DIR)
|
|
except OSError:
|
|
logger.error('Could not create cache dir. Check permissions of datadir: %s', DATA_DIR)
|
|
|
|
# Sanity check for search interval. Set it to at least 6 hours
|
|
if SEARCH_INTERVAL < 360:
|
|
logger.info("Search interval too low. Resetting to 6 hour minimum")
|
|
SEARCH_INTERVAL = 360
|
|
|
|
# Initialize the database
|
|
logger.info('Checking to see if the database has all tables....')
|
|
try:
|
|
dbcheck()
|
|
except Exception, e:
|
|
logger.error("Can't connect to the database: %s", e)
|
|
|
|
# Get the currently installed version - returns None, 'win32' or the git hash
|
|
# Also sets INSTALL_TYPE variable to 'win', 'git' or 'source'
|
|
CURRENT_VERSION, GIT_BRANCH = versioncheck.getVersion()
|
|
|
|
# Check for new versions
|
|
if CHECK_GITHUB_ON_STARTUP:
|
|
try:
|
|
LATEST_VERSION = versioncheck.checkGithub()
|
|
except:
|
|
logger.exception("Unhandled exception")
|
|
LATEST_VERSION = CURRENT_VERSION
|
|
else:
|
|
LATEST_VERSION = CURRENT_VERSION
|
|
|
|
# Store the original umask
|
|
UMASK = os.umask(0)
|
|
os.umask(UMASK)
|
|
|
|
__INITIALIZED__ = True
|
|
return True
|
|
|
|
def daemonize():
|
|
|
|
if threading.activeCount() != 1:
|
|
logger.warn('There are %r active threads. Daemonizing may cause \
|
|
strange behavior.' % threading.enumerate())
|
|
|
|
sys.stdout.flush()
|
|
sys.stderr.flush()
|
|
|
|
# Do first fork
|
|
try:
|
|
pid = os.fork() # @UndefinedVariable - only available in UNIX
|
|
if pid != 0:
|
|
sys.exit(0)
|
|
except OSError, e:
|
|
raise RuntimeError("1st fork failed: %s [%d]", e.strerror, e.errno)
|
|
|
|
os.setsid()
|
|
|
|
# Make sure I can read my own files and shut out others
|
|
prev = os.umask(0) # @UndefinedVariable - only available in UNIX
|
|
os.umask(prev and int('077', 8))
|
|
|
|
# Make the child a session-leader by detaching from the terminal
|
|
try:
|
|
pid = os.fork() # @UndefinedVariable - only available in UNIX
|
|
if pid != 0:
|
|
sys.exit(0)
|
|
except OSError, e:
|
|
raise RuntimeError("2nd fork failed: %s [%d]", e.strerror, e.errno)
|
|
|
|
dev_null = file('/dev/null', 'r')
|
|
os.dup2(dev_null.fileno(), sys.stdin.fileno())
|
|
|
|
si = open('/dev/null', "r")
|
|
so = open('/dev/null', "a+")
|
|
se = open('/dev/null', "a+")
|
|
|
|
os.dup2(si.fileno(), sys.stdin.fileno())
|
|
os.dup2(so.fileno(), sys.stdout.fileno())
|
|
os.dup2(se.fileno(), sys.stderr.fileno())
|
|
|
|
pid = os.getpid()
|
|
logger.info('Daemonized to PID: %d', pid)
|
|
|
|
if CREATEPID:
|
|
logger.info("Writing PID %d to %s", pid, PIDFILE)
|
|
with file(PIDFILE, 'w') as fp:
|
|
fp.write("%s\n" % pid)
|
|
|
|
def launch_browser(host, port, root):
|
|
|
|
if host == '0.0.0.0':
|
|
host = 'localhost'
|
|
|
|
if ENABLE_HTTPS:
|
|
protocol = 'https'
|
|
else:
|
|
protocol = 'http'
|
|
|
|
try:
|
|
webbrowser.open('%s://%s:%i%s' % (protocol, host, port, root))
|
|
except Exception, e:
|
|
logger.error('Could not launch browser: %s', e)
|
|
|
|
def config_write():
|
|
|
|
new_config = ConfigObj(encoding="UTF-8")
|
|
new_config.filename = CONFIG_FILE
|
|
|
|
new_config['General'] = {}
|
|
new_config['General']['config_version'] = CONFIG_VERSION
|
|
new_config['General']['http_port'] = HTTP_PORT
|
|
new_config['General']['http_host'] = HTTP_HOST
|
|
new_config['General']['http_username'] = HTTP_USERNAME
|
|
new_config['General']['http_password'] = HTTP_PASSWORD
|
|
new_config['General']['http_root'] = HTTP_ROOT
|
|
new_config['General']['http_proxy'] = int(HTTP_PROXY)
|
|
new_config['General']['enable_https'] = int(ENABLE_HTTPS)
|
|
new_config['General']['https_cert'] = HTTPS_CERT
|
|
new_config['General']['https_key'] = HTTPS_KEY
|
|
new_config['General']['launch_browser'] = int(LAUNCH_BROWSER)
|
|
new_config['General']['api_enabled'] = int(API_ENABLED)
|
|
new_config['General']['api_key'] = API_KEY
|
|
new_config['General']['log_dir'] = LOG_DIR
|
|
new_config['General']['cache_dir'] = CACHE_DIR
|
|
new_config['General']['git_path'] = GIT_PATH
|
|
new_config['General']['git_user'] = GIT_USER
|
|
new_config['General']['git_branch'] = GIT_BRANCH
|
|
new_config['General']['do_not_override_git_branch'] = int(DO_NOT_OVERRIDE_GIT_BRANCH)
|
|
|
|
new_config['General']['check_github'] = int(CHECK_GITHUB)
|
|
new_config['General']['check_github_on_startup'] = int(CHECK_GITHUB_ON_STARTUP)
|
|
new_config['General']['check_github_interval'] = CHECK_GITHUB_INTERVAL
|
|
|
|
new_config['General']['music_dir'] = MUSIC_DIR
|
|
new_config['General']['destination_dir'] = DESTINATION_DIR
|
|
new_config['General']['lossless_destination_dir'] = LOSSLESS_DESTINATION_DIR
|
|
new_config['General']['preferred_quality'] = PREFERRED_QUALITY
|
|
new_config['General']['preferred_bitrate'] = PREFERRED_BITRATE
|
|
new_config['General']['preferred_bitrate_high_buffer'] = PREFERRED_BITRATE_HIGH_BUFFER
|
|
new_config['General']['preferred_bitrate_low_buffer'] = PREFERRED_BITRATE_LOW_BUFFER
|
|
new_config['General']['preferred_bitrate_allow_lossless'] = int(PREFERRED_BITRATE_ALLOW_LOSSLESS)
|
|
new_config['General']['detect_bitrate'] = int(DETECT_BITRATE)
|
|
new_config['General']['auto_add_artists'] = int(ADD_ARTISTS)
|
|
new_config['General']['correct_metadata'] = int(CORRECT_METADATA)
|
|
new_config['General']['move_files'] = int(MOVE_FILES)
|
|
new_config['General']['rename_files'] = int(RENAME_FILES)
|
|
new_config['General']['folder_format'] = FOLDER_FORMAT
|
|
new_config['General']['file_format'] = FILE_FORMAT
|
|
new_config['General']['file_underscores'] = int(FILE_UNDERSCORES)
|
|
new_config['General']['cleanup_files'] = int(CLEANUP_FILES)
|
|
new_config['General']['add_album_art'] = int(ADD_ALBUM_ART)
|
|
new_config['General']['album_art_format'] = ALBUM_ART_FORMAT
|
|
new_config['General']['embed_album_art'] = int(EMBED_ALBUM_ART)
|
|
new_config['General']['embed_lyrics'] = int(EMBED_LYRICS)
|
|
new_config['General']['replace_existing_folders'] = int(REPLACE_EXISTING_FOLDERS)
|
|
new_config['General']['nzb_downloader'] = NZB_DOWNLOADER
|
|
new_config['General']['torrent_downloader'] = TORRENT_DOWNLOADER
|
|
new_config['General']['download_dir'] = DOWNLOAD_DIR
|
|
new_config['General']['blackhole_dir'] = BLACKHOLE_DIR
|
|
new_config['General']['usenet_retention'] = USENET_RETENTION
|
|
new_config['General']['include_extras'] = int(INCLUDE_EXTRAS)
|
|
new_config['General']['extras'] = EXTRAS
|
|
new_config['General']['autowant_upcoming'] = int(AUTOWANT_UPCOMING)
|
|
new_config['General']['autowant_all'] = int(AUTOWANT_ALL)
|
|
new_config['General']['keep_torrent_files'] = int(KEEP_TORRENT_FILES)
|
|
new_config['General']['prefer_torrents'] = PREFER_TORRENTS
|
|
new_config['General']['open_magnet_links'] = OPEN_MAGNET_LINKS
|
|
|
|
new_config['General']['numberofseeders'] = NUMBEROFSEEDERS
|
|
new_config['General']['torrentblackhole_dir'] = TORRENTBLACKHOLE_DIR
|
|
new_config['General']['isohunt'] = int(ISOHUNT)
|
|
new_config['General']['kat'] = int(KAT)
|
|
new_config['General']['mininova'] = int(MININOVA)
|
|
new_config['General']['piratebay'] = int(PIRATEBAY)
|
|
new_config['General']['piratebay_proxy_url'] = PIRATEBAY_PROXY_URL
|
|
new_config['General']['download_torrent_dir'] = DOWNLOAD_TORRENT_DIR
|
|
|
|
new_config['Waffles'] = {}
|
|
new_config['Waffles']['waffles'] = int(WAFFLES)
|
|
new_config['Waffles']['waffles_uid'] = WAFFLES_UID
|
|
new_config['Waffles']['waffles_passkey'] = WAFFLES_PASSKEY
|
|
|
|
new_config['Rutracker'] = {}
|
|
new_config['Rutracker']['rutracker'] = int(RUTRACKER)
|
|
new_config['Rutracker']['rutracker_user'] = RUTRACKER_USER
|
|
new_config['Rutracker']['rutracker_password'] = RUTRACKER_PASSWORD
|
|
|
|
new_config['What.cd'] = {}
|
|
new_config['What.cd']['whatcd'] = int(WHATCD)
|
|
new_config['What.cd']['whatcd_username'] = WHATCD_USERNAME
|
|
new_config['What.cd']['whatcd_password'] = WHATCD_PASSWORD
|
|
|
|
new_config['General']['search_interval'] = SEARCH_INTERVAL
|
|
new_config['General']['libraryscan'] = int(LIBRARYSCAN)
|
|
new_config['General']['libraryscan_interval'] = LIBRARYSCAN_INTERVAL
|
|
new_config['General']['download_scan_interval'] = DOWNLOAD_SCAN_INTERVAL
|
|
new_config['General']['update_db_interval'] = UPDATE_DB_INTERVAL
|
|
new_config['General']['mb_ignore_age'] = MB_IGNORE_AGE
|
|
|
|
new_config['SABnzbd'] = {}
|
|
new_config['SABnzbd']['sab_host'] = SAB_HOST
|
|
new_config['SABnzbd']['sab_username'] = SAB_USERNAME
|
|
new_config['SABnzbd']['sab_password'] = SAB_PASSWORD
|
|
new_config['SABnzbd']['sab_apikey'] = SAB_APIKEY
|
|
new_config['SABnzbd']['sab_category'] = SAB_CATEGORY
|
|
|
|
new_config['NZBget'] = {}
|
|
new_config['NZBget']['nzbget_username'] = NZBGET_USERNAME
|
|
new_config['NZBget']['nzbget_password'] = NZBGET_PASSWORD
|
|
new_config['NZBget']['nzbget_category'] = NZBGET_CATEGORY
|
|
new_config['NZBget']['nzbget_host'] = NZBGET_HOST
|
|
|
|
new_config['Headphones'] = {}
|
|
new_config['Headphones']['headphones_indexer'] = int(HEADPHONES_INDEXER)
|
|
|
|
new_config['Transmission'] = {}
|
|
new_config['Transmission']['transmission_host'] = TRANSMISSION_HOST
|
|
new_config['Transmission']['transmission_username'] = TRANSMISSION_USERNAME
|
|
new_config['Transmission']['transmission_password'] = TRANSMISSION_PASSWORD
|
|
|
|
new_config['uTorrent'] = {}
|
|
new_config['uTorrent']['utorrent_host'] = UTORRENT_HOST
|
|
new_config['uTorrent']['utorrent_username'] = UTORRENT_USERNAME
|
|
new_config['uTorrent']['utorrent_password'] = UTORRENT_PASSWORD
|
|
|
|
new_config['Newznab'] = {}
|
|
new_config['Newznab']['newznab'] = int(NEWZNAB)
|
|
new_config['Newznab']['newznab_host'] = NEWZNAB_HOST
|
|
new_config['Newznab']['newznab_apikey'] = NEWZNAB_APIKEY
|
|
new_config['Newznab']['newznab_enabled'] = int(NEWZNAB_ENABLED)
|
|
# Need to unpack the extra newznabs for saving in config.ini
|
|
flattened_newznabs = []
|
|
for newznab in EXTRA_NEWZNABS:
|
|
for item in newznab:
|
|
flattened_newznabs.append(item)
|
|
|
|
new_config['Newznab']['extra_newznabs'] = flattened_newznabs
|
|
|
|
new_config['NZBsorg'] = {}
|
|
new_config['NZBsorg']['nzbsorg'] = int(NZBSORG)
|
|
new_config['NZBsorg']['nzbsorg_uid'] = NZBSORG_UID
|
|
new_config['NZBsorg']['nzbsorg_hash'] = NZBSORG_HASH
|
|
|
|
new_config['NZBsRus'] = {}
|
|
new_config['NZBsRus']['nzbsrus'] = int(NZBSRUS)
|
|
new_config['NZBsRus']['nzbsrus_uid'] = NZBSRUS_UID
|
|
new_config['NZBsRus']['nzbsrus_apikey'] = NZBSRUS_APIKEY
|
|
|
|
new_config['omgwtfnzbs'] = {}
|
|
new_config['omgwtfnzbs']['omgwtfnzbs'] = int(OMGWTFNZBS)
|
|
new_config['omgwtfnzbs']['omgwtfnzbs_uid'] = OMGWTFNZBS_UID
|
|
new_config['omgwtfnzbs']['omgwtfnzbs_apikey'] = OMGWTFNZBS_APIKEY
|
|
|
|
new_config['General']['preferred_words'] = PREFERRED_WORDS
|
|
new_config['General']['ignored_words'] = IGNORED_WORDS
|
|
new_config['General']['required_words'] = REQUIRED_WORDS
|
|
|
|
new_config['Growl'] = {}
|
|
new_config['Growl']['growl_enabled'] = int(GROWL_ENABLED)
|
|
new_config['Growl']['growl_host'] = GROWL_HOST
|
|
new_config['Growl']['growl_password'] = GROWL_PASSWORD
|
|
new_config['Growl']['growl_onsnatch'] = int(GROWL_ONSNATCH)
|
|
|
|
new_config['Prowl'] = {}
|
|
new_config['Prowl']['prowl_enabled'] = int(PROWL_ENABLED)
|
|
new_config['Prowl']['prowl_keys'] = PROWL_KEYS
|
|
new_config['Prowl']['prowl_onsnatch'] = int(PROWL_ONSNATCH)
|
|
new_config['Prowl']['prowl_priority'] = int(PROWL_PRIORITY)
|
|
|
|
new_config['XBMC'] = {}
|
|
new_config['XBMC']['xbmc_enabled'] = int(XBMC_ENABLED)
|
|
new_config['XBMC']['xbmc_host'] = XBMC_HOST
|
|
new_config['XBMC']['xbmc_username'] = XBMC_USERNAME
|
|
new_config['XBMC']['xbmc_password'] = XBMC_PASSWORD
|
|
new_config['XBMC']['xbmc_update'] = int(XBMC_UPDATE)
|
|
new_config['XBMC']['xbmc_notify'] = int(XBMC_NOTIFY)
|
|
|
|
new_config['LMS'] = {}
|
|
new_config['LMS']['lms_enabled'] = int(LMS_ENABLED)
|
|
new_config['LMS']['lms_host'] = LMS_HOST
|
|
|
|
new_config['Plex'] = {}
|
|
new_config['Plex']['plex_enabled'] = int(PLEX_ENABLED)
|
|
new_config['Plex']['plex_server_host'] = PLEX_SERVER_HOST
|
|
new_config['Plex']['plex_client_host'] = PLEX_CLIENT_HOST
|
|
new_config['Plex']['plex_username'] = PLEX_USERNAME
|
|
new_config['Plex']['plex_password'] = PLEX_PASSWORD
|
|
new_config['Plex']['plex_update'] = int(PLEX_UPDATE)
|
|
new_config['Plex']['plex_notify'] = int(PLEX_NOTIFY)
|
|
|
|
new_config['NMA'] = {}
|
|
new_config['NMA']['nma_enabled'] = int(NMA_ENABLED)
|
|
new_config['NMA']['nma_apikey'] = NMA_APIKEY
|
|
new_config['NMA']['nma_priority'] = NMA_PRIORITY
|
|
new_config['NMA']['nma_onsnatch'] = int(NMA_ONSNATCH)
|
|
|
|
new_config['Pushalot'] = {}
|
|
new_config['Pushalot']['pushalot_enabled'] = int(PUSHALOT_ENABLED)
|
|
new_config['Pushalot']['pushalot_apikey'] = PUSHALOT_APIKEY
|
|
new_config['Pushalot']['pushalot_onsnatch'] = int(PUSHALOT_ONSNATCH)
|
|
|
|
new_config['Pushover'] = {}
|
|
new_config['Pushover']['pushover_enabled'] = int(PUSHOVER_ENABLED)
|
|
new_config['Pushover']['pushover_keys'] = PUSHOVER_KEYS
|
|
new_config['Pushover']['pushover_onsnatch'] = int(PUSHOVER_ONSNATCH)
|
|
new_config['Pushover']['pushover_priority'] = int(PUSHOVER_PRIORITY)
|
|
new_config['Pushover']['pushover_apitoken'] = PUSHOVER_APITOKEN
|
|
|
|
new_config['PushBullet'] = {}
|
|
new_config['PushBullet']['pushbullet_enabled'] = int(PUSHBULLET_ENABLED)
|
|
new_config['PushBullet']['pushbullet_apikey'] = PUSHBULLET_APIKEY
|
|
new_config['PushBullet']['pushbullet_deviceid'] = PUSHBULLET_DEVICEID
|
|
new_config['PushBullet']['pushbullet_onsnatch'] = int(PUSHBULLET_ONSNATCH)
|
|
|
|
new_config['Twitter'] = {}
|
|
new_config['Twitter']['twitter_enabled'] = int(TWITTER_ENABLED)
|
|
new_config['Twitter']['twitter_onsnatch'] = int(TWITTER_ONSNATCH)
|
|
new_config['Twitter']['twitter_username'] = TWITTER_USERNAME
|
|
new_config['Twitter']['twitter_password'] = TWITTER_PASSWORD
|
|
new_config['Twitter']['twitter_prefix'] = TWITTER_PREFIX
|
|
|
|
new_config['Songkick'] = {}
|
|
new_config['Songkick']['songkick_enabled'] = int(SONGKICK_ENABLED)
|
|
new_config['Songkick']['songkick_apikey'] = SONGKICK_APIKEY
|
|
new_config['Songkick']['songkick_location'] = SONGKICK_LOCATION
|
|
new_config['Songkick']['songkick_filter_enabled'] = int(SONGKICK_FILTER_ENABLED)
|
|
|
|
new_config['Synoindex'] = {}
|
|
new_config['Synoindex']['synoindex_enabled'] = int(SYNOINDEX_ENABLED)
|
|
|
|
new_config['General']['lastfm_username'] = LASTFM_USERNAME
|
|
new_config['General']['interface'] = INTERFACE
|
|
new_config['General']['folder_permissions'] = FOLDER_PERMISSIONS
|
|
new_config['General']['file_permissions'] = FILE_PERMISSIONS
|
|
|
|
new_config['General']['music_encoder'] = int(MUSIC_ENCODER)
|
|
new_config['General']['encoder'] = ENCODER
|
|
new_config['General']['xldprofile'] = XLDPROFILE
|
|
new_config['General']['bitrate'] = int(BITRATE)
|
|
new_config['General']['samplingfrequency'] = int(SAMPLINGFREQUENCY)
|
|
new_config['General']['encoder_path'] = ENCODER_PATH
|
|
new_config['General']['advancedencoder'] = ADVANCEDENCODER
|
|
new_config['General']['encoderoutputformat'] = ENCODEROUTPUTFORMAT
|
|
new_config['General']['encoderquality'] = ENCODERQUALITY
|
|
new_config['General']['encodervbrcbr'] = ENCODERVBRCBR
|
|
new_config['General']['encoderlossless'] = int(ENCODERLOSSLESS)
|
|
new_config['General']['encoder_multicore'] = int(ENCODER_MULTICORE)
|
|
new_config['General']['encoder_multicore_count'] = int(ENCODER_MULTICORE_COUNT)
|
|
new_config['General']['delete_lossless_files'] = int(DELETE_LOSSLESS_FILES)
|
|
|
|
new_config['General']['mirror'] = MIRROR
|
|
new_config['General']['customhost'] = CUSTOMHOST
|
|
new_config['General']['customport'] = CUSTOMPORT
|
|
new_config['General']['customsleep'] = CUSTOMSLEEP
|
|
new_config['General']['hpuser'] = HPUSER
|
|
new_config['General']['hppass'] = HPPASS
|
|
|
|
new_config['Advanced'] = {}
|
|
new_config['Advanced']['album_completion_pct'] = ALBUM_COMPLETION_PCT
|
|
new_config['Advanced']['cache_sizemb'] = CACHE_SIZEMB
|
|
new_config['Advanced']['journal_mode'] = JOURNAL_MODE
|
|
|
|
new_config.write()
|
|
|
|
|
|
def start():
|
|
|
|
global __INITIALIZED__, started
|
|
|
|
if __INITIALIZED__:
|
|
|
|
# Start our scheduled background tasks
|
|
from headphones import updater, searcher, librarysync, postprocessor
|
|
|
|
SCHED.add_interval_job(updater.dbUpdate, hours=UPDATE_DB_INTERVAL)
|
|
SCHED.add_interval_job(searcher.searchforalbum, minutes=SEARCH_INTERVAL)
|
|
SCHED.add_interval_job(librarysync.libraryScan, hours=LIBRARYSCAN_INTERVAL, kwargs={'cron':True})
|
|
|
|
if CHECK_GITHUB:
|
|
SCHED.add_interval_job(versioncheck.checkGithub, minutes=CHECK_GITHUB_INTERVAL)
|
|
|
|
if DOWNLOAD_SCAN_INTERVAL > 0:
|
|
SCHED.add_interval_job(postprocessor.checkFolder, minutes=DOWNLOAD_SCAN_INTERVAL)
|
|
|
|
SCHED.start()
|
|
|
|
started = True
|
|
|
|
def sig_handler(signum=None, frame=None):
|
|
if type(signum) != type(None):
|
|
logger.info("Signal %i caught, saving and exiting...", signum)
|
|
shutdown()
|
|
|
|
def dbcheck():
|
|
|
|
conn=sqlite3.connect(DB_FILE)
|
|
c=conn.cursor()
|
|
c.execute('CREATE TABLE IF NOT EXISTS artists (ArtistID TEXT UNIQUE, ArtistName TEXT, ArtistSortName TEXT, DateAdded TEXT, Status TEXT, IncludeExtras INTEGER, LatestAlbum TEXT, ReleaseDate TEXT, AlbumID TEXT, HaveTracks INTEGER, TotalTracks INTEGER, LastUpdated TEXT, ArtworkURL TEXT, ThumbURL TEXT, Extras TEXT)')
|
|
c.execute('CREATE TABLE IF NOT EXISTS albums (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, ReleaseDate TEXT, DateAdded TEXT, AlbumID TEXT UNIQUE, Status TEXT, Type TEXT, ArtworkURL TEXT, ThumbURL TEXT, ReleaseID TEXT, ReleaseCountry TEXT, ReleaseFormat TEXT, SearchTerm TEXT)') # ReleaseFormat here means CD,Digital,Vinyl, etc. If using the default Headphones hybrid release, ReleaseID will equal AlbumID (AlbumID is releasegroup id)
|
|
c.execute('CREATE TABLE IF NOT EXISTS tracks (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, AlbumID TEXT, TrackTitle TEXT, TrackDuration, TrackID TEXT, TrackNumber INTEGER, Location TEXT, BitRate INTEGER, CleanName TEXT, Format TEXT, ReleaseID TEXT)') # Format here means mp3, flac, etc.
|
|
c.execute('CREATE TABLE IF NOT EXISTS allalbums (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, ReleaseDate TEXT, AlbumID TEXT, Type TEXT, ReleaseID TEXT, ReleaseCountry TEXT, ReleaseFormat TEXT)')
|
|
c.execute('CREATE TABLE IF NOT EXISTS alltracks (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, AlbumID TEXT, TrackTitle TEXT, TrackDuration, TrackID TEXT, TrackNumber INTEGER, Location TEXT, BitRate INTEGER, CleanName TEXT, Format TEXT, ReleaseID TEXT)')
|
|
c.execute('CREATE TABLE IF NOT EXISTS snatched (AlbumID TEXT, Title TEXT, Size INTEGER, URL TEXT, DateAdded TEXT, Status TEXT, FolderName TEXT, Kind TEXT)')
|
|
c.execute('CREATE TABLE IF NOT EXISTS have (ArtistName TEXT, AlbumTitle TEXT, TrackNumber TEXT, TrackTitle TEXT, TrackLength TEXT, BitRate TEXT, Genre TEXT, Date TEXT, TrackID TEXT, Location TEXT, CleanName TEXT, Format TEXT, Matched TEXT)') # Matched is a temporary value used to see if there was a match found in alltracks
|
|
c.execute('CREATE TABLE IF NOT EXISTS lastfmcloud (ArtistName TEXT, ArtistID TEXT, Count INTEGER)')
|
|
c.execute('CREATE TABLE IF NOT EXISTS descriptions (ArtistID TEXT, ReleaseGroupID TEXT, ReleaseID TEXT, Summary TEXT, Content TEXT, LastUpdated TEXT)')
|
|
c.execute('CREATE TABLE IF NOT EXISTS blacklist (ArtistID TEXT UNIQUE)')
|
|
c.execute('CREATE TABLE IF NOT EXISTS newartists (ArtistName TEXT UNIQUE)')
|
|
c.execute('CREATE TABLE IF NOT EXISTS releases (ReleaseID TEXT, ReleaseGroupID TEXT, UNIQUE(ReleaseID, ReleaseGroupID))')
|
|
c.execute('CREATE INDEX IF NOT EXISTS tracks_albumid ON tracks(AlbumID ASC)')
|
|
c.execute('CREATE INDEX IF NOT EXISTS album_artistid_reldate ON albums(ArtistID ASC, ReleaseDate DESC)')
|
|
#Below creates indices to speed up Active Artist updating
|
|
c.execute('CREATE INDEX IF NOT EXISTS alltracks_relid ON alltracks(ReleaseID ASC, TrackID ASC)')
|
|
c.execute('CREATE INDEX IF NOT EXISTS allalbums_relid ON allalbums(ReleaseID ASC)')
|
|
c.execute('CREATE INDEX IF NOT EXISTS have_location ON have(Location ASC)')
|
|
#Below creates indices to speed up library scanning & matching
|
|
c.execute('CREATE INDEX IF NOT EXISTS have_Metadata ON have(ArtistName ASC, AlbumTitle ASC, TrackTitle ASC)')
|
|
c.execute('CREATE INDEX IF NOT EXISTS have_CleanName ON have(CleanName ASC)')
|
|
c.execute('CREATE INDEX IF NOT EXISTS tracks_Metadata ON tracks(ArtistName ASC, AlbumTitle ASC, TrackTitle ASC)')
|
|
c.execute('CREATE INDEX IF NOT EXISTS tracks_CleanName ON tracks(CleanName ASC)')
|
|
c.execute('CREATE INDEX IF NOT EXISTS alltracks_Metadata ON alltracks(ArtistName ASC, AlbumTitle ASC, TrackTitle ASC)')
|
|
c.execute('CREATE INDEX IF NOT EXISTS alltracks_CleanName ON alltracks(CleanName ASC)')
|
|
c.execute('CREATE INDEX IF NOT EXISTS tracks_Location ON tracks(Location ASC)')
|
|
c.execute('CREATE INDEX IF NOT EXISTS alltracks_Location ON alltracks(Location ASC)')
|
|
|
|
try:
|
|
c.execute('SELECT IncludeExtras from artists')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE artists ADD COLUMN IncludeExtras INTEGER DEFAULT 0')
|
|
|
|
try:
|
|
c.execute('SELECT LatestAlbum from artists')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE artists ADD COLUMN LatestAlbum TEXT')
|
|
|
|
try:
|
|
c.execute('SELECT ReleaseDate from artists')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE artists ADD COLUMN ReleaseDate TEXT')
|
|
|
|
try:
|
|
c.execute('SELECT AlbumID from artists')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE artists ADD COLUMN AlbumID TEXT')
|
|
|
|
try:
|
|
c.execute('SELECT HaveTracks from artists')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE artists ADD COLUMN HaveTracks INTEGER DEFAULT 0')
|
|
|
|
try:
|
|
c.execute('SELECT TotalTracks from artists')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE artists ADD COLUMN TotalTracks INTEGER DEFAULT 0')
|
|
|
|
try:
|
|
c.execute('SELECT Type from albums')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE albums ADD COLUMN Type TEXT DEFAULT "Album"')
|
|
|
|
try:
|
|
c.execute('SELECT TrackNumber from tracks')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE tracks ADD COLUMN TrackNumber INTEGER')
|
|
|
|
try:
|
|
c.execute('SELECT FolderName from snatched')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE snatched ADD COLUMN FolderName TEXT')
|
|
|
|
try:
|
|
c.execute('SELECT Location from tracks')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE tracks ADD COLUMN Location TEXT')
|
|
|
|
try:
|
|
c.execute('SELECT Location from have')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE have ADD COLUMN Location TEXT')
|
|
|
|
try:
|
|
c.execute('SELECT BitRate from tracks')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE tracks ADD COLUMN BitRate INTEGER')
|
|
|
|
try:
|
|
c.execute('SELECT CleanName from tracks')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE tracks ADD COLUMN CleanName TEXT')
|
|
|
|
try:
|
|
c.execute('SELECT CleanName from have')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE have ADD COLUMN CleanName TEXT')
|
|
|
|
# Add the Format column
|
|
try:
|
|
c.execute('SELECT Format from have')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE have ADD COLUMN Format TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT Format from tracks')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE tracks ADD COLUMN Format TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT LastUpdated from artists')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE artists ADD COLUMN LastUpdated TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT ArtworkURL from artists')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE artists ADD COLUMN ArtworkURL TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT ArtworkURL from albums')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE albums ADD COLUMN ArtworkURL TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT ThumbURL from artists')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE artists ADD COLUMN ThumbURL TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT ThumbURL from albums')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE albums ADD COLUMN ThumbURL TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT ArtistID from descriptions')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE descriptions ADD COLUMN ArtistID TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT LastUpdated from descriptions')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE descriptions ADD COLUMN LastUpdated TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT ReleaseID from albums')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE albums ADD COLUMN ReleaseID TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT ReleaseFormat from albums')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE albums ADD COLUMN ReleaseFormat TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT ReleaseCountry from albums')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE albums ADD COLUMN ReleaseCountry TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT ReleaseID from tracks')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE tracks ADD COLUMN ReleaseID TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT Matched from have')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE have ADD COLUMN Matched TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT Extras from artists')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE artists ADD COLUMN Extras TEXT DEFAULT NULL')
|
|
# Need to update some stuff when people are upgrading and have 'include extras' set globally/for an artist
|
|
if INCLUDE_EXTRAS:
|
|
EXTRAS = "1,2,3,4,5,6,7,8"
|
|
logger.info("Copying over current artist IncludeExtras information")
|
|
artists = c.execute('SELECT ArtistID, IncludeExtras from artists').fetchall()
|
|
for artist in artists:
|
|
if artist[1]:
|
|
c.execute('UPDATE artists SET Extras=? WHERE ArtistID=?', ("1,2,3,4,5,6,7,8", artist[0]))
|
|
|
|
try:
|
|
c.execute('SELECT Kind from snatched')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE snatched ADD COLUMN Kind TEXT DEFAULT NULL')
|
|
|
|
try:
|
|
c.execute('SELECT SearchTerm from albums')
|
|
except sqlite3.OperationalError:
|
|
c.execute('ALTER TABLE albums ADD COLUMN SearchTerm TEXT DEFAULT NULL')
|
|
|
|
|
|
conn.commit()
|
|
c.close()
|
|
|
|
|
|
def shutdown(restart=False, update=False):
|
|
|
|
cherrypy.engine.exit()
|
|
SCHED.shutdown(wait=False)
|
|
|
|
config_write()
|
|
|
|
if not restart and not update:
|
|
logger.info('Headphones is shutting down...')
|
|
|
|
if update:
|
|
logger.info('Headphones is updating...')
|
|
try:
|
|
versioncheck.update()
|
|
except Exception, e:
|
|
logger.warn('Headphones failed to update: %s. Restarting.', e)
|
|
|
|
if CREATEPID :
|
|
logger.info ('Removing pidfile %s', PIDFILE)
|
|
os.remove(PIDFILE)
|
|
|
|
if restart:
|
|
logger.info('Headphones is restarting...')
|
|
popen_list = [sys.executable, FULL_PATH]
|
|
popen_list += ARGS
|
|
if '--nolaunch' not in popen_list:
|
|
popen_list += ['--nolaunch']
|
|
logger.info('Restarting Headphones with %s', popen_list)
|
|
subprocess.Popen(popen_list, cwd=os.getcwd())
|
|
|
|
os._exit(0)
|