예제 #1
0
def remove_all(request: WSGIRequest) -> HttpResponse:
    """Empties the queue. Only admin is permitted to do this."""
    if not user_manager.is_admin(request.user):
        return HttpResponseForbidden()
    with playback.mopidy_command() as allowed:
        if allowed:
            with transaction.atomic():
                playback.queue.all().delete()
    return HttpResponse()
예제 #2
0
def restart(_request: WSGIRequest) -> None:
    """Restarts the current song from the beginning."""
    with playback.mopidy_command() as allowed:
        if allowed:
            PLAYER.playback.seek(0)
    try:
        current_song = models.CurrentSong.objects.get()
        current_song.created = timezone.now()
        current_song.save()
    except models.CurrentSong.DoesNotExist:
        pass
예제 #3
0
def seek_forward(_request: WSGIRequest) -> None:
    """Jumps forward in the current song."""
    with playback.mopidy_command() as allowed:
        if allowed:
            current_position = PLAYER.playback.get_time_position()
            PLAYER.playback.seek(current_position + SEEK_DISTANCE * 1000)
    try:
        current_song = models.CurrentSong.objects.get()
        current_song.created -= datetime.timedelta(seconds=SEEK_DISTANCE)
        current_song.save()
    except models.CurrentSong.DoesNotExist:
        pass
예제 #4
0
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)
예제 #5
0
def _set_volume(volume) -> None:
    try:
        # Try to set the volume via the pulse server.
        # This is faster and does not impact visualization
        subprocess.run(
            f"pactl set-sink-volume @DEFAULT_SINK@ {round(volume*100)}%".split(
            ),
            env={"PULSE_SERVER": conf.PULSE_SERVER},
            check=True,
        )
    except (FileNotFoundError, subprocess.CalledProcessError):
        # pulse is not installed or there is no server running.
        # change mopidy's volume
        with playback.mopidy_command() as allowed:
            if allowed:
                PLAYER.mixer.set_volume(round(volume * 100))
예제 #6
0
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)
예제 #7
0
def vote(request: WSGIRequest) -> HttpResponse:
    """Modify the vote-count of the given song by the given amount.
    If a song receives too many downvotes, it is removed."""
    key_param = request.POST.get("key")
    amount_param = request.POST.get("amount")
    if key_param is None or amount_param is None:
        return HttpResponseBadRequest()
    key = int(key_param)
    amount = int(amount_param)
    if amount < -2 or amount > 2:
        return HttpResponseBadRequest()

    if storage.get("ip_checking") and not user_manager.try_vote(
            user_manager.get_client_ip(request), key, amount):
        return HttpResponseBadRequest("nice try")

    models.CurrentSong.objects.filter(queue_key=key).update(votes=F("votes") +
                                                            amount)
    try:
        current_song = models.CurrentSong.objects.get()
        if (current_song.queue_key == key
                and current_song.votes <= -storage.get(  # pylint: disable=invalid-unary-operand-type
                    "downvotes_to_kick")):
            with playback.mopidy_command() as allowed:
                if allowed:
                    PLAYER.playback.next()
    except models.CurrentSong.DoesNotExist:
        pass

    removed = playback.queue.vote(
        key,
        amount,
        -storage.get("downvotes_to_kick"),  # pylint: disable=invalid-unary-operand-type
    )
    # if we removed a song by voting, and it was added by autoplay,
    # we want it to be the new basis for autoplay
    if removed is not None:
        if not removed.manually_requested:
            playback.handle_autoplay(removed.external_url or removed.title)
        else:
            playback.handle_autoplay()
    musiq.update_state()
    return HttpResponse()
예제 #8
0
def skip(_request: WSGIRequest) -> None:
    """Skips the current song and continues with the next one."""
    with playback.mopidy_command() as allowed:
        if allowed:
            redis.put("backup_playing", False)
            PLAYER.playback.next()