mirror of
https://github.com/RafaelSolVargas/Vulkan.git
synced 2025-10-29 16:57:23 +00:00
Adding volume change command, pre-release
This commit is contained in:
parent
fc02cab769
commit
2114f15840
@ -343,6 +343,13 @@ class VEmbeds:
|
||||
description=self.__messages.PLAYER_NOT_PLAYING,
|
||||
colour=self.__colors.BLUE)
|
||||
return embed
|
||||
|
||||
def VOLUME_CHANGED(self, volume: float) -> Embed:
|
||||
embed = Embed(
|
||||
title=self.__messages.SONG_PLAYER,
|
||||
description=self.__messages.VOLUME_CHANGED.format(volume),
|
||||
colour=self.__colors.BLUE)
|
||||
return embed
|
||||
|
||||
def QUEUE(self, title: str, description: str) -> Embed:
|
||||
embed = Embed(
|
||||
|
||||
@ -30,6 +30,8 @@ class Helper(Singleton):
|
||||
self.HELP_SHUFFLE = 'Shuffle the songs playing.'
|
||||
self.HELP_SHUFFLE_LONG = 'Randomly shuffle the songs in the queue.\n\nArguments: None.'
|
||||
self.HELP_PLAY = 'Plays a song from URL'
|
||||
self.CHANGE_VOLUME = '**[Pre-release]** - Set the volume of the song'
|
||||
self.CHANGE_VOLUME_LONG = '**[Pre-release]** - Change the volume of the song, expect a number from 0 to 100'
|
||||
self.HELP_PLAY_LONG = 'Play a song in discord. \n\nRequire: You to be connected to a voice channel.\nArguments: Youtube, Spotify or Deezer song/playlist link or the title of the song to be searched in Youtube.'
|
||||
self.HELP_HISTORY = f'Show the history of played songs.'
|
||||
self.HELP_HISTORY_LONG = f'Show the last {config.MAX_SONGS_HISTORY} played songs'
|
||||
|
||||
@ -16,6 +16,7 @@ class Messages(Singleton):
|
||||
self.SONGINFO_REQUESTER = 'Requester: '
|
||||
self.SONGINFO_POSITION = 'Position: '
|
||||
|
||||
self.VOLUME_CHANGED = '**[Pre-release]** - Song volume changed to `{}`%'
|
||||
self.SONGS_ADDED = 'Downloading `{}` songs to add to the queue'
|
||||
self.SONG_ADDED = 'Downloading the song `{}` to add to the queue'
|
||||
self.SONG_ADDED_TWO = f'{self.__emojis.MUSIC} Song added to the queue'
|
||||
@ -56,6 +57,7 @@ class Messages(Singleton):
|
||||
self.ERROR_MOVING = f'{self.__emojis.ERROR} Error while moving the songs'
|
||||
self.LENGTH_ERROR = f'{self.__emojis.ERROR} Numbers must be between 1 and queue length, use -1 for the last song'
|
||||
self.ERROR_NUMBER = f'{self.__emojis.ERROR} This command require a number'
|
||||
self.ERROR_VOLUME_NUMBER = f'{self.__emojis.ERROR} This command require a number between 0 and 100'
|
||||
self.ERROR_PLAYING = f'{self.__emojis.ERROR} Error while playing songs'
|
||||
self.COMMAND_NOT_FOUND = f'{self.__emojis.ERROR} Command not found, type {configs.BOT_PREFIX}help to see all commands'
|
||||
self.UNKNOWN_ERROR = f'{self.__emojis.ERROR} Unknown Error, if needed, use {configs.BOT_PREFIX}reset to reset the player of your server'
|
||||
|
||||
@ -21,7 +21,7 @@ class ControlCog(Cog):
|
||||
'MUSIC': ['resume', 'pause', 'loop', 'stop',
|
||||
'skip', 'play', 'queue', 'clear',
|
||||
'np', 'shuffle', 'move', 'remove',
|
||||
'reset', 'prev', 'history'],
|
||||
'reset', 'prev', 'history', 'volume'],
|
||||
'RANDOM': ['choose', 'cara', 'random']
|
||||
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ from Handlers.ResumeHandler import ResumeHandler
|
||||
from Handlers.HistoryHandler import HistoryHandler
|
||||
from Handlers.QueueHandler import QueueHandler
|
||||
from Handlers.LoopHandler import LoopHandler
|
||||
from Handlers.VolumeHandler import VolumeHandler
|
||||
from Messages.MessagesCategory import MessagesCategory
|
||||
from Messages.Responses.EmoteCogResponse import EmoteCommandResponse
|
||||
from Messages.Responses.EmbedCogResponse import EmbedCommandResponse
|
||||
@ -64,6 +65,25 @@ class MusicCog(Cog):
|
||||
except Exception as e:
|
||||
print(f'[ERROR IN COG] -> {e}')
|
||||
|
||||
@command(name="volume", help=helper.CHANGE_VOLUME, description=helper.CHANGE_VOLUME_LONG, aliases=['v'])
|
||||
async def volume(self, ctx: Context, *args) -> None:
|
||||
try:
|
||||
controller = VolumeHandler(ctx, self.__bot)
|
||||
|
||||
if len(args) > 1:
|
||||
track = " ".join(args)
|
||||
else:
|
||||
track = args[0]
|
||||
|
||||
response = await controller.run(track)
|
||||
if response is not None:
|
||||
cogResponser1 = EmbedCommandResponse(response, MessagesCategory.PLAYER)
|
||||
cogResponser2 = EmoteCommandResponse(response, MessagesCategory.PLAYER)
|
||||
await cogResponser1.run()
|
||||
await cogResponser2.run()
|
||||
except Exception as e:
|
||||
print(f'[ERROR IN COG] -> {e}')
|
||||
|
||||
@command(name="queue", help=helper.HELP_QUEUE, description=helper.HELP_QUEUE_LONG, aliases=['q', 'fila', 'musicas'])
|
||||
async def queue(self, ctx: Context, *args) -> None:
|
||||
try:
|
||||
|
||||
@ -15,6 +15,7 @@ from Handlers.ResumeHandler import ResumeHandler
|
||||
from Handlers.HistoryHandler import HistoryHandler
|
||||
from Handlers.QueueHandler import QueueHandler
|
||||
from Handlers.LoopHandler import LoopHandler
|
||||
from Handlers.VolumeHandler import VolumeHandler
|
||||
from Messages.MessagesCategory import MessagesCategory
|
||||
from Messages.Responses.SlashEmbedResponse import SlashEmbedResponse
|
||||
from Music.VulkanBot import VulkanBot
|
||||
@ -237,6 +238,22 @@ class SlashCommands(Cog):
|
||||
except Exception:
|
||||
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||
|
||||
@slash_command(name='volume', description=helper.CHANGE_VOLUME_LONG)
|
||||
async def move(self, ctx: ApplicationContext,
|
||||
volume: Option(float, "The new volume of the song", min_value=1, default= 100)) -> None:
|
||||
if not self.__bot.listingSlash:
|
||||
return
|
||||
try:
|
||||
await ctx.defer()
|
||||
|
||||
controller = VolumeHandler(ctx, self.__bot)
|
||||
|
||||
response = await controller.run(f'{volume}')
|
||||
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.PLAYER)
|
||||
await cogResponser.run()
|
||||
except Exception:
|
||||
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||
|
||||
@slash_command(name='remove', description=helper.HELP_REMOVE)
|
||||
async def remove(self, ctx: ApplicationContext,
|
||||
position: Option(int, "The song position to remove", min_value=1)) -> None:
|
||||
|
||||
62
Handlers/VolumeHandler.py
Normal file
62
Handlers/VolumeHandler.py
Normal file
@ -0,0 +1,62 @@
|
||||
from Config.Exceptions import BadCommandUsage, NumberRequired, VulkanError
|
||||
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from discord.ext.commands import Context
|
||||
from Music.VulkanBot import VulkanBot
|
||||
from discord import Interaction
|
||||
from typing import Union
|
||||
|
||||
|
||||
class VolumeHandler(AbstractHandler):
|
||||
def __init__(self, ctx: Union[Context, Interaction], bot: VulkanBot) -> None:
|
||||
super().__init__(ctx, bot)
|
||||
|
||||
async def run(self, args: str) -> HandlerResponse:
|
||||
if args is None or args.strip() == '':
|
||||
error = BadCommandUsage()
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
error = self.__validateInput(args)
|
||||
if error:
|
||||
embed = self.embeds.ERROR_EMBED(error.message)
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
playersManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||
if not playersManager.verifyIfPlayerExists(self.guild):
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
error = BadCommandUsage()
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
playerLock = playersManager.getPlayerLock(self.guild)
|
||||
acquired = playerLock.acquire(timeout=self.config.ACQUIRE_LOCK_TIMEOUT)
|
||||
volume = self.__convert_input_to_volume(args)
|
||||
if acquired:
|
||||
volumeCommand = VCommands(VCommandsType.VOLUME, volume)
|
||||
await playersManager.sendCommandToPlayer(volumeCommand, self.guild, self.ctx)
|
||||
|
||||
playerLock.release()
|
||||
|
||||
embed = self.embeds.VOLUME_CHANGED(volume)
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
else:
|
||||
playersManager.resetPlayer(self.guild, self.ctx)
|
||||
|
||||
embed = self.embeds.PLAYER_RESTARTED()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
|
||||
def __convert_input_to_volume(self, input_volume: str) -> float:
|
||||
volume = float(input_volume)
|
||||
if volume < 0:
|
||||
volume = 0
|
||||
if volume > 100:
|
||||
volume = 100
|
||||
|
||||
return volume
|
||||
|
||||
def __validateInput(self, volume: str) -> Union[VulkanError, None]:
|
||||
try:
|
||||
_ = float(volume)
|
||||
except:
|
||||
return NumberRequired(self.messages.ERROR_VOLUME_NUMBER)
|
||||
@ -13,6 +13,7 @@ class VCommandsType(Enum):
|
||||
RESET = 'Reset'
|
||||
NOW_PLAYING = 'Now Playing'
|
||||
TERMINATE = 'Terminate'
|
||||
VOLUME = 'Volume'
|
||||
SLEEPING = 'Sleeping'
|
||||
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import asyncio
|
||||
from time import sleep, time
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
from Music.VulkanInitializer import VulkanInitializer
|
||||
from discord import VoiceClient
|
||||
from discord import PCMVolumeTransformer, VoiceClient
|
||||
from asyncio import AbstractEventLoop, Semaphore, Queue
|
||||
from multiprocessing import Process, RLock, Lock, Queue
|
||||
from threading import Thread
|
||||
@ -54,6 +54,7 @@ class ProcessPlayer(Process):
|
||||
self.__voiceChannel: VoiceChannel = None
|
||||
self.__voiceClient: VoiceClient = None
|
||||
|
||||
self.__currentSongChangeVolume = False
|
||||
self.__playing = False
|
||||
self.__forceStop = False
|
||||
self.__botCompletedLoad = False
|
||||
@ -98,6 +99,31 @@ class ProcessPlayer(Process):
|
||||
# In this point the process should finalize
|
||||
self.__timer.cancel()
|
||||
|
||||
def __set_volume(self, volume: float) -> None:
|
||||
"""Set the volume of the player, must be values between 0 and 100"""
|
||||
try:
|
||||
if self.__voiceClient is None:
|
||||
return
|
||||
|
||||
if not isinstance(volume, float):
|
||||
print('[PROCESS ERROR] -> Volume instance must be float')
|
||||
return
|
||||
|
||||
if volume < 0:
|
||||
volume = 0
|
||||
if volume > 100:
|
||||
volume = 100
|
||||
|
||||
volume = volume / 100
|
||||
|
||||
if not self.__currentSongChangeVolume:
|
||||
print('[PROCESS ERROR] -> Cannot change the volume of this song')
|
||||
return
|
||||
|
||||
self.__voiceClient.source.volume = volume
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
def __verifyIfIsPlaying(self) -> bool:
|
||||
if self.__voiceClient is None:
|
||||
return False
|
||||
@ -151,6 +177,10 @@ class ProcessPlayer(Process):
|
||||
self.__songPlaying = song
|
||||
|
||||
player = FFmpegPCMAudio(song.source, **self.FFMPEG_OPTIONS)
|
||||
if not player.is_opus():
|
||||
player = PCMVolumeTransformer(player, 1)
|
||||
self.__currentSongChangeVolume = True
|
||||
|
||||
self.__voiceClient.play(player, after=lambda e: self.__playNext(e))
|
||||
|
||||
self.__timer.cancel()
|
||||
@ -169,6 +199,8 @@ class ProcessPlayer(Process):
|
||||
print(f'[PROCESS PLAYER -> ERROR PLAYING SONG] -> {error}')
|
||||
with self.__playlistLock:
|
||||
with self.__playerLock:
|
||||
self.__currentSongChangeVolume = False
|
||||
|
||||
if self.__forceStop: # If it's forced to stop player
|
||||
self.__forceStop = False
|
||||
return None
|
||||
@ -271,6 +303,8 @@ class ProcessPlayer(Process):
|
||||
asyncio.run_coroutine_threadsafe(self.__reset(), self.__loop)
|
||||
elif type == VCommandsType.STOP:
|
||||
asyncio.run_coroutine_threadsafe(self.__stop(), self.__loop)
|
||||
elif type == VCommandsType.VOLUME:
|
||||
self.__set_volume(args)
|
||||
else:
|
||||
print(f'[PROCESS PLAYER ERROR] -> Unknown Command Received: {command}')
|
||||
except Exception as e:
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import asyncio
|
||||
from time import time
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
from discord import VoiceClient
|
||||
from discord import PCMVolumeTransformer, VoiceClient
|
||||
from asyncio import AbstractEventLoop
|
||||
from threading import RLock, Thread
|
||||
from multiprocessing import Lock
|
||||
@ -45,6 +45,7 @@ class ThreadPlayer(Thread):
|
||||
self.__voiceChannel: VoiceChannel = voiceChannel
|
||||
self.__voiceClient: VoiceClient = None
|
||||
|
||||
self.__currentSongChangeVolume = False
|
||||
self.__downloader = Downloader()
|
||||
self.__callback = callbackToSendCommand
|
||||
self.__exitCB = exitCB
|
||||
@ -56,6 +57,31 @@ class ThreadPlayer(Thread):
|
||||
self.FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
|
||||
'options': '-vn'}
|
||||
|
||||
def __set_volume(self, volume: float) -> None:
|
||||
"""Set the volume of the player, must be values between 0 and 100"""
|
||||
try:
|
||||
if self.__voiceClient is None:
|
||||
return
|
||||
|
||||
if not isinstance(volume, float):
|
||||
print('[THREAD ERROR] -> Volume instance must be float')
|
||||
return
|
||||
|
||||
if volume < 0:
|
||||
volume = 0
|
||||
if volume > 100:
|
||||
volume = 100
|
||||
|
||||
volume = volume / 100
|
||||
|
||||
if not self.__currentSongChangeVolume:
|
||||
print('[THREAD ERROR] -> Cannot change the volume of this song')
|
||||
return
|
||||
|
||||
self.__voiceClient.source.volume = volume
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
def __verifyIfIsPlaying(self) -> bool:
|
||||
if self.__voiceClient is None:
|
||||
return False
|
||||
@ -109,6 +135,9 @@ class ThreadPlayer(Thread):
|
||||
self.__songPlaying = song
|
||||
|
||||
player = FFmpegPCMAudio(song.source, **self.FFMPEG_OPTIONS)
|
||||
if not player.is_opus():
|
||||
player = PCMVolumeTransformer(player, 1)
|
||||
self.__currentSongChangeVolume = True
|
||||
self.__voiceClient.play(player, after=lambda e: self.__playNext(e))
|
||||
|
||||
self.__timer.cancel()
|
||||
@ -127,6 +156,7 @@ class ThreadPlayer(Thread):
|
||||
print(f'[THREAD PLAYER -> ERROR PLAYING SONG] -> {error}')
|
||||
with self.__playlistLock:
|
||||
with self.__playerLock:
|
||||
self.__currentSongChangeVolume = False
|
||||
if self.__forceStop: # If it's forced to stop player
|
||||
self.__forceStop = False
|
||||
return None
|
||||
@ -217,6 +247,8 @@ class ThreadPlayer(Thread):
|
||||
await self.__reset()
|
||||
elif type == VCommandsType.STOP:
|
||||
await self.__stop()
|
||||
elif type == VCommandsType.VOLUME:
|
||||
self.__set_volume(args)
|
||||
else:
|
||||
print(f'[THREAD PLAYER ERROR] -> Unknown Command Received: {command}')
|
||||
except Exception as e:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user