Skip to content
This repository has been archived by the owner on Aug 1, 2021. It is now read-only.

Commit

Permalink
[voice] Better Queue (#44)
Browse files Browse the repository at this point in the history
* Add built-in Playable queue

* More functionality
  • Loading branch information
b1naryth1ef committed Jul 17, 2017
1 parent 885a215 commit 667eb1b
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 4 deletions.
2 changes: 1 addition & 1 deletion disco/voice/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def on_voice_server_update(self, data):
if self.token and self.token != data.token:
return

self.log.info('[%s] Recieved VOICE_SERVER_UPDATE (state = %s)', self, self.state)
self.log.info('[%s] Recieved VOICE_SERVER_UPDATE (state = %s / endpoint = %s)', self, self.state, data.endpoint)

self.token = data.token
self.set_state(VoiceState.AUTHENTICATING)
Expand Down
6 changes: 3 additions & 3 deletions disco/voice/player.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import time
import gevent

from six.moves import queue
from holster.enum import Enum
from holster.emitter import Emitter

from disco.voice.client import VoiceState
from disco.voice.queue import PlayableQueue

MAX_TIMESTAMP = 4294967295

Expand All @@ -19,11 +19,11 @@ class Player(object):
'DISCONNECT'
)

def __init__(self, client):
def __init__(self, client, queue=None):
self.client = client

# Queue contains playable items
self.queue = queue.Queue()
self.queue = queue or PlayableQueue()

# Whether we're playing music (true for lifetime)
self.playing = True
Expand Down
50 changes: 50 additions & 0 deletions disco/voice/queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import abc
import six
import gevent
import random


@six.add_metaclass(abc.ABCMeta)
class BaseQueue(object):
@abc.abstractmethod
def get(self):
raise NotImplementedError


class PlayableQueue(BaseQueue):
def __init__(self):
self._data = []
self._event = gevent.event.Event()

def append(self, item):
self._data.append(item)

if self._event:
self._event.set()
self._event = None

def _get(self):
if not len(self._data):
if not self._event:
self._event = gevent.event.Event()
self._event.wait()
return self._get()
return self._data.pop(0)

def get(self):
return self._get()

def shuffle(self):
random.shuffle(self._data)

def clear(self):
self._data = []

def __len__(self):
return len(self._data)

def __iter__(self):
return self._data.__iter__()

def __nonzero__(self):
return True
66 changes: 66 additions & 0 deletions tests/tests_voice_queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import gevent
from unittest import TestCase

from disco.voice.queue import PlayableQueue


class TestPlayableQueue(TestCase):
def test_append(self):
q = PlayableQueue()
q.append(1)
q.append(2)
q.append(3)

self.assertEqual(q._data, [1, 2, 3])
self.assertEqual(q.get(), 1)
self.assertEqual(q.get(), 2)
self.assertEqual(q.get(), 3)

def test_len(self):
q = PlayableQueue()

for idx in range(1234):
q.append(idx)

self.assertEqual(len(q), 1234)

def test_iter(self):
q = PlayableQueue()

for idx in range(5):
q.append(idx)

self.assertEqual(sum(q), 10)

def test_blocking_get(self):
q = PlayableQueue()
result = gevent.event.AsyncResult()

def get():
result.set(q.get())

gevent.spawn(get)
q.append(5)
self.assertEqual(result.get(), 5)

def test_shuffle(self):
q = PlayableQueue()

for idx in range(10000):
q.append(idx)

self.assertEqual(q._data[0], 0)
q.shuffle()
self.assertNotEqual(q._data[0], 0)

def test_clear(self):
q = PlayableQueue()

for idx in range(100):
q.append(idx)

self.assertEqual(q._data[0], 0)
self.assertEqual(q._data[-1], 99)
self.assertEqual(len(q), 100)
q.clear()
self.assertEqual(len(q), 0)

0 comments on commit 667eb1b

Please sign in to comment.