mirror of
https://github.com/RafaelSolVargas/Vulkan.git
synced 2025-10-29 16:57:23 +00:00
Adding a queue for player send commands to Main process
This commit is contained in:
parent
5902a0dc72
commit
60a36425ee
@ -30,3 +30,9 @@ class VConfigs(Singleton):
|
||||
|
||||
self.MY_ERROR_BAD_COMMAND = 'This string serves to verify if some error was raised by myself on purpose'
|
||||
self.INVITE_URL = 'https://discordapp.com/oauth2/authorize?client_id={}&scope=bot'
|
||||
|
||||
def getProcessManager(self):
|
||||
return self.__manager
|
||||
|
||||
def setProcessManager(self, newManager):
|
||||
self.__manager = newManager
|
||||
|
||||
@ -19,6 +19,8 @@ from UI.Responses.EmoteCogResponse import EmoteCommandResponse
|
||||
from UI.Responses.EmbedCogResponse import EmbedCommandResponse
|
||||
from UI.Views.PlayerView import PlayerView
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from Config.Configs import VConfigs
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
|
||||
helper = Helper()
|
||||
|
||||
@ -32,6 +34,7 @@ class MusicCog(Cog):
|
||||
|
||||
def __init__(self, bot: VulkanBot) -> None:
|
||||
self.__bot: VulkanBot = bot
|
||||
VConfigs().setProcessManager(ProcessManager(bot))
|
||||
|
||||
@command(name="play", help=helper.HELP_PLAY, description=helper.HELP_PLAY_LONG, aliases=['p', 'tocar'])
|
||||
async def play(self, ctx: Context, *args) -> None:
|
||||
|
||||
@ -4,7 +4,6 @@ from discord.ext.commands import Context
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
|
||||
|
||||
class ClearHandler(AbstractHandler):
|
||||
@ -13,7 +12,7 @@ class ClearHandler(AbstractHandler):
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
# Get the current process of the guild
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if processInfo:
|
||||
# Clear the playlist
|
||||
|
||||
@ -4,7 +4,6 @@ from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Utils.Utils import Utils
|
||||
from typing import Union
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from discord import Interaction
|
||||
|
||||
|
||||
@ -14,7 +13,7 @@ class HistoryHandler(AbstractHandler):
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
# Get the current process of the guild
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if processInfo:
|
||||
processLock = processInfo.getLock()
|
||||
|
||||
@ -3,7 +3,6 @@ from Music.VulkanBot import VulkanBot
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Config.Exceptions import BadCommandUsage
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from typing import Union
|
||||
from discord import Interaction
|
||||
|
||||
@ -14,7 +13,7 @@ class LoopHandler(AbstractHandler):
|
||||
|
||||
async def run(self, args: str) -> HandlerResponse:
|
||||
# Get the current process of the guild
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if not processInfo:
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
|
||||
@ -5,7 +5,6 @@ from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Config.Exceptions import BadCommandUsage, VulkanError, InvalidInput, NumberRequired, UnknownError
|
||||
from Music.Playlist import Playlist
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from typing import Union
|
||||
from discord import Interaction
|
||||
|
||||
@ -15,7 +14,7 @@ class MoveHandler(AbstractHandler):
|
||||
super().__init__(ctx, bot)
|
||||
|
||||
async def run(self, pos1: str, pos2: str) -> HandlerResponse:
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if not processInfo:
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
|
||||
@ -3,7 +3,6 @@ from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from Utils.Cleaner import Cleaner
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from typing import Union
|
||||
from discord import Interaction
|
||||
|
||||
@ -15,7 +14,7 @@ class NowPlayingHandler(AbstractHandler):
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
# Get the current process of the guild
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if not processInfo:
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
from discord.ext.commands import Context
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from typing import Union
|
||||
@ -13,12 +12,12 @@ class PauseHandler(AbstractHandler):
|
||||
super().__init__(ctx, bot)
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if processInfo:
|
||||
# Send Pause command to be execute by player process
|
||||
command = VCommands(VCommandsType.PAUSE, None)
|
||||
queue = processInfo.getQueue()
|
||||
queue = processInfo.getQueueToPlayer()
|
||||
queue.put(command)
|
||||
|
||||
return HandlerResponse(self.ctx)
|
||||
|
||||
@ -8,7 +8,6 @@ from Handlers.HandlerResponse import HandlerResponse
|
||||
from Music.Downloader import Downloader
|
||||
from Music.Searcher import Searcher
|
||||
from Music.Song import Song
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from Parallelism.ProcessInfo import ProcessInfo
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
from Music.VulkanBot import VulkanBot
|
||||
@ -38,7 +37,7 @@ class PlayHandler(AbstractHandler):
|
||||
raise InvalidInput(self.messages.INVALID_INPUT, self.messages.ERROR_TITLE)
|
||||
|
||||
# Get the process context for the current guild
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getPlayerInfo(self.guild, self.ctx)
|
||||
playlist = processInfo.getPlaylist()
|
||||
process = processInfo.getProcess()
|
||||
@ -74,7 +73,7 @@ class PlayHandler(AbstractHandler):
|
||||
playlist.add_song(song)
|
||||
# Release the acquired Lock
|
||||
processLock.release()
|
||||
queue = processInfo.getQueue()
|
||||
queue = processInfo.getQueueToPlayer()
|
||||
playCommand = VCommands(VCommandsType.PLAY, None)
|
||||
queue.put(playCommand)
|
||||
else:
|
||||
@ -106,7 +105,7 @@ class PlayHandler(AbstractHandler):
|
||||
|
||||
async def __downloadSongsAndStore(self, songs: List[Song], processInfo: ProcessInfo) -> None:
|
||||
playlist = processInfo.getPlaylist()
|
||||
queue = processInfo.getQueue()
|
||||
queue = processInfo.getQueueToPlayer()
|
||||
playCommand = VCommands(VCommandsType.PLAY, None)
|
||||
# Trigger a task for each song to be downloaded
|
||||
tasks: List[asyncio.Task] = []
|
||||
@ -115,7 +114,7 @@ class PlayHandler(AbstractHandler):
|
||||
tasks.append(task)
|
||||
|
||||
# In the original order, await for the task and then if successfully downloaded add in the playlist
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
for index, task in enumerate(tasks):
|
||||
await task
|
||||
song = songs[index]
|
||||
|
||||
@ -2,7 +2,6 @@ from discord.ext.commands import Context
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Config.Exceptions import BadCommandUsage, ImpossibleMove
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from typing import Union
|
||||
@ -14,7 +13,7 @@ class PrevHandler(AbstractHandler):
|
||||
super().__init__(ctx, bot)
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getPlayerInfo(self.guild, self.ctx)
|
||||
if not processInfo:
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
@ -44,7 +43,7 @@ class PrevHandler(AbstractHandler):
|
||||
|
||||
# Send a prev command, together with the user voice channel
|
||||
prevCommand = VCommands(VCommandsType.PREV, self.author.voice.channel.id)
|
||||
queue = processInfo.getQueue()
|
||||
queue = processInfo.getQueueToPlayer()
|
||||
queue.put(prevCommand)
|
||||
return HandlerResponse(self.ctx)
|
||||
|
||||
|
||||
@ -3,7 +3,6 @@ from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Music.Downloader import Downloader
|
||||
from Utils.Utils import Utils
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from typing import Union
|
||||
from discord import Interaction
|
||||
@ -16,7 +15,7 @@ class QueueHandler(AbstractHandler):
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
# Retrieve the process of the guild
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if not processInfo: # If no process return empty list
|
||||
embed = self.embeds.EMPTY_QUEUE()
|
||||
|
||||
@ -4,7 +4,6 @@ from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Config.Exceptions import BadCommandUsage, VulkanError, ErrorRemoving, InvalidInput, NumberRequired
|
||||
from Music.Playlist import Playlist
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from typing import Union
|
||||
from discord import Interaction
|
||||
@ -16,7 +15,7 @@ class RemoveHandler(AbstractHandler):
|
||||
|
||||
async def run(self, position: str) -> HandlerResponse:
|
||||
# Get the current process of the guild
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if not processInfo:
|
||||
# Clear the playlist
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
from discord.ext.commands import Context
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from typing import Union
|
||||
@ -14,11 +13,11 @@ class ResetHandler(AbstractHandler):
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
# Get the current process of the guild
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if processInfo:
|
||||
command = VCommands(VCommandsType.RESET, None)
|
||||
queue = processInfo.getQueue()
|
||||
queue = processInfo.getQueueToPlayer()
|
||||
queue.put(command)
|
||||
|
||||
return HandlerResponse(self.ctx)
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
from discord.ext.commands import Context
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from typing import Union
|
||||
@ -13,12 +12,12 @@ class ResumeHandler(AbstractHandler):
|
||||
super().__init__(ctx, bot)
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if processInfo:
|
||||
# Send Resume command to be execute by player process
|
||||
command = VCommands(VCommandsType.RESUME, None)
|
||||
queue = processInfo.getQueue()
|
||||
queue = processInfo.getQueueToPlayer()
|
||||
queue.put(command)
|
||||
|
||||
return HandlerResponse(self.ctx)
|
||||
|
||||
@ -2,7 +2,6 @@ from discord.ext.commands import Context
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Config.Exceptions import UnknownError
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from typing import Union
|
||||
from discord import Interaction
|
||||
@ -13,7 +12,7 @@ class ShuffleHandler(AbstractHandler):
|
||||
super().__init__(ctx, bot)
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if processInfo:
|
||||
try:
|
||||
|
||||
@ -3,7 +3,6 @@ from Handlers.AbstractHandler import AbstractHandler
|
||||
from Config.Exceptions import BadCommandUsage
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
from typing import Union
|
||||
from discord import Interaction
|
||||
@ -14,7 +13,7 @@ class SkipHandler(AbstractHandler):
|
||||
super().__init__(ctx, bot)
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if processInfo: # Verify if there is a running process
|
||||
playlist = processInfo.getPlaylist()
|
||||
@ -25,7 +24,7 @@ class SkipHandler(AbstractHandler):
|
||||
|
||||
# Send a command to the player process to skip the music
|
||||
command = VCommands(VCommandsType.SKIP, None)
|
||||
queue = processInfo.getQueue()
|
||||
queue = processInfo.getQueueToPlayer()
|
||||
queue.put(command)
|
||||
|
||||
return HandlerResponse(self.ctx)
|
||||
|
||||
@ -2,7 +2,6 @@ from discord.ext.commands import Context
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
from typing import Union
|
||||
from discord import Interaction
|
||||
@ -13,12 +12,12 @@ class StopHandler(AbstractHandler):
|
||||
super().__init__(ctx, bot)
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
processManager = ProcessManager()
|
||||
processManager = self.config.getProcessManager()
|
||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||
if processInfo:
|
||||
# Send command to player process stop
|
||||
command = VCommands(VCommandsType.STOP, None)
|
||||
queue = processInfo.getQueue()
|
||||
queue = processInfo.getQueueToPlayer()
|
||||
queue.put(command)
|
||||
|
||||
return HandlerResponse(self.ctx)
|
||||
|
||||
63
Music/MessagesController.py
Normal file
63
Music/MessagesController.py
Normal file
@ -0,0 +1,63 @@
|
||||
from typing import List
|
||||
from discord import Embed, Message
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from Parallelism.ProcessInfo import ProcessInfo
|
||||
from Config.Configs import VConfigs
|
||||
from Config.Messages import Messages
|
||||
from Music.Song import Song
|
||||
from Config.Embeds import VEmbeds
|
||||
from UI.Views.PlayerView import PlayerView
|
||||
|
||||
|
||||
class MessagesController:
|
||||
def __init__(self, bot: VulkanBot) -> None:
|
||||
self.__bot = bot
|
||||
self.__previousMessages = []
|
||||
self.__configs = VConfigs()
|
||||
self.__messages = Messages()
|
||||
self.__embeds = VEmbeds()
|
||||
|
||||
async def sendNowPlaying(self, processInfo: ProcessInfo, song: Song) -> None:
|
||||
# Get the lock of the playlist
|
||||
print('Entrei')
|
||||
playlistLock = processInfo.getLock()
|
||||
playlist = processInfo.getPlaylist()
|
||||
with playlistLock:
|
||||
print('A')
|
||||
if playlist.isLoopingOne():
|
||||
title = self.__messages.ONE_SONG_LOOPING
|
||||
else:
|
||||
title = self.__messages.SONG_PLAYING
|
||||
|
||||
embed = self.__embeds.SONG_INFO(song.info, title)
|
||||
view = PlayerView(self.__bot)
|
||||
channel = processInfo.getTextChannel()
|
||||
|
||||
await self.__deletePreviousNPMessages()
|
||||
await channel.send(embed=embed, view=view)
|
||||
self.__previousMessages.append(await self.__getSendedMessage())
|
||||
|
||||
async def __deletePreviousNPMessages(self) -> None:
|
||||
for message in self.__previousMessages:
|
||||
try:
|
||||
await message.delete()
|
||||
except:
|
||||
pass
|
||||
self.__previousMessages.clear()
|
||||
|
||||
async def __getSendedMessage(self) -> Message:
|
||||
stringToIdentify = 'Uploader:'
|
||||
last_messages: List[Message] = await self.__textChannel.history(limit=5).flatten()
|
||||
|
||||
for message in last_messages:
|
||||
try:
|
||||
if message.author == self.__bot.user:
|
||||
if len(message.embeds) > 0:
|
||||
embed: Embed = message.embeds[0]
|
||||
if len(embed.fields) > 0:
|
||||
if embed.fields[0].name == stringToIdentify:
|
||||
return message
|
||||
|
||||
except Exception as e:
|
||||
print(f'DEVELOPER NOTE -> Error cleaning messages {e}')
|
||||
continue
|
||||
@ -11,6 +11,9 @@ class VCommandsType(Enum):
|
||||
PLAY = 'Play'
|
||||
STOP = 'Stop'
|
||||
RESET = 'Reset'
|
||||
NOW_PLAYING = 'Now Playing'
|
||||
TERMINATE = 'Terminate'
|
||||
SLEEPING = 'Sleeping'
|
||||
|
||||
|
||||
class VCommands:
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import asyncio
|
||||
from Music.VulkanInitializer import VulkanInitializer
|
||||
from discord import User, Member, Message, Embed
|
||||
from asyncio import AbstractEventLoop, Semaphore
|
||||
from multiprocessing import Process, Queue, RLock
|
||||
from threading import Lock, Thread
|
||||
from asyncio import AbstractEventLoop, Semaphore, Queue
|
||||
from multiprocessing import Process, RLock, Lock
|
||||
from threading import Thread
|
||||
from typing import Callable, List
|
||||
from discord import Guild, FFmpegPCMAudio, VoiceChannel, TextChannel
|
||||
from Music.Playlist import Playlist
|
||||
@ -31,7 +31,7 @@ class TimeoutClock:
|
||||
class PlayerProcess(Process):
|
||||
"""Process that will play songs, receive commands from the main process by a Queue"""
|
||||
|
||||
def __init__(self, name: str, playlist: Playlist, lock: Lock, queue: Queue, guildID: int, textID: int, voiceID: int, authorID: int) -> None:
|
||||
def __init__(self, name: str, playlist: Playlist, lock: Lock, queueToReceive: Queue, queueToSend: Queue, guildID: int, textID: int, voiceID: int, authorID: int) -> None:
|
||||
"""
|
||||
Start a new process that will have his own bot instance
|
||||
Due to pickle serialization, no objects are stored, the values initialization are being made in the run method
|
||||
@ -40,7 +40,8 @@ class PlayerProcess(Process):
|
||||
# Synchronization objects
|
||||
self.__playlist: Playlist = playlist
|
||||
self.__playlistLock: Lock = lock
|
||||
self.__queue: Queue = queue
|
||||
self.__queueReceive: Queue = queueToReceive
|
||||
self.__queueSend: Queue = queueToSend
|
||||
self.__semStopPlaying: Semaphore = None
|
||||
self.__loop: AbstractEventLoop = None
|
||||
# Discord context ID
|
||||
@ -96,8 +97,7 @@ class PlayerProcess(Process):
|
||||
# Start the timeout function
|
||||
self.__timer = TimeoutClock(self.__timeoutHandler, self.__loop)
|
||||
# Thread that will receive commands to be executed in this Process
|
||||
self.__commandsReceiver = Thread(target=self.__commandsReceiver, daemon=True)
|
||||
self.__commandsReceiver.start()
|
||||
self.__loop.create_task(self.__commandsReceiver())
|
||||
|
||||
# Start a Task to play songs
|
||||
self.__loop.create_task(self.__playPlaylistSongs())
|
||||
@ -146,8 +146,10 @@ class PlayerProcess(Process):
|
||||
self.__timer.cancel()
|
||||
self.__timer = TimeoutClock(self.__timeoutHandler, self.__loop)
|
||||
|
||||
await self.__deletePrevNowPlaying()
|
||||
await self.__showNowPlaying()
|
||||
nowPlayingCommand = VCommands(VCommandsType.NOW_PLAYING, song)
|
||||
await self.__queueSend.put(nowPlayingCommand)
|
||||
# await self.__deletePrevNowPlaying()
|
||||
# await self.__showNowPlaying()
|
||||
except Exception as e:
|
||||
print(f'[ERROR IN PLAY SONG] -> {e}, {type(e)}')
|
||||
self.__playNext(None)
|
||||
@ -190,12 +192,11 @@ class PlayerProcess(Process):
|
||||
|
||||
self.__loop.create_task(self.__playSong(song), name=f'Song {song.identifier}')
|
||||
|
||||
def __commandsReceiver(self) -> None:
|
||||
async def __commandsReceiver(self) -> None:
|
||||
while True:
|
||||
command: VCommands = self.__queue.get()
|
||||
command: VCommands = await self.__queueReceive.get()
|
||||
type = command.getType()
|
||||
args = command.getArgs()
|
||||
print(f'{self.name} received command {type}')
|
||||
|
||||
try:
|
||||
self.__playerLock.acquire()
|
||||
@ -206,13 +207,13 @@ class PlayerProcess(Process):
|
||||
elif type == VCommandsType.SKIP:
|
||||
self.__skip()
|
||||
elif type == VCommandsType.PLAY:
|
||||
asyncio.run_coroutine_threadsafe(self.__playPlaylistSongs(), self.__loop)
|
||||
await self.__playPlaylistSongs()
|
||||
elif type == VCommandsType.PREV:
|
||||
asyncio.run_coroutine_threadsafe(self.__playPrev(args), self.__loop)
|
||||
await self.__playPrev(args)
|
||||
elif type == VCommandsType.RESET:
|
||||
asyncio.run_coroutine_threadsafe(self.__reset(), self.__loop)
|
||||
await self.__reset()
|
||||
elif type == VCommandsType.STOP:
|
||||
asyncio.run_coroutine_threadsafe(self.__stop(), self.__loop)
|
||||
await self.__stop()
|
||||
else:
|
||||
print(f'[ERROR] -> Unknown Command Received: {command}')
|
||||
except Exception as e:
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
from multiprocessing import Process, Queue, Lock
|
||||
from discord import TextChannel
|
||||
from Music.Playlist import Playlist
|
||||
|
||||
|
||||
@ -7,11 +8,13 @@ class ProcessInfo:
|
||||
Class to store the reference to all structures to maintain a player process
|
||||
"""
|
||||
|
||||
def __init__(self, process: Process, queue: Queue, playlist: Playlist, lock: Lock) -> None:
|
||||
def __init__(self, process: Process, queueToPlayer: Queue, queueToMain: Queue, playlist: Playlist, lock: Lock, textChannel: TextChannel) -> None:
|
||||
self.__process = process
|
||||
self.__queue = queue
|
||||
self.__queueToPlayer = queueToPlayer
|
||||
self.__queueToMain = queueToMain
|
||||
self.__playlist = playlist
|
||||
self.__lock = lock
|
||||
self.__textChannel = textChannel
|
||||
|
||||
def setProcess(self, newProcess: Process) -> None:
|
||||
self.__process = newProcess
|
||||
@ -19,11 +22,17 @@ class ProcessInfo:
|
||||
def getProcess(self) -> Process:
|
||||
return self.__process
|
||||
|
||||
def getQueue(self) -> Queue:
|
||||
return self.__queue
|
||||
def getQueueToPlayer(self) -> Queue:
|
||||
return self.__queueToPlayer
|
||||
|
||||
def getQueueToMain(self) -> Queue:
|
||||
return self.__queueToMain
|
||||
|
||||
def getPlaylist(self) -> Playlist:
|
||||
return self.__playlist
|
||||
|
||||
def getLock(self) -> Lock:
|
||||
return self.__lock
|
||||
|
||||
def getTextChannel(self) -> TextChannel:
|
||||
return self.__textChannel
|
||||
|
||||
@ -1,13 +1,21 @@
|
||||
from multiprocessing import Queue, Lock
|
||||
from asyncio import Queue, Task
|
||||
import asyncio
|
||||
from multiprocessing import Lock
|
||||
from multiprocessing.managers import BaseManager, NamespaceProxy
|
||||
from typing import Dict, Union
|
||||
from queue import Empty
|
||||
from threading import Thread
|
||||
from typing import Dict, Tuple, Union
|
||||
from Config.Singleton import Singleton
|
||||
from discord import Guild, Interaction
|
||||
from discord.ext.commands import Context
|
||||
from Music.MessagesController import MessagesController
|
||||
from Music.Song import Song
|
||||
from Parallelism.PlayerProcess import PlayerProcess
|
||||
from Music.Playlist import Playlist
|
||||
from Parallelism.ProcessInfo import ProcessInfo
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from Tests.LoopRunner import LoopRunner
|
||||
|
||||
|
||||
class ProcessManager(Singleton):
|
||||
@ -16,12 +24,16 @@ class ProcessManager(Singleton):
|
||||
Deal with the creation of shared memory
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
def __init__(self, bot: VulkanBot = None) -> None:
|
||||
if not super().created:
|
||||
self.__bot = bot
|
||||
VManager.register('Playlist', Playlist)
|
||||
self.__manager = VManager()
|
||||
self.__manager.start()
|
||||
self.__playersProcess: Dict[Guild, ProcessInfo] = {}
|
||||
# self.__playersListeners: Dict[Guild, Tuple[Thread, bool]] = {}
|
||||
self.__playersListeners: Dict[Guild, Task] = {}
|
||||
self.__playersMessages: Dict[Guild, MessagesController] = {}
|
||||
|
||||
def setPlayerInfo(self, guild: Guild, info: ProcessInfo):
|
||||
self.__playersProcess[guild.id] = info
|
||||
@ -37,11 +49,11 @@ class ProcessManager(Singleton):
|
||||
return self.__playersProcess[guild.id]
|
||||
|
||||
if guild.id not in self.__playersProcess.keys():
|
||||
self.__playersProcess[guild.id] = self.__createProcessInfo(context)
|
||||
self.__playersProcess[guild.id] = self.__createProcessInfo(guild, context)
|
||||
else:
|
||||
# If the process has ended create a new one
|
||||
if not self.__playersProcess[guild.id].getProcess().is_alive():
|
||||
self.__playersProcess[guild.id] = self.__recreateProcess(context)
|
||||
self.__playersProcess[guild.id] = self.__recreateProcess(guild, context)
|
||||
|
||||
return self.__playersProcess[guild.id]
|
||||
except Exception as e:
|
||||
@ -53,11 +65,11 @@ class ProcessManager(Singleton):
|
||||
return None
|
||||
|
||||
# Recreate the process keeping the playlist
|
||||
newProcessInfo = self.__recreateProcess(context)
|
||||
newProcessInfo = self.__recreateProcess(guild, context)
|
||||
newProcessInfo.getProcess().start() # Start the process
|
||||
# Send a command to start the play again
|
||||
playCommand = VCommands(VCommandsType.PLAY)
|
||||
newProcessInfo.getQueue().put(playCommand)
|
||||
newProcessInfo.getQueueToPlayer().put(playCommand)
|
||||
self.__playersProcess[guild.id] = newProcessInfo
|
||||
|
||||
def getRunningPlayerInfo(self, guild: Guild) -> ProcessInfo:
|
||||
@ -67,7 +79,7 @@ class ProcessManager(Singleton):
|
||||
|
||||
return self.__playersProcess[guild.id]
|
||||
|
||||
def __createProcessInfo(self, context: Context) -> ProcessInfo:
|
||||
def __createProcessInfo(self, guild: Guild, context: Context) -> ProcessInfo:
|
||||
guildID: int = context.guild.id
|
||||
textID: int = context.channel.id
|
||||
voiceID: int = context.author.voice.channel.id
|
||||
@ -75,14 +87,25 @@ class ProcessManager(Singleton):
|
||||
|
||||
playlist: Playlist = self.__manager.Playlist()
|
||||
lock = Lock()
|
||||
queue = Queue()
|
||||
process = PlayerProcess(context.guild.name, playlist, lock, queue,
|
||||
guildID, textID, voiceID, authorID)
|
||||
processInfo = ProcessInfo(process, queue, playlist, lock)
|
||||
queueToListen = Queue()
|
||||
queueToSend = Queue()
|
||||
process = PlayerProcess(context.guild.name, playlist, lock, queueToSend,
|
||||
queueToListen, guildID, textID, voiceID, authorID)
|
||||
processInfo = ProcessInfo(process, queueToSend, queueToListen,
|
||||
playlist, lock, context.channel)
|
||||
|
||||
task = asyncio.create_task(self.__listenToCommands(queueToListen, guild))
|
||||
# Create a Thread to listen for the queue coming from the Player Process
|
||||
# thread = Thread(target=self.__listenToCommands, args=(queueToListen, guild), daemon=True)
|
||||
self.__playersListeners[guildID] = task
|
||||
# thread.start()
|
||||
|
||||
# Create a Message Controller for this player
|
||||
self.__playersMessages[guildID] = MessagesController(self.__bot)
|
||||
|
||||
return processInfo
|
||||
|
||||
def __recreateProcess(self, context: Context) -> ProcessInfo:
|
||||
def __recreateProcess(self, guild: Guild, context: Context) -> ProcessInfo:
|
||||
"""Create a new process info using previous playlist"""
|
||||
guildID: int = context.guild.id
|
||||
textID: int = context.channel.id
|
||||
@ -91,14 +114,78 @@ class ProcessManager(Singleton):
|
||||
|
||||
playlist: Playlist = self.__playersProcess[guildID].getPlaylist()
|
||||
lock = Lock()
|
||||
queue = Queue()
|
||||
queueToListen = Queue()
|
||||
queueToSend = Queue()
|
||||
process = PlayerProcess(context.guild.name, playlist, lock, queueToSend,
|
||||
queueToListen, guildID, textID, voiceID, authorID)
|
||||
processInfo = ProcessInfo(process, queueToSend, queueToListen, playlist, lock)
|
||||
|
||||
process = PlayerProcess(context.guild.name, playlist, lock, queue,
|
||||
guildID, textID, voiceID, authorID)
|
||||
processInfo = ProcessInfo(process, queue, playlist, lock)
|
||||
task = asyncio.create_task(self.__listenToCommands(queueToListen, guild))
|
||||
# Create a Thread to listen for the queue coming from the Player Process
|
||||
# thread = Thread(target=self.__listenToCommands, args=(queueToListen, guild), daemon=True)
|
||||
self.__playersListeners[guildID] = task
|
||||
# thread.start()
|
||||
|
||||
# Create a Message Controller for this player
|
||||
self.__playersMessages[guildID] = MessagesController(self.__bot)
|
||||
|
||||
return processInfo
|
||||
|
||||
async def __listenToCommands(self, queue: Queue, guild: Guild) -> None:
|
||||
shouldEnd = False
|
||||
guildID = guild.id
|
||||
while not shouldEnd:
|
||||
shouldEnd = self.__playersListeners[guildID][1]
|
||||
try:
|
||||
print('Esperando')
|
||||
command: VCommands = await queue.get()
|
||||
commandType = command.getType()
|
||||
args = command.getArgs()
|
||||
|
||||
print(f'Process {guild.name} sended command {commandType}')
|
||||
if commandType == VCommandsType.NOW_PLAYING:
|
||||
print('Aqui dentro')
|
||||
await self.__showNowPlaying(args, guildID)
|
||||
elif commandType == VCommandsType.TERMINATE:
|
||||
# Delete the process elements and return, to finish task
|
||||
self.__terminateProcess()
|
||||
return
|
||||
elif commandType == VCommandsType.SLEEPING:
|
||||
# The process might be used again
|
||||
self.__sleepingProcess()
|
||||
return
|
||||
else:
|
||||
print(f'[ERROR] -> Unknown Command Received from Process: {commandType}')
|
||||
except Empty:
|
||||
continue
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(f'[ERROR IN LISTENING PROCESS] -> {guild.name} - {e}')
|
||||
|
||||
def __terminateProcess(self, guildID: int) -> None:
|
||||
# Delete all structures associated with the Player
|
||||
del self.__playersProcess[guildID]
|
||||
del self.__playersMessages[guildID]
|
||||
threadListening = self.__playersListeners[guildID]
|
||||
threadListening._stop()
|
||||
del self.__playersListeners[guildID]
|
||||
|
||||
def __sleepingProcess(self, guildID: int) -> None:
|
||||
# Disable all process structures, except Playlist
|
||||
queue1 = self.__playersProcess[guildID].getQueueToMain()
|
||||
queue2 = self.__playersProcess[guildID].getQueueToPlayer()
|
||||
queue1.close()
|
||||
queue1.join_thread()
|
||||
queue2.close()
|
||||
queue2.join_thread()
|
||||
|
||||
async def __showNowPlaying(self, guildID: int, song: Song) -> None:
|
||||
messagesController = self.__playersMessages[guildID]
|
||||
processInfo = self.__playersProcess[guildID]
|
||||
print('Aq1')
|
||||
await messagesController.sendNowPlaying(processInfo, song)
|
||||
print('Aq2')
|
||||
|
||||
|
||||
class VManager(BaseManager):
|
||||
pass
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
from typing import Optional
|
||||
from discord.ui import View
|
||||
from Config.Emojis import VEmojis
|
||||
from UI.Buttons.PauseButton import PauseButton
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user