# Path: uchroma/util.py
# def ensure_future(coro, loop=None):
#     """
#     Wrapper for asyncio.ensure_future which dumps exceptions
#     """
#     if loop is None:
#         loop = asyncio.get_event_loop()
#     fut = asyncio.ensure_future(coro, loop=loop)
#     def exception_logging_done_cb(fut):
#         try:
#             e = fut.exception()
#         except asyncio.CancelledError:
#             return
#         if e is not None:
#             loop.call_exception_handler({
#                 'message': 'Unhandled exception in async future',
#                 'future': fut,
#                 'exception': e,
#             })
#     fut.add_done_callback(exception_logging_done_cb)
#     return fut


import asyncio
import functools
import evdev
from concurrent import futures
from uchroma.util import ensure_future
            return True

        if not self._opened:
            if not self._open_input_devices():
                return False

        self._event_callbacks.append(callback)
        return True


    async def remove_callback(self, callback):
        """
        Removes a previously registered callback

        :param callback: coroutine to remove
        """
        if callback not in self._event_callbacks:
            return

        self._event_callbacks.remove(callback)

        if not self._event_callbacks:
            await self._close_input_devices()


    async def shutdown(self):
        """
        Shuts down the InputManager and disconnects any active callbacks
        """
        for callback in self._event_callbacks:

# Path: uchroma/util.py
# def ensure_future(coro, loop=None):
#     """
#     Wrapper for asyncio.ensure_future which dumps exceptions
#     """
#     if loop is None:
#         loop = asyncio.get_event_loop()
#     fut = asyncio.ensure_future(coro, loop=loop)
#     def exception_logging_done_cb(fut):
#         try:
#             e = fut.exception()
#         except asyncio.CancelledError:
#             return
#         if e is not None:
#             loop.call_exception_handler({
#                 'message': 'Unhandled exception in async future',
#                 'future': fut,
#                 'exception': e,
#             })
#     fut.add_done_callback(exception_logging_done_cb)
#     return fut


# Path: uchroma/server/input.py
import asyncio
import functools
import evdev
from concurrent import futures
from uchroma.util import ensure_future

            return True

        if not self._opened:
            if not self._open_input_devices():
                return False

        self._event_callbacks.append(callback)
        return True


    async def remove_callback(self, callback):
        """
        Removes a previously registered callback

        :param callback: coroutine to remove
        """
        if callback not in self._event_callbacks:
            return

        self._event_callbacks.remove(callback)

        if not self._event_callbacks:
            await self._close_input_devices()


    async def shutdown(self):
        """
        Shuts down the InputManager and disconnects any active callbacks
        """
        for callback in self._event_callbacks:

            await ensure_future(self.remove_callback(callback))