mirror of
https://github.com/RafaelSolVargas/Vulkan.git
synced 2025-10-29 16:57:23 +00:00
Sending more code
This commit is contained in:
parent
7d53840f87
commit
1f45b64a62
@ -40,7 +40,7 @@ class MusicCog(Cog):
|
||||
self.__bot: VulkanBot = bot
|
||||
self.__embeds = VEmbeds()
|
||||
configs = VConfigs()
|
||||
if configs.SHOULD_AUTO_DISCONNECT_WHEN_ALONE:
|
||||
if configs.SONG_PLAYBACK_IN_SEPARATE_PROCESS:
|
||||
configs.setPlayersManager(ProcessPlayerManager(bot))
|
||||
else:
|
||||
configs.setPlayersManager(ThreadPlayerManager(bot))
|
||||
|
||||
@ -49,7 +49,7 @@ class JumpMusicHandler(AbstractHandler):
|
||||
|
||||
# Send a command to the player to skip the music
|
||||
command = VCommands(VCommandsType.SKIP, None)
|
||||
playersManager.sendCommandToPlayer(command, self.guild)
|
||||
await playersManager.sendCommandToPlayer(command, self.guild)
|
||||
|
||||
return HandlerResponse(self.ctx)
|
||||
except:
|
||||
|
||||
@ -16,7 +16,7 @@ class PauseHandler(AbstractHandler):
|
||||
playersManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||
if playersManager.verifyIfPlayerExists(self.guild):
|
||||
command = VCommands(VCommandsType.PAUSE, None)
|
||||
playersManager.sendCommandToPlayer(command, self.guild)
|
||||
await playersManager.sendCommandToPlayer(command, self.guild)
|
||||
|
||||
embed = self.embeds.PLAYER_PAUSED()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
|
||||
@ -71,7 +71,7 @@ class PlayHandler(AbstractHandler):
|
||||
# Release the acquired Lock
|
||||
playerLock.release()
|
||||
playCommand = VCommands(VCommandsType.PLAY, None)
|
||||
playersManager.sendCommandToPlayer(playCommand, self.guild)
|
||||
await playersManager.sendCommandToPlayer(playCommand, self.guild)
|
||||
else:
|
||||
playersManager.resetPlayer(self.guild, self.ctx)
|
||||
embed = self.embeds.PLAYER_RESTARTED()
|
||||
@ -127,7 +127,7 @@ class PlayHandler(AbstractHandler):
|
||||
acquired = playerLock.acquire(timeout=self.config.ACQUIRE_LOCK_TIMEOUT)
|
||||
if acquired:
|
||||
playlist.add_song(song)
|
||||
playersManager.sendCommandToPlayer(playCommand, self.guild)
|
||||
await playersManager.sendCommandToPlayer(playCommand, self.guild)
|
||||
playerLock.release()
|
||||
else:
|
||||
playersManager.resetPlayer(self.guild, self.ctx)
|
||||
|
||||
@ -38,7 +38,7 @@ class PrevHandler(AbstractHandler):
|
||||
|
||||
# Send a prev command, together with the user voice channel
|
||||
prevCommand = VCommands(VCommandsType.PREV, self.author.voice.channel.id)
|
||||
playersManager.sendCommandToPlayer(prevCommand, self.guild)
|
||||
await playersManager.sendCommandToPlayer(prevCommand, self.guild)
|
||||
|
||||
embed = self.embeds.RETURNING_SONG()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
|
||||
@ -16,7 +16,7 @@ class ResetHandler(AbstractHandler):
|
||||
playersManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||
if playersManager.verifyIfPlayerExists(self.guild):
|
||||
command = VCommands(VCommandsType.RESET, None)
|
||||
playersManager.sendCommandToPlayer(command, self.guild)
|
||||
await playersManager.sendCommandToPlayer(command, self.guild)
|
||||
return HandlerResponse(self.ctx)
|
||||
else:
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
|
||||
@ -16,7 +16,7 @@ class ResumeHandler(AbstractHandler):
|
||||
playersManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||
if playersManager.verifyIfPlayerExists(self.guild):
|
||||
command = VCommands(VCommandsType.RESUME, None)
|
||||
playersManager.sendCommandToPlayer(command, self.guild)
|
||||
await playersManager.sendCommandToPlayer(command, self.guild)
|
||||
embed = self.embeds.PLAYER_RESUMED()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
else:
|
||||
|
||||
@ -16,7 +16,7 @@ class SkipHandler(AbstractHandler):
|
||||
playersManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||
if playersManager.verifyIfPlayerExists(self.guild):
|
||||
command = VCommands(VCommandsType.SKIP, None)
|
||||
playersManager.sendCommandToPlayer(command, self.guild)
|
||||
await playersManager.sendCommandToPlayer(command, self.guild)
|
||||
embed = self.embeds.SKIPPING_SONG()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
else:
|
||||
|
||||
@ -16,7 +16,7 @@ class StopHandler(AbstractHandler):
|
||||
playersManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||
if playersManager.verifyIfPlayerExists(self.guild):
|
||||
command = VCommands(VCommandsType.STOP, None)
|
||||
playersManager.sendCommandToPlayer(command, self.guild)
|
||||
await playersManager.sendCommandToPlayer(command, self.guild)
|
||||
embed = self.embeds.STOPPING_PLAYER()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
else:
|
||||
|
||||
@ -13,7 +13,7 @@ class AbstractPlayersManager(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def sendCommandToPlayer(self, command: VCommands, guild: Guild, forceCreation: bool = False, context: Union[Context, Interaction] = None):
|
||||
async def sendCommandToPlayer(self, command: VCommands, guild: Guild, forceCreation: bool = False, context: Union[Context, Interaction] = None):
|
||||
"""If the forceCreation boolean is True, then the context must be provided for the Player to be created"""
|
||||
pass
|
||||
|
||||
|
||||
@ -2,11 +2,11 @@ import asyncio
|
||||
from time import sleep, time
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
from Music.VulkanInitializer import VulkanInitializer
|
||||
from discord import Member, VoiceClient
|
||||
from discord import VoiceClient
|
||||
from asyncio import AbstractEventLoop, Semaphore, Queue
|
||||
from multiprocessing import Process, RLock, Lock, Queue
|
||||
from threading import Thread
|
||||
from typing import Callable, List
|
||||
from typing import Callable
|
||||
from discord import Guild, FFmpegPCMAudio, VoiceChannel
|
||||
from Music.Playlist import Playlist
|
||||
from Music.Song import Song
|
||||
@ -29,7 +29,7 @@ class TimeoutClock:
|
||||
self.__task.cancel()
|
||||
|
||||
|
||||
class PlayerProcess(Process):
|
||||
class ProcessPlayer(Process):
|
||||
"""Process that will play songs, receive commands from the main process by a Queue"""
|
||||
|
||||
def __init__(self, name: str, playlist: Playlist, lock: Lock, queueToReceive: Queue, queueToSend: Queue, guildID: int, voiceID: int) -> None:
|
||||
@ -421,9 +421,3 @@ class PlayerProcess(Process):
|
||||
except Exception as e:
|
||||
print(f'[ERROR CONNECTING TO VC] -> {e}')
|
||||
return False
|
||||
|
||||
def __getBotMember(self) -> Member:
|
||||
guild_members: List[Member] = self.__guild.members
|
||||
for member in guild_members:
|
||||
if member.id == self.__bot.user.id:
|
||||
return member
|
||||
@ -6,12 +6,12 @@ from queue import Empty
|
||||
from threading import Thread
|
||||
from typing import Dict, Tuple, Union
|
||||
from Config.Singleton import Singleton
|
||||
from discord import Guild, Interaction, TextChannel
|
||||
from discord import Guild, Interaction, TextChannel, VoiceChannel
|
||||
from discord.ext.commands import Context
|
||||
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||
from Parallelism.ProcessExecutor import ProcessCommandsExecutor
|
||||
from Music.Song import Song
|
||||
from Parallelism.PlayerProcess import PlayerProcess
|
||||
from Parallelism.ProcessPlayer import ProcessPlayer
|
||||
from Music.Playlist import Playlist
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
from Music.VulkanBot import VulkanBot
|
||||
@ -74,18 +74,18 @@ class ProcessPlayerManager(Singleton, AbstractPlayersManager):
|
||||
if not super().created:
|
||||
self.__bot = bot
|
||||
VManager.register('Playlist', Playlist)
|
||||
VManager.register('VoiceChannel', VoiceChannel)
|
||||
self.__manager = VManager()
|
||||
self.__manager.start()
|
||||
self.__playersProcess: Dict[int, PlayerProcessInfo] = {}
|
||||
self.__playersListeners: Dict[int, Tuple[Thread, bool]] = {}
|
||||
self.__playersCommandsExecutor: Dict[int, ProcessCommandsExecutor] = {}
|
||||
|
||||
def sendCommandToPlayer(self, command: VCommands, guild: Guild, forceCreation: bool = False, context: Union[Context, Interaction] = None):
|
||||
async def sendCommandToPlayer(self, command: VCommands, guild: Guild, forceCreation: bool = False, context: Union[Context, Interaction] = None):
|
||||
if forceCreation:
|
||||
processInfo = self.createPlayerForGuild(guild, context)
|
||||
else:
|
||||
processInfo = self.__getRunningPlayerInfo(guild)
|
||||
|
||||
if processInfo == None:
|
||||
return
|
||||
|
||||
@ -149,7 +149,7 @@ class ProcessPlayerManager(Singleton, AbstractPlayersManager):
|
||||
lock = Lock()
|
||||
queueToListen = Queue()
|
||||
queueToSend = Queue()
|
||||
process = PlayerProcess(context.guild.name, playlist, lock, queueToSend,
|
||||
process = ProcessPlayer(context.guild.name, playlist, lock, queueToSend,
|
||||
queueToListen, guildID, voiceID)
|
||||
processInfo = PlayerProcessInfo(process, queueToSend, queueToListen,
|
||||
playlist, lock, context.channel)
|
||||
@ -196,7 +196,7 @@ class ProcessPlayerManager(Singleton, AbstractPlayersManager):
|
||||
lock = Lock()
|
||||
queueToListen = Queue()
|
||||
queueToSend = Queue()
|
||||
process = PlayerProcess(context.guild.name, playlist, lock, queueToSend,
|
||||
process = ProcessPlayer(context.guild.name, playlist, lock, queueToSend,
|
||||
queueToListen, guildID, textID, voiceID, authorID)
|
||||
processInfo = PlayerProcessInfo(process, queueToSend, queueToListen,
|
||||
playlist, lock, context.channel)
|
||||
|
||||
@ -5,7 +5,7 @@ from discord import VoiceClient
|
||||
from asyncio import AbstractEventLoop
|
||||
from threading import RLock, Thread
|
||||
from multiprocessing import Lock
|
||||
from typing import Callable
|
||||
from typing import Callable, Coroutine
|
||||
from discord import Guild, FFmpegPCMAudio, VoiceChannel
|
||||
from Music.Playlist import Playlist
|
||||
from Music.Song import Song
|
||||
@ -28,10 +28,10 @@ class TimeoutClock:
|
||||
self.__task.cancel()
|
||||
|
||||
|
||||
class PlayerThread(Thread):
|
||||
class ThreadPlayer(Thread):
|
||||
"""Player Thread to control the song playback in the same Process of the Main Process"""
|
||||
|
||||
def __init__(self, bot: VulkanBot, guild: Guild, name: str, voiceChannel: VoiceChannel, playlist: Playlist, lock: Lock, guildID: int, voiceID: int) -> None:
|
||||
def __init__(self, bot: VulkanBot, guild: Guild, name: str, voiceChannel: VoiceChannel, playlist: Playlist, lock: Lock, guildID: int, voiceID: int, callbackToSendCommand: Callable, exitCB: Callable) -> None:
|
||||
Thread.__init__(self, name=name, group=None, target=None, args=(), kwargs={})
|
||||
# Synchronization objects
|
||||
self.__playlist: Playlist = playlist
|
||||
@ -39,14 +39,15 @@ class PlayerThread(Thread):
|
||||
self.__loop: AbstractEventLoop = None
|
||||
self.__playerLock: RLock = RLock()
|
||||
# Discord context ID
|
||||
self.__guildID = guildID
|
||||
self.__voiceChannelID = voiceID
|
||||
self.__guild: Guild = guild
|
||||
self.__bot: VulkanBot = bot
|
||||
self.__voiceChannel: VoiceChannel = voiceChannel
|
||||
self.__voiceClient: VoiceClient = None
|
||||
|
||||
self.__downloader = Downloader()
|
||||
self.__callback = callbackToSendCommand
|
||||
self.__exitCB = exitCB
|
||||
self.__bot = bot
|
||||
|
||||
self.__playing = False
|
||||
self.__forceStop = False
|
||||
@ -57,8 +58,7 @@ class PlayerThread(Thread):
|
||||
"""This method is called automatically when the Thread starts"""
|
||||
try:
|
||||
print(f'Starting Player Thread for Guild {self.name}')
|
||||
self.__loop = asyncio.get_event_loop_policy().new_event_loop()
|
||||
asyncio.set_event_loop(self.__loop)
|
||||
self.__loop = self.__bot.loop
|
||||
self.__loop.run_until_complete(self._run())
|
||||
|
||||
except Exception as e:
|
||||
@ -89,6 +89,7 @@ class PlayerThread(Thread):
|
||||
song = self.__playlist.next_song()
|
||||
|
||||
if song is not None:
|
||||
print('Criando song')
|
||||
self.__loop.create_task(self.__playSong(song), name=f'Song {song.identifier}')
|
||||
self.__playing = True
|
||||
|
||||
@ -131,7 +132,7 @@ class PlayerThread(Thread):
|
||||
self.__timer = TimeoutClock(self.__timeoutHandler, self.__loop)
|
||||
|
||||
nowPlayingCommand = VCommands(VCommandsType.NOW_PLAYING, song)
|
||||
self.__queueSend.put(nowPlayingCommand)
|
||||
await self.__callback(nowPlayingCommand, self.__guild.id, song)
|
||||
except Exception as e:
|
||||
print(f'[ERROR IN PLAY SONG FUNCTION] -> {e}, {type(e)}')
|
||||
self.__playNext(None)
|
||||
@ -155,11 +156,8 @@ class PlayerThread(Thread):
|
||||
self.__playlist.loop_off()
|
||||
self.__songPlaying = None
|
||||
self.__playing = False
|
||||
# Send a command to the main process put this one to sleep
|
||||
sleepCommand = VCommands(VCommandsType.SLEEPING)
|
||||
self.__queueSend.put(sleepCommand)
|
||||
# Release the semaphore to finish the process
|
||||
self.__semStopPlaying.release()
|
||||
# Send a command to the main process to kill this thread
|
||||
self.__exitCB(self.__guild.id)
|
||||
|
||||
def __verifyIfSongAvailable(self, song: Song) -> bool:
|
||||
"""Verify the song source to see if it's already expired"""
|
||||
@ -1,5 +1,5 @@
|
||||
from multiprocessing import Lock
|
||||
from typing import Dict, Union
|
||||
from typing import Any, Dict, Union
|
||||
from Config.Singleton import Singleton
|
||||
from discord import Guild, Interaction, TextChannel
|
||||
from discord.ext.commands import Context
|
||||
@ -8,7 +8,7 @@ from Music.Song import Song
|
||||
from Music.Playlist import Playlist
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from Parallelism.PlayerThread import PlayerThread
|
||||
from Parallelism.ThreadPlayer import ThreadPlayer
|
||||
|
||||
|
||||
class ThreadPlayerInfo:
|
||||
@ -16,13 +16,13 @@ class ThreadPlayerInfo:
|
||||
Class to store the reference to all structures to maintain a player thread
|
||||
"""
|
||||
|
||||
def __init__(self, thread: PlayerThread, playlist: Playlist, lock: Lock, textChannel: TextChannel) -> None:
|
||||
def __init__(self, thread: ThreadPlayer, playlist: Playlist, lock: Lock, textChannel: TextChannel) -> None:
|
||||
self.__thread = thread
|
||||
self.__playlist = playlist
|
||||
self.__lock = lock
|
||||
self.__textChannel = textChannel
|
||||
|
||||
def getThread(self) -> PlayerThread:
|
||||
def getPlayer(self) -> ThreadPlayer:
|
||||
return self.__thread
|
||||
|
||||
def getPlaylist(self) -> Playlist:
|
||||
@ -45,8 +45,23 @@ class ThreadPlayerManager(Singleton, AbstractPlayersManager):
|
||||
self.__bot = bot
|
||||
self.__playersThreads: Dict[int, ThreadPlayerInfo] = {}
|
||||
|
||||
def sendCommandToPlayer(self, command: VCommands, guild: Guild, forceCreation: bool = False, context: Union[Context, Interaction] = None):
|
||||
return super().sendCommandToPlayer(command, guild, forceCreation, context)
|
||||
async def sendCommandToPlayer(self, command: VCommands, guild: Guild, forceCreation: bool = False, context: Union[Context, Interaction] = None):
|
||||
playerInfo = self.__playersThreads[guild.id]
|
||||
player = playerInfo.getPlayer()
|
||||
if player is None and forceCreation:
|
||||
self.__createPlayerThreadInfo(context)
|
||||
if player is None:
|
||||
return
|
||||
|
||||
await player.receiveCommand(command)
|
||||
|
||||
async def __receiveCommand(self, command: VCommands, guildID: int, args: Any) -> None:
|
||||
commandType = command.getType()
|
||||
if commandType == VCommandsType.NOW_PLAYING:
|
||||
await self.showNowPlaying(guildID, args)
|
||||
else:
|
||||
print(
|
||||
f'[ERROR] -> Command not processable received from Thread {guildID}: {commandType}')
|
||||
|
||||
def getPlayerPlaylist(self, guild: Guild) -> Playlist:
|
||||
playerInfo = self.__getRunningPlayerInfo(guild)
|
||||
@ -67,7 +82,7 @@ class ThreadPlayerManager(Singleton, AbstractPlayersManager):
|
||||
self.__playersThreads[guild.id] = self.__createPlayerThreadInfo(context)
|
||||
else:
|
||||
# If the thread has ended create a new one
|
||||
if not self.__playersThreads[guild.id].getThread().is_alive():
|
||||
if not self.__playersThreads[guild.id].getPlayer().is_alive():
|
||||
self.__playersThreads[guild.id] = self.__recreateThread(guild, context)
|
||||
|
||||
return self.__playersThreads[guild.id]
|
||||
@ -80,7 +95,7 @@ class ThreadPlayerManager(Singleton, AbstractPlayersManager):
|
||||
|
||||
# Recreate the thread keeping the playlist
|
||||
newPlayerInfo = self.__recreateThread(guild, context)
|
||||
newPlayerInfo.getThread().start()
|
||||
newPlayerInfo.getPlayer().start()
|
||||
# Send a command to start the play again
|
||||
playCommand = VCommands(VCommandsType.PLAY)
|
||||
newPlayerInfo.getQueueToPlayer().put(playCommand)
|
||||
@ -100,14 +115,25 @@ class ThreadPlayerManager(Singleton, AbstractPlayersManager):
|
||||
else:
|
||||
voiceID: int = context.author.voice.channel.id
|
||||
|
||||
voiceChannel = self.__bot.get_channel(voiceID)
|
||||
|
||||
playlist = Playlist()
|
||||
lock = Lock()
|
||||
player = PlayerThread(context.guild.name, playlist, lock, guildID, voiceID)
|
||||
player = ThreadPlayer(self.__bot, context.guild, context.guild.name,
|
||||
voiceChannel, playlist, lock, guildID, voiceID, self.__receiveCommand, self.__deleteThread)
|
||||
playerInfo = ThreadPlayerInfo(player, playlist, lock, context.channel)
|
||||
player.start()
|
||||
|
||||
return playerInfo
|
||||
|
||||
def __deleteThread(self, guildID: int) -> None:
|
||||
"""Tries to delete the thread and removes all the references to it"""
|
||||
playerInfo = self.__playersThreads[guildID]
|
||||
if playerInfo:
|
||||
thread = playerInfo.getPlayer()
|
||||
del thread
|
||||
self.__playersThreads.popitem(thread)
|
||||
|
||||
def __recreateThread(self, guild: Guild, context: Union[Context, Interaction]) -> ThreadPlayerInfo:
|
||||
self.__stopPossiblyRunningProcess(guild)
|
||||
|
||||
@ -116,10 +142,12 @@ class ThreadPlayerManager(Singleton, AbstractPlayersManager):
|
||||
voiceID: int = context.user.voice.channel.id
|
||||
else:
|
||||
voiceID: int = context.author.voice.channel.id
|
||||
voiceChannel = self.__bot.get_channel(voiceID)
|
||||
|
||||
playlist = self.__playersThreads[guildID].getPlaylist()
|
||||
lock = Lock()
|
||||
player = PlayerThread(context.guild.name, playlist, lock, guildID, voiceID)
|
||||
player = ThreadPlayer(self.__bot, context.guild, context.guild.name,
|
||||
voiceChannel, playlist, lock, guildID, voiceID, self.__receiveCommand, self.__deleteThread)
|
||||
playerInfo = ThreadPlayerInfo(player, playlist, lock, context.channel)
|
||||
player.start()
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user