Example #1
0
 def lineReceived(self, line):
     line = line.decode('utf-8')
     command_list = self._state and isinstance(self._state[0], list)
     state_list = self._state[0] if command_list else self._state
     if line.startswith(HELLO_PREFIX):
         self.mpd_version = line[len(HELLO_PREFIX):].strip()
         # default state idle, enter idle
         if self._default_idle:
             self.idle().addCallback(self._dispatch_idle_result)
     elif line.startswith(ERROR_PREFIX):
         error = line[len(ERROR_PREFIX):].strip()
         if command_list:
             state_list[0].errback(CommandError(error))
             for state in state_list[1:-1]:
                 state.errback(
                     CommandListError('An earlier command failed.'))
             state_list[-1].errback(CommandListError(error))
             del self._state[0]
             del self._command_list_results[0]
         else:
             state_list.pop(0).errback(CommandError(error))
         self._continue_idle()
     elif line == SUCCESS or (command_list and line == NEXT):
         state_list.pop(0).callback(self._rcvd_lines[:])
         self._rcvd_lines = []
         if command_list and line == SUCCESS:
             del self._state[0]
         self._continue_idle()
     else:
         self._rcvd_lines.append(line)
Example #2
0
    async def _execute_binary(self, command, args):
        # Fun fact: By fetching data in lockstep, this is a bit less efficient
        # than it could be (which would be "after having received the first
        # chunk, guess that the other chunks are of equal size and request at
        # several multiples concurrently, ensuring the TCP connection can stay
        # full), but at the other hand it leaves the command queue empty so
        # that more time critical commands can be executed right away

        data = None
        args = list(args)
        assert len(args) == 1
        args.append(0)
        final_metadata = None
        while True:
            partial_result = BinaryCommandResult()
            await self.__command_queue.put(partial_result)
            self._end_idle()
            self._write_command(command, args)
            metadata = await partial_result
            chunk = metadata.pop('binary', None)

            if final_metadata is None:
                data = chunk
                final_metadata = metadata
                if not data:
                    break
                try:
                    size = int(final_metadata['size'])
                except KeyError:
                    size = len(chunk)
                except ValueError:
                    raise CommandError(
                        "Size data unsuitable for binary transfer")
            else:
                if metadata != final_metadata:
                    raise CommandError(
                        "Metadata of binary data changed during transfer")
                if chunk is None:
                    raise CommandError(
                        "Binary field vanished changed during transfer")
                data += chunk
            args[-1] = len(data)
            if len(data) > size:
                raise CommandListError("Binary data announced size exceeded")
            elif len(data) == size:
                break

        if data is not None:
            final_metadata['binary'] = data

        final_metadata.pop('size', None)

        return final_metadata
Example #3
0
 def noidle(self):
     if not self._idle:
         raise CommandError('Not in idle state')
     # delete first pending deferred, idle returns nothing when
     # noidle gets called
     self._state.pop(0)
     self._idle = False
     return self._execute('noidle', [], self._parse_list)
Example #4
0
 async def _read_line(self):
     line = await self.__readline()
     if not line.endswith("\n"):
         raise ConnectionError("Connection lost while reading line")
     line = line.rstrip("\n")
     if line.startswith(ERROR_PREFIX):
         error = line[len(ERROR_PREFIX):].strip()
         raise CommandError(error)
     if line == SUCCESS:
         return None
     return line
Example #5
0
 def idle(self):
     if self._idle:
         raise CommandError('Already in idle state')
     self._idle = True
     return self._execute('idle', [], self._parse_list)
Example #6
0
 def idle(self):
     if self._idle:
         raise CommandError("Already in idle state")
     self._idle = True
     return self._execute("idle", [], self._parse_list)