def _handle_brightness_request(device: str, request: WSGIRequest) -> HttpResponse: value, response = extract_value(request.POST) assert device in ["ring", "strip", "wled", "screen"] storage.put(cast(DeviceBrightness, f"{device}_brightness"), float(value)) _notify_settings_changed(device) return response
def __init__(self, manager) -> None: super().__init__(manager, "wled") self.led_count = storage.get("wled_led_count") self.ip = storage.get("wled_ip") if not self.ip: try: device = util.get_devices()[0] broadcast = util.broadcast_of_device(device) self.ip = broadcast except Exception: # pylint: disable=broad-except # we don't want the startup to fail # just because the broadcast address could not be determined self.ip = "127.0.0.1" storage.put("wled_ip", self.ip) self.port = storage.get("wled_port") self.header = bytes([ 2, # DRGB protocol, we update every led every frame 1, # wait 1 second after the last packet until resuming normally ]) self.initialized = True redis.put("wled_initialized", True)
def set_volume(request: WSGIRequest) -> HttpResponse: """Sets the playback volume. value has to be a float between 0 and 1.""" volume, response = extract_value(request.POST) _set_volume(float(volume)) storage.put("volume", float(volume)) return response
def set_autoplay(request: WSGIRequest) -> None: """Enables or disables autoplay depending on the given value. If enabled and the current song is the last one, a new song is enqueued, based on the current one.""" enabled = request.POST.get("value") == "true" storage.put("autoplay", enabled) playback.handle_autoplay()
def setUp(self) -> None: super().setUp() self._setup_test_library() self._add_local_playlist() storage.put("interactivity", storage.Interactivity.full_voting) self.client.logout()
def set_wled_port(request: WSGIRequest) -> HttpResponse: """Updates the wled port.""" value, response = extract_value(request.POST) if not 1024 <= int(value) <= 65535: return HttpResponseBadRequest("invalid port") storage.put("wled_port", int(value)) _notify_settings_changed("wled") return response
def set_wled_led_count(request: WSGIRequest) -> HttpResponse: """Updates the wled led_count.""" value, response = extract_value(request.POST) if not 2 <= int(value) <= 490: return HttpResponseBadRequest("must be between 2 and 490") storage.put("wled_led_count", int(value)) _notify_settings_changed("wled") return response
def _handle_monochrome_request(device: str, request: WSGIRequest) -> HttpResponse: value, response = extract_value(request.POST) assert device in ["ring", "strip", "wled", "screen"] storage.put(cast(DeviceMonochrome, f"{device}_monochrome"), strtobool(value)) _notify_settings_changed(device) return response
def set_initial_resolution(request: WSGIRequest) -> HttpResponse: """Sets the resolution used on the screen.""" value, response = extract_value(request.POST) resolution = tuple(map(int, value.split("x"))) resolution = cast(Tuple[int, int], resolution) storage.put("initial_resolution", resolution) # adjusting sets the resolution and restarts the screen program _notify_settings_changed("adjust_screen") return response
def set_wled_ip(request: WSGIRequest) -> HttpResponse: """Updates the wled ip.""" value, response = extract_value(request.POST) try: socket.inet_aton(value) except socket.error: return HttpResponseBadRequest("invalid ip") storage.put("wled_ip", value) _notify_settings_changed("wled") return response
def adjust(self) -> None: """Updates resolutions and resets the current one. Needed after changing screens or hotplugging after booting without a connected screen.""" self.resolution = storage.get("initial_resolution") resolutions = list(reversed(sorted(self.list_resolutions()))) redis.put("resolutions", resolutions) # if unset, initialize with the highest resolution if self.resolution == (0, 0): storage.put("initial_resolution", resolutions[0]) self.resolution = resolutions[0] self.set_resolution(self.resolution)
def set_jamendo_credentials(request: WSGIRequest) -> HttpResponse: """Update jamendo credentials.""" client_id = request.POST.get("client_id") if not client_id: return HttpResponseBadRequest("All fields are required") storage.put("jamendo_client_id", client_id) system.update_mopidy_config("pulse") return HttpResponse("Updated credentials")
def set_soundcloud_credentials(request: WSGIRequest) -> HttpResponse: """Update soundcloud credentials.""" auth_token = request.POST.get("auth_token") if not auth_token: return HttpResponseBadRequest("All fields are required") storage.put("soundcloud_auth_token", auth_token) system.update_mopidy_config("pulse") return HttpResponse("Updated credentials")
def set_interactivity(request: WSGIRequest) -> HttpResponse: """Enables or disables voting based on the given value.""" value, response = extract_value(request.POST) if value not in [ getattr(storage.Interactivity, attr) for attr in dir(storage.Interactivity) if not attr.startswith("__") ]: return HttpResponseBadRequest("Invalid value") storage.put("interactivity", value) return response
def set_output(request: WSGIRequest) -> HttpResponse: """Sets the given device as default output device.""" output = request.POST.get("value") if not output: return HttpResponseBadRequest("No output selected") if output == request.POST.get("output"): return HttpResponseBadRequest("Output unchanged") storage.put("output", output) return _set_output(output)
def set_fixed_color(request: WSGIRequest) -> HttpResponse: """Updates the static color used for some programs.""" hex_col, response = extract_value(request.POST) hex_col = hex_col.lstrip("#") try: color = tuple(int(hex_col[i:i + 2], 16) / 255 for i in (0, 2, 4)) except IndexError: return HttpResponseBadRequest("color needs to be in #rrggbb format") # https://github.com/python/mypy/issues/5068 color = cast(Tuple[float, float, float], color) storage.put("fixed_color", color) _notify_settings_changed("base") return response
def pause(_request: WSGIRequest) -> None: """Pauses the current song if it is playing. No-op if already paused.""" with playback.mopidy_command() as allowed: if allowed: PLAYER.playback.pause() try: current_song = models.CurrentSong.objects.get() current_song.last_paused = timezone.now() current_song.save() except models.CurrentSong.DoesNotExist: pass storage.put("paused", True)
def start() -> None: """Initializes this module by checking which platforms are available to use.""" # local songs are enabled if a library is set local_enabled = os.path.islink(library.get_library_path()) storage.put("local_enabled", local_enabled) # in the docker container all dependencies are installed youtube_available = conf.DOCKER or importlib.util.find_spec( "yt_dlp") is not None redis.put("youtube_available", youtube_available) if not youtube_available: # if youtube is not available, overwrite the database to disable it storage.put("youtube_enabled", False) # Spotify has no python dependencies we could easily check. try: spotify_available = ( conf.DOCKER or "[spotify]" in subprocess.check_output( ["mopidy", "config"], stderr=subprocess.DEVNULL).decode().splitlines()) except FileNotFoundError: # mopidy is not installed (eg in docker). Since we can't check, enable spotify_available = True redis.put("spotify_available", spotify_available) if not spotify_available: storage.put("spotify_enabled", False) soundcloud_available = (conf.DOCKER or importlib.util.find_spec("soundcloud") is not None) redis.put("soundcloud_available", soundcloud_available) if not soundcloud_available: storage.put("soundcloud_enabled", False) # Jamendo has no python dependencies we could easily check. try: jamendo_available = ( conf.DOCKER or "[jamendo]" in subprocess.check_output( ["mopidy", "config"], stderr=subprocess.DEVNULL).decode().splitlines()) except FileNotFoundError: jamendo_available = True redis.put("jamendo_available", jamendo_available) if not jamendo_available: storage.put("jamendo_enabled", False)
def play(_request: WSGIRequest) -> None: """Resumes the current song if it is paused. No-op if already playing.""" with playback.mopidy_command() as allowed: if allowed: PLAYER.playback.play() try: # move the creation timestamp into the future for the duration of the pause # this ensures that the progress calculation (starting from created) is correct current_song = models.CurrentSong.objects.get() now = timezone.now() pause_duration = (now - current_song.last_paused).total_seconds() current_song.created += datetime.timedelta(seconds=pause_duration) current_song.created = min(current_song.created, now) current_song.save() except models.CurrentSong.DoesNotExist: pass storage.put("paused", False)
def _set_extension_enabled(extension, enabled) -> HttpResponse: if enabled: if conf.DOCKER: response = HttpResponse( "Make sure you provided mopidy with correct credentials.") else: extensions = system.check_mopidy_extensions() functional, message = extensions[extension] if not functional: return HttpResponseBadRequest(message) response = HttpResponse(message) else: response = HttpResponse("Disabled extension") assert extension in [ "local", "youtube", "spotify", "soundcloud", "jamendo" ] storage.put(cast(PlatformEnabled, f"{extension}_enabled"), enabled) return response
def set_spotify_credentials(request: WSGIRequest) -> HttpResponse: """Update spotify credentials.""" username = request.POST.get("username") password = request.POST.get("password") client_id = request.POST.get("client_id") client_secret = request.POST.get("client_secret") if not username or not password or not client_id or not client_secret: return HttpResponseBadRequest("All fields are required") storage.put("spotify_username", username) storage.put("spotify_password", password) storage.put("spotify_client_id", client_id) storage.put("spotify_client_secret", client_secret) system.update_mopidy_config("pulse") return HttpResponse("Updated credentials")
def set_online_suggestions(request: WSGIRequest) -> HttpResponse: """Enables or disables online suggestions based on the given value.""" value, response = extract_value(request.POST) storage.put("online_suggestions", strtobool(value)) return response
def set_dynamic_embedded_stream(request: WSGIRequest) -> HttpResponse: """Enables or disables dynamic streaming based on the given value.""" value, response = extract_value(request.POST) storage.put("dynamic_embedded_stream", strtobool(value)) return response
def set_embed_stream(request: WSGIRequest) -> HttpResponse: """Enables or disables logging of requests and play logs based on the given value.""" value, response = extract_value(request.POST) storage.put("embed_stream", strtobool(value)) return response
def set_downvotes_to_kick(request: WSGIRequest) -> HttpResponse: """Sets the number of downvotes that are needed to remove a song from the queue.""" value, response = extract_value(request.POST) storage.put("downvotes_to_kick", int(value)) return response
def set_ip_checking(request: WSGIRequest) -> HttpResponse: """Enables or disables ip checking based on the given value.""" value, response = extract_value(request.POST) storage.put("ip_checking", strtobool(value)) return response
def set_buzzer_success_probability(request: WSGIRequest) -> HttpResponse: """Sets the probability for the buzzer to play a success sound.""" value, response = extract_value(request.POST) storage.put("buzzer_success_probability", float(value)) return response
def set_buzzer_cooldown(request: WSGIRequest) -> HttpResponse: """Sets the minimum time that needs to pass between buzzer presses.""" value, response = extract_value(request.POST) storage.put("buzzer_cooldown", float(value)) return response
def set_alarm_probability(request: WSGIRequest) -> HttpResponse: """Sets the probability with which an alarm is triggered after each song.""" value, response = extract_value(request.POST) storage.put("alarm_probability", float(value)) return response
def set_people_to_party(request: WSGIRequest) -> HttpResponse: """Sets the amount of active clients needed to enable partymode.""" value, response = extract_value(request.POST) storage.put("people_to_party", int(value)) return response