From 1ce6deaa48abc90160effb935c99c41e5bb4278b Mon Sep 17 00:00:00 2001 From: Rafael Vargas Date: Fri, 22 Jul 2022 22:57:27 -0300 Subject: [PATCH] Modifying clear and skip commands to work with process --- Controllers/ClearController.py | 11 ++++- Controllers/SkipController.py | 25 ++++++----- Parallelism/PlayerProcess.py | 76 +++++++++++++++++++--------------- 3 files changed, 67 insertions(+), 45 deletions(-) diff --git a/Controllers/ClearController.py b/Controllers/ClearController.py index ab54f38..5c9188b 100644 --- a/Controllers/ClearController.py +++ b/Controllers/ClearController.py @@ -2,6 +2,7 @@ from discord.ext.commands import Context from discord import Client from Controllers.AbstractController import AbstractController from Controllers.ControllerResponse import ControllerResponse +from Parallelism.ProcessManager import ProcessManager class ClearController(AbstractController): @@ -9,5 +10,13 @@ class ClearController(AbstractController): super().__init__(ctx, bot) async def run(self) -> ControllerResponse: - self.player.playlist.clear() + # Get the current process of the guild + processManager = ProcessManager() + processContext = processManager.getRunningPlayerContext(self.guild) + if processContext: + # Clear the playlist + playlist = processContext.getPlaylist() + with processContext.getLock(): + playlist.clear() + return ControllerResponse(self.ctx) diff --git a/Controllers/SkipController.py b/Controllers/SkipController.py index 43abbfd..bb203fe 100644 --- a/Controllers/SkipController.py +++ b/Controllers/SkipController.py @@ -3,6 +3,8 @@ from discord import Client from Controllers.AbstractController import AbstractController from Exceptions.Exceptions import BadCommandUsage from Controllers.ControllerResponse import ControllerResponse +from Parallelism.ProcessManager import ProcessManager +from Parallelism.Commands import VCommands, VCommandsType class SkipController(AbstractController): @@ -10,14 +12,17 @@ class SkipController(AbstractController): super().__init__(ctx, bot) async def run(self) -> ControllerResponse: - if self.player.playlist.isLoopingOne(): - embed = self.embeds.ERROR_DUE_LOOP_ONE_ON() - error = BadCommandUsage() - return ControllerResponse(self.ctx, embed, error) + processManager = ProcessManager() + processContext = processManager.getRunningPlayerContext(self.guild) + if processContext: # Verify if there is a running process + playlist = processContext.getPlaylist() + if playlist.isLoopingOne(): + embed = self.embeds.ERROR_DUE_LOOP_ONE_ON() + error = BadCommandUsage() + return ControllerResponse(self.ctx, embed, error) - voice = self.controller.get_guild_voice(self.guild) - if voice is None: - return ControllerResponse(self.ctx) - else: - voice.stop() - return ControllerResponse(self.ctx) + # Send a command to the player process to skip the music + command = VCommands(VCommandsType.SKIP, None) + queue = processContext.getQueue() + queue.put(command) + return ControllerResponse(self.ctx) diff --git a/Parallelism/PlayerProcess.py b/Parallelism/PlayerProcess.py index 42210b8..4f39e3d 100644 --- a/Parallelism/PlayerProcess.py +++ b/Parallelism/PlayerProcess.py @@ -62,12 +62,15 @@ class PlayerProcess(Process): def run(self) -> None: """Method called by process.start(), this will exec the actually _run method in a event loop""" - self.__loop = asyncio.get_event_loop() - self.__configs = Configs() + try: + self.__loop = asyncio.get_event_loop() + self.__configs = Configs() - self.__semStopPlaying = Semaphore(0) - self.__stopped = asyncio.Event() - self.__loop.run_until_complete(self._run()) + self.__semStopPlaying = Semaphore(0) + self.__stopped = asyncio.Event() + self.__loop.run_until_complete(self._run()) + except Exception as e: + print(f'[Error in Process {self.name}] -> {e}') async def _run(self) -> None: # Recreate the bot instance and objects using discord API @@ -102,9 +105,9 @@ class PlayerProcess(Process): async def __playSong(self, song: Song) -> None: try: - source = await self.__ensureSource(song) - if source is None: - self.__playNext(None) + if song.source is None: + return self.__playNext(None) + self.__playing = True player = FFmpegPCMAudio(song.source, **self.FFMPEG_OPTIONS) @@ -141,20 +144,27 @@ class PlayerProcess(Process): print(f'Command Received: {type}') if type == VCommandsType.PAUSE: - self.pause() + self.__pause() elif type == VCommandsType.PLAY: self.__loop.create_task(self.__playPlaylistSongs()) elif type == VCommandsType.PLAY_PREV: self.__playPrev() elif type == VCommandsType.RESUME: - pass + self.__resume() elif type == VCommandsType.SKIP: - pass + self.__skip() else: print(f'[ERROR] -> Unknown Command Received: {command}') - def pause(self): - print(id(self)) + def __pause(self) -> None: + pass + + def __resume(self) -> None: + pass + + def __skip(self) -> None: + if self.__guild.voice_client is not None: + self.__guild.voice_client.stop() async def __playPrev(self, ctx: Context) -> None: with self.__lock: @@ -208,29 +218,27 @@ class PlayerProcess(Process): return bot async def __timeoutHandler(self) -> None: - if self.__guild.voice_client is None: - return + try: + print('TimeoutHandler') + if self.__guild.voice_client is None: + print('return') + return - if self.__guild.voice_client.is_playing() or self.__guild.voice_client.is_paused(): - self.__timer = TimeoutClock(self.__timeoutHandler) + if self.__guild.voice_client.is_playing() or self.__guild.voice_client.is_paused(): + print('Resetting') + self.__timer = TimeoutClock(self.__timeoutHandler, self.__loop) - elif self.__guild.voice_client.is_connected(): - with self.__lock: - self.__playlist.clear() - self.__playlist.loop_off() - await self.__guild.voice_client.disconnect() - # Release semaphore to finish process - self.__semStopPlaying.release() - - async def __ensureSource(self, song: Song) -> str: - while True: - if song.source is not None: # If song got downloaded - return song.source - - if song.problematic: # If song got any error - return None - - await asyncio.sleep(0.1) + elif self.__guild.voice_client.is_connected(): + print('Finish') + with self.__lock: + self.__playlist.clear() + self.__playlist.loop_off() + self.__playing = False + await self.__guild.voice_client.disconnect() + # Release semaphore to finish process + self.__semStopPlaying.release() + except Exception as e: + print(f'[Error in Timeout] -> {e}') def __is_connected(self) -> bool: try: