Reputation: 19
I have tried creating a dictionary and storing a list of .create_ytdl_player() instances to each discord server id.
I just need to know how to make the players play after the previous one has finished.
I figure I would have to use .is_playing() or .is_done() but I don't know how to use them. Can someone help?
Upvotes: 0
Views: 4497
Reputation: 884
I'll answer the question with code that works for a single instance (although it shouldn't be hard to edit it for multiple instances by fetching the right player and voice_channel objects from the dictionary).
You have to first make a queue that store the urls that your player will play your objects in. I assume that you should also make a dictionary of queues to store the different urls for the different servers.
To help manage your stream_player workflow, first declare a voice and player object in the outermost scope.
self.player = None
self.voice = None
The voice object should be set after the bot joins a voice channel:
mvoice = await client.join_voice_channel(voice channel id here)
self.voice = mvoice
We then have to make two functions as Python does not support async lamdas while managing the stream player can only be done from a async function. The play_music function should be called by the bot whenever the user types the relevant command:
#pass the url into here when a user calls the bot
async def play_music(client, message, url=None):
if url is None:
#function is being called from after (this will be explained in the next function)
if queue.size() > 0:
#fetch from queue
url = queue.dequeue()
else:
#Unset stored objects, also possibly disconnect from voice channel here
self.player = None
self.voice = None
return
if self.player is None:
#no one is using the stream player, we can start playback immediately
self.player = await self.voice.create_ytdl_player(url, after=lambda: play_next(client, message))
self.player.start()
else:
if self.player.is_playing():
#called by the user to add a song
queue.enqueue(url)
else:
#this section happens when a song has finished, we play the next song here
self.player = await self.voice.create_ytdl_player(url, after=lambda: play_next(client, message))
self.player.start()
The play_next function will be called from the finalizer after the stream player has finished a song and will call the above function again but without the url argument.
def play_next(client, message):
asyncio.run_coroutine_threadsafe(play_music(client, message), client.loop)
Upvotes: 5