Esempio n. 1
0
    def _loop(self):
        while True:

            catch_up = None
            if models.CurrentSong.objects.exists():
                # recover interrupted song from database
                current_song = models.CurrentSong.objects.get()

                # continue with the current song (approximately) where we last left
                duration = song_utils.get_duration(current_song.location)
                catch_up = (timezone.now() -
                            current_song.created).total_seconds()
            else:
                self.queue_semaphore.acquire()

                # select the next song depending on settings
                if self.musiq.base.settings.voting_system:
                    with transaction.atomic():
                        song = self.queue.all().order_by('-votes', 'index')[0]
                        song_id = song.id
                        self.queue.remove(song.id)
                elif self.shuffle:
                    index = random.randint(
                        0,
                        models.QueuedSong.objects.count() - 1)
                    song_id = models.QueuedSong.objects.all()[index].id
                    song = self.queue.remove(song_id)
                else:
                    # move the first song in the queue into the current song
                    song_id, song = self.queue.dequeue()

                if song is None:
                    # either the semaphore didn't match up with the actual count of songs in the queue or a race condition occured
                    self.musiq.base.logger.info('dequeued on empty list')
                    continue

                location = song_utils.path_from_url(song.url)
                current_song = models.CurrentSong.objects.create(
                    queue_key=song_id,
                    votes=song.votes,
                    url=song.url,
                    artist=song.artist,
                    title=song.title,
                    duration=song.duration,
                    location=location)

                try:
                    archived_song = models.ArchivedSong.objects.get(
                        url=current_song.url)
                    if self.musiq.base.settings.voting_system:
                        votes = current_song.votes
                    else:
                        votes = None
                    if self.musiq.base.settings.logging_enabled:
                        models.PlayLog.objects.create(song=archived_song,
                                                      votes=votes)
                except (models.ArchivedSong.DoesNotExist,
                        models.ArchivedSong.MultipleObjectsReturned):
                    pass

            self.musiq.update_state()

            with self.mpd_command(important=True):
                self.player.add('file://' + current_song.location)
                self.player.play()
                if catch_up is not None:
                    self.player.seekcur(catch_up)
            self.musiq.update_state()

            self._wait_until_song_end()

            with self.mpd_command(important=True):
                try:
                    self.player.delete(0)
                except mpd.base.CommandError:
                    # catch Bad song index if there is no song
                    pass
            current_song.delete()

            if self.repeat:
                self.queue.enqueue(current_song.location)
                self.queue_semaphore.release()
            else:
                # the song left the queue, we can delete big downloads
                song_utils.decide_deletion(current_song.location)

            self.musiq.update_state()

            if self.musiq.base.user_manager.partymode_enabled(
            ) and random.random() < self.musiq.base.settings.alarm_probability:
                self.alarm_playing.set()
                self.musiq.base.lights.alarm_started()

                with self.mpd_command(important=True):
                    self.player.add('file://' + os.path.join(
                        settings.BASE_DIR, 'config/sounds/alarm.mp3'))
                    self.player.play()
                self._wait_until_song_end()

                self.musiq.base.lights.alarm_stopped()
                with self.mpd_command(important=True):
                    self.player.delete(0)
                self.alarm_playing.clear()
Esempio n. 2
0
    def _loop(self):
        while True:

            catch_up = None
            if models.CurrentSong.objects.exists():
                # recover interrupted song from database
                current_song = models.CurrentSong.objects.get()

                # continue with the current song (approximately) where we last left
                song_provider = SongProvider.create(self.musiq, internal_url=current_song.internal_url)
                duration = song_provider.get_metadata()['duration']
                catch_up = round((timezone.now() - current_song.created).total_seconds() * 1000)
                if catch_up > duration * 1000:
                    catch_up = -1
            else:
                self.queue_semaphore.acquire()

                # select the next song depending on settings
                if self.musiq.base.settings.voting_system:
                    with transaction.atomic():
                        song = self.queue.all().order_by('-votes', 'index')[0]
                        song_id = song.id
                        self.queue.remove(song.id)
                elif self.shuffle:
                    index = random.randint(0,models.QueuedSong.objects.count() - 1)
                    song_id = models.QueuedSong.objects.all()[index].id
                    song = self.queue.remove(song_id)
                else:
                    # move the first song in the queue into the current song
                    song_id, song = self.queue.dequeue()

                if song is None:
                    # either the semaphore didn't match up with the actual count of songs in the queue or a race condition occured
                    self.musiq.base.logger.info('dequeued on empty list')
                    continue
                

                current_song = models.CurrentSong.objects.create(
                        queue_key=song_id,
                        manually_requested=song.manually_requested,
                        votes=song.votes,
                        internal_url=song.internal_url,
                        external_url=song.external_url,
                        artist=song.artist,
                        title=song.title,
                        duration=song.duration,
                )

                self._handle_autoplay()

                try:
                    archived_song = models.ArchivedSong.objects.get(url=current_song.external_url)
                    if self.musiq.base.settings.voting_system:
                        votes = current_song.votes
                    else:
                        votes = None
                    if self.musiq.base.settings.logging_enabled:
                        models.PlayLog.objects.create(
                                song=archived_song,
                                manually_requested=current_song.manually_requested,
                                votes=votes)
                except (models.ArchivedSong.DoesNotExist, models.ArchivedSong.MultipleObjectsReturned):
                    pass

            self.musiq.update_state()

            playing = Event()
            @self.player.on_event('playback_state_changed')
            def on_playback_state_changed(event):
                playing.set()

            with self.mopidy_command(important=True):
                # after a restart consume may be set to False again, so make sure it is on
                self.player.tracklist.clear()
                self.player.tracklist.set_consume(True)
                self.player.tracklist.add(uris=[current_song.internal_url])
                self.player.playback.play()
                # mopidy can only seek when the song is playing
                playing.wait(timeout=1)
                if catch_up is not None and catch_up >= 0:
                    self.player.playback.seek(catch_up)

            self.musiq.update_state()

            if catch_up is None or catch_up >= 0:
                if not self._wait_until_song_end():
                    # there was a ConnectionError during waiting for the song to end
                    # thus, we do not delete the current song but recover its state by restarting the loop
                    continue

            current_song.delete()

            if self.repeat:
                song_provider = SongProvider.create(self.musiq, internal_url=current_song.internal_url)
                self.queue.enqueue(song_provider.get_metadata(), False)
                self.queue_semaphore.release()
            else:
                # the song left the queue, we can delete big downloads
                song_utils.decide_deletion(current_song.internal_url)

            self.musiq.update_state()

            if self.musiq.base.user_manager.partymode_enabled() and random.random() < self.musiq.base.settings.alarm_probability:
                self.alarm_playing.set()
                self.musiq.base.lights.alarm_started()

                self.musiq.update_state()

                with self.mopidy_command(important=True):
                    self.player.tracklist.add(uris=['file://'+os.path.join(settings.BASE_DIR, 'config/sounds/alarm.m4a')])
                    self.player.playback.play()
                playing.clear()
                playing.wait(timeout=1)
                self._wait_until_song_end()

                self.musiq.base.lights.alarm_stopped()
                self.musiq.update_state()
                self.alarm_playing.clear()