Restyled by yapf
This commit is contained in:
@@ -33,18 +33,15 @@ def client():
|
|||||||
return
|
return
|
||||||
if (args[0] == "p" or args[0] == "play") and len(args) == 2:
|
if (args[0] == "p" or args[0] == "play") and len(args) == 2:
|
||||||
track_uri_search = re.search(
|
track_uri_search = re.search(
|
||||||
r"^spotify:track:(?P<TrackID>[0-9a-zA-Z]{22})$", args[1]
|
r"^spotify:track:(?P<TrackID>[0-9a-zA-Z]{22})$", args[1])
|
||||||
)
|
|
||||||
track_url_search = re.search(
|
track_url_search = re.search(
|
||||||
r"^(https?://)?open.spotify.com/track/(?P<TrackID>[0-9a-zA-Z]{22})(\?si=.+?)?$",
|
r"^(https?://)?open.spotify.com/track/(?P<TrackID>[0-9a-zA-Z]{22})(\?si=.+?)?$",
|
||||||
args[1],
|
args[1],
|
||||||
)
|
)
|
||||||
if track_uri_search is not None or track_url_search is not None:
|
if track_uri_search is not None or track_url_search is not None:
|
||||||
track_id_str = (
|
track_id_str = (track_uri_search
|
||||||
track_uri_search
|
if track_uri_search is not None else
|
||||||
if track_uri_search is not None
|
track_url_search).group("TrackID")
|
||||||
else track_url_search
|
|
||||||
).group("TrackID")
|
|
||||||
play(track_id_str)
|
play(track_id_str)
|
||||||
wait()
|
wait()
|
||||||
if args[0] == "q" or args[0] == "quality":
|
if args[0] == "q" or args[0] == "quality":
|
||||||
@@ -64,20 +61,22 @@ def client():
|
|||||||
token = session.tokens().get("user-read-email")
|
token = session.tokens().get("user-read-email")
|
||||||
resp = requests.get(
|
resp = requests.get(
|
||||||
"https://api.spotify.com/v1/search",
|
"https://api.spotify.com/v1/search",
|
||||||
{"limit": "5", "offset": "0", "q": cmd[2:], "type": "track"},
|
{
|
||||||
|
"limit": "5",
|
||||||
|
"offset": "0",
|
||||||
|
"q": cmd[2:],
|
||||||
|
"type": "track"
|
||||||
|
},
|
||||||
headers={"Authorization": "Bearer %s" % token},
|
headers={"Authorization": "Bearer %s" % token},
|
||||||
)
|
)
|
||||||
i = 1
|
i = 1
|
||||||
tracks = resp.json()["tracks"]["items"]
|
tracks = resp.json()["tracks"]["items"]
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
print(
|
print("%d, %s | %s" % (
|
||||||
"%d, %s | %s"
|
i,
|
||||||
% (
|
track["name"],
|
||||||
i,
|
",".join([artist["name"] for artist in track["artists"]]),
|
||||||
track["name"],
|
))
|
||||||
",".join([artist["name"] for artist in track["artists"]]),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
i += 1
|
i += 1
|
||||||
position = -1
|
position = -1
|
||||||
while True:
|
while True:
|
||||||
@@ -115,8 +114,7 @@ def login():
|
|||||||
def play(track_id_str: str):
|
def play(track_id_str: str):
|
||||||
track_id = TrackId.from_base62(track_id_str)
|
track_id = TrackId.from_base62(track_id_str)
|
||||||
stream = session.content_feeder().load(
|
stream = session.content_feeder().load(
|
||||||
track_id, VorbisOnlyAudioQuality(AudioQuality.VERY_HIGH), False, None
|
track_id, VorbisOnlyAudioQuality(AudioQuality.VERY_HIGH), False, None)
|
||||||
)
|
|
||||||
ffplay = subprocess.Popen(
|
ffplay = subprocess.Popen(
|
||||||
["ffplay", "-"],
|
["ffplay", "-"],
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
@@ -132,13 +130,11 @@ def play(track_id_str: str):
|
|||||||
|
|
||||||
|
|
||||||
def splash():
|
def splash():
|
||||||
print(
|
print("=================================\n"
|
||||||
"=================================\n"
|
"| Librespot-Python Player |\n"
|
||||||
"| Librespot-Python Player |\n"
|
"| |\n"
|
||||||
"| |\n"
|
"| by kokarare1212 |\n"
|
||||||
"| by kokarare1212 |\n"
|
"=================================\n\n\n")
|
||||||
"=================================\n\n\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ class AbsChunkedInputStream(InputStream, HaltListener):
|
|||||||
_decoded_length: int = 0
|
_decoded_length: int = 0
|
||||||
|
|
||||||
def __init__(self, retry_on_chunk_error: bool):
|
def __init__(self, retry_on_chunk_error: bool):
|
||||||
self.retries: typing.Final[typing.List[int]] = [0 for _ in range(self.chunks())]
|
self.retries: typing.Final[typing.List[int]] = [
|
||||||
|
0 for _ in range(self.chunks())
|
||||||
|
]
|
||||||
self.retry_on_chunk_error = retry_on_chunk_error
|
self.retry_on_chunk_error = retry_on_chunk_error
|
||||||
|
|
||||||
def is_closed(self) -> bool:
|
def is_closed(self) -> bool:
|
||||||
@@ -107,13 +109,10 @@ class AbsChunkedInputStream(InputStream, HaltListener):
|
|||||||
self.request_chunk_from_stream(chunk)
|
self.request_chunk_from_stream(chunk)
|
||||||
self.requested_chunks()[chunk] = True
|
self.requested_chunks()[chunk] = True
|
||||||
|
|
||||||
for i in range(
|
for i in range(chunk + 1,
|
||||||
chunk + 1, min(self.chunks() - 1, chunk + self.preload_ahead) + 1
|
min(self.chunks() - 1, chunk + self.preload_ahead) + 1):
|
||||||
):
|
if (self.requested_chunks()[i]
|
||||||
if (
|
and self.retries[i] < self.preload_chunk_retries):
|
||||||
self.requested_chunks()[i]
|
|
||||||
and self.retries[i] < self.preload_chunk_retries
|
|
||||||
):
|
|
||||||
self.request_chunk_from_stream(i)
|
self.request_chunk_from_stream(i)
|
||||||
self.requested_chunks()[chunk] = True
|
self.requested_chunks()[chunk] = True
|
||||||
|
|
||||||
@@ -147,7 +146,10 @@ class AbsChunkedInputStream(InputStream, HaltListener):
|
|||||||
|
|
||||||
self.check_availability(chunk, True, True)
|
self.check_availability(chunk, True, True)
|
||||||
|
|
||||||
def read(self, b: bytearray = None, offset: int = None, length: int = None) -> int:
|
def read(self,
|
||||||
|
b: bytearray = None,
|
||||||
|
offset: int = None,
|
||||||
|
length: int = None) -> int:
|
||||||
if b is None and offset is None and length is None:
|
if b is None and offset is None and length is None:
|
||||||
return self.internal_read()
|
return self.internal_read()
|
||||||
if not (b is not None and offset is not None and length is not None):
|
if not (b is not None and offset is not None and length is not None):
|
||||||
@@ -157,9 +159,8 @@ class AbsChunkedInputStream(InputStream, HaltListener):
|
|||||||
raise IOError("Stream is closed!")
|
raise IOError("Stream is closed!")
|
||||||
|
|
||||||
if offset < 0 or length < 0 or length > len(b) - offset:
|
if offset < 0 or length < 0 or length > len(b) - offset:
|
||||||
raise IndexError(
|
raise IndexError("offset: {}, length: {}, buffer: {}".format(
|
||||||
"offset: {}, length: {}, buffer: {}".format(offset, length, len(b))
|
offset, length, len(b)))
|
||||||
)
|
|
||||||
elif length == 0:
|
elif length == 0:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -174,7 +175,8 @@ class AbsChunkedInputStream(InputStream, HaltListener):
|
|||||||
self.check_availability(chunk, True, False)
|
self.check_availability(chunk, True, False)
|
||||||
|
|
||||||
copy = min(len(self.buffer()[chunk]) - chunk_off, length - i)
|
copy = min(len(self.buffer()[chunk]) - chunk_off, length - i)
|
||||||
b[offset + 0 : copy] = self.buffer()[chunk][chunk_off : chunk_off + copy]
|
b[offset + 0:copy] = self.buffer()[chunk][chunk_off:chunk_off +
|
||||||
|
copy]
|
||||||
i += copy
|
i += copy
|
||||||
self._pos += copy
|
self._pos += copy
|
||||||
|
|
||||||
@@ -222,5 +224,4 @@ class AbsChunkedInputStream(InputStream, HaltListener):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def from_stream_error(stream_error: int):
|
def from_stream_error(stream_error: int):
|
||||||
return AbsChunkedInputStream.ChunkException(
|
return AbsChunkedInputStream.ChunkException(
|
||||||
"Failed due to stream error, code: {}".format(stream_error)
|
"Failed due to stream error, code: {}".format(stream_error))
|
||||||
)
|
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ class CdnFeedHelper:
|
|||||||
|
|
||||||
streamer = session.cdn().stream_file(file, key, url, halt_listener)
|
streamer = session.cdn().stream_file(file, key, url, halt_listener)
|
||||||
input_stream = streamer.stream()
|
input_stream = streamer.stream()
|
||||||
normalization_data = NormalizationData.NormalizationData.read(input_stream)
|
normalization_data = NormalizationData.NormalizationData.read(
|
||||||
|
input_stream)
|
||||||
if input_stream.skip(0xA7) != 0xA7:
|
if input_stream.skip(0xA7) != 0xA7:
|
||||||
raise IOError("Couldn't skip 0xa7 bytes!")
|
raise IOError("Couldn't skip 0xa7 bytes!")
|
||||||
return PlayableContentFeeder.PlayableContentFeeder.LoadedStream(
|
return PlayableContentFeeder.PlayableContentFeeder.LoadedStream(
|
||||||
@@ -48,13 +49,13 @@ class CdnFeedHelper:
|
|||||||
streamer,
|
streamer,
|
||||||
normalization_data,
|
normalization_data,
|
||||||
PlayableContentFeeder.PlayableContentFeeder.Metrics(
|
PlayableContentFeeder.PlayableContentFeeder.Metrics(
|
||||||
file.file_id, preload, -1 if preload else audio_key_time
|
file.file_id, preload, -1 if preload else audio_key_time),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_episode_external(
|
def load_episode_external(
|
||||||
session: Session, episode: Metadata.Episode, halt_listener: HaltListener
|
session: Session, episode: Metadata.Episode,
|
||||||
|
halt_listener: HaltListener
|
||||||
) -> PlayableContentFeeder.PlayableContentFeeder.LoadedStream:
|
) -> PlayableContentFeeder.PlayableContentFeeder.LoadedStream:
|
||||||
resp = session.client().head(episode.external_url)
|
resp = session.client().head(episode.external_url)
|
||||||
|
|
||||||
@@ -62,18 +63,17 @@ class CdnFeedHelper:
|
|||||||
CdnFeedHelper._LOGGER.warning("Couldn't resolve redirect!")
|
CdnFeedHelper._LOGGER.warning("Couldn't resolve redirect!")
|
||||||
|
|
||||||
url = resp.url
|
url = resp.url
|
||||||
CdnFeedHelper._LOGGER.debug(
|
CdnFeedHelper._LOGGER.debug("Fetched external url for {}: {}".format(
|
||||||
"Fetched external url for {}: {}".format(
|
Utils.Utils.bytes_to_hex(episode.gid), url))
|
||||||
Utils.Utils.bytes_to_hex(episode.gid), url
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
streamer = session.cdn().stream_external_episode(episode, url, halt_listener)
|
streamer = session.cdn().stream_external_episode(
|
||||||
|
episode, url, halt_listener)
|
||||||
return PlayableContentFeeder.PlayableContentFeeder.LoadedStream(
|
return PlayableContentFeeder.PlayableContentFeeder.LoadedStream(
|
||||||
episode,
|
episode,
|
||||||
streamer,
|
streamer,
|
||||||
None,
|
None,
|
||||||
PlayableContentFeeder.PlayableContentFeeder.Metrics(None, False, -1),
|
PlayableContentFeeder.PlayableContentFeeder.Metrics(
|
||||||
|
None, False, -1),
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -102,6 +102,5 @@ class CdnFeedHelper:
|
|||||||
streamer,
|
streamer,
|
||||||
normalization_data,
|
normalization_data,
|
||||||
PlayableContentFeeder.PlayableContentFeeder.Metrics(
|
PlayableContentFeeder.PlayableContentFeeder.Metrics(
|
||||||
file.file_id, False, audio_key_time
|
file.file_id, False, audio_key_time),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ class CdnManager:
|
|||||||
def get_head(self, file_id: bytes):
|
def get_head(self, file_id: bytes):
|
||||||
resp = self._session.client().get(
|
resp = self._session.client().get(
|
||||||
self._session.get_user_attribute(
|
self._session.get_user_attribute(
|
||||||
"head-files-url", "https://heads-fa.spotify.com/head/{file_id}"
|
"head-files-url",
|
||||||
).replace("{file_id}", Utils.bytes_to_hex(file_id))
|
"https://heads-fa.spotify.com/head/{file_id}").replace(
|
||||||
)
|
"{file_id}", Utils.bytes_to_hex(file_id)))
|
||||||
|
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
raise IOError("{}".format(resp.status_code))
|
raise IOError("{}".format(resp.status_code))
|
||||||
@@ -50,9 +50,9 @@ class CdnManager:
|
|||||||
|
|
||||||
return body
|
return body
|
||||||
|
|
||||||
def stream_external_episode(
|
def stream_external_episode(self, episode: Metadata.Episode,
|
||||||
self, episode: Metadata.Episode, external_url: str, halt_listener: HaltListener
|
external_url: str,
|
||||||
):
|
halt_listener: HaltListener):
|
||||||
return CdnManager.Streamer(
|
return CdnManager.Streamer(
|
||||||
self._session,
|
self._session,
|
||||||
StreamId(episode),
|
StreamId(episode),
|
||||||
@@ -84,8 +84,7 @@ class CdnManager:
|
|||||||
resp = self._session.api().send(
|
resp = self._session.api().send(
|
||||||
"GET",
|
"GET",
|
||||||
"/storage-resolve/files/audio/interactive/{}".format(
|
"/storage-resolve/files/audio/interactive/{}".format(
|
||||||
Utils.bytes_to_hex(file_id)
|
Utils.bytes_to_hex(file_id)),
|
||||||
),
|
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -101,13 +100,11 @@ class CdnManager:
|
|||||||
proto.ParseFromString(body)
|
proto.ParseFromString(body)
|
||||||
if proto.result == StorageResolve.StorageResolveResponse.Result.CDN:
|
if proto.result == StorageResolve.StorageResolveResponse.Result.CDN:
|
||||||
url = random.choice(proto.cdnurl)
|
url = random.choice(proto.cdnurl)
|
||||||
self._LOGGER.debug(
|
self._LOGGER.debug("Fetched CDN url for {}: {}".format(
|
||||||
"Fetched CDN url for {}: {}".format(Utils.bytes_to_hex(file_id), url)
|
Utils.bytes_to_hex(file_id), url))
|
||||||
)
|
|
||||||
return url
|
return url
|
||||||
raise CdnManager.CdnException(
|
raise CdnManager.CdnException(
|
||||||
"Could not retrieve CDN url! result: {}".format(proto.result)
|
"Could not retrieve CDN url! result: {}".format(proto.result))
|
||||||
)
|
|
||||||
|
|
||||||
class CdnException(Exception):
|
class CdnException(Exception):
|
||||||
pass
|
pass
|
||||||
@@ -167,8 +164,7 @@ class CdnManager:
|
|||||||
if expire_at is None:
|
if expire_at is None:
|
||||||
self._expiration = -1
|
self._expiration = -1
|
||||||
self._cdnManager._LOGGER.warning(
|
self._cdnManager._LOGGER.warning(
|
||||||
"Invalid __token__ in CDN url: {}".format(url)
|
"Invalid __token__ in CDN url: {}".format(url))
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
self._expiration = expire_at * 1000
|
self._expiration = expire_at * 1000
|
||||||
@@ -178,10 +174,8 @@ class CdnManager:
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
self._expiration = -1
|
self._expiration = -1
|
||||||
self._cdnManager._LOGGER.warning(
|
self._cdnManager._LOGGER.warning(
|
||||||
"Couldn't extract expiration, invalid parameter in CDN url: ".format(
|
"Couldn't extract expiration, invalid parameter in CDN url: "
|
||||||
url
|
.format(url))
|
||||||
)
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
self._expiration = int(token_url.query[:i]) * 1000
|
self._expiration = int(token_url.query[:i]) * 1000
|
||||||
@@ -190,8 +184,8 @@ class CdnManager:
|
|||||||
self._expiration = -1
|
self._expiration = -1
|
||||||
|
|
||||||
class Streamer(
|
class Streamer(
|
||||||
GeneralAudioStream.GeneralAudioStream,
|
GeneralAudioStream.GeneralAudioStream,
|
||||||
GeneralWritableStream.GeneralWritableStream,
|
GeneralWritableStream.GeneralWritableStream,
|
||||||
):
|
):
|
||||||
_session: Session = None
|
_session: Session = None
|
||||||
_streamId: StreamId = None
|
_streamId: StreamId = None
|
||||||
@@ -224,38 +218,39 @@ class CdnManager:
|
|||||||
self._cdnUrl = cdn_url
|
self._cdnUrl = cdn_url
|
||||||
self._haltListener = halt_listener
|
self._haltListener = halt_listener
|
||||||
|
|
||||||
resp = self.request(range_start=0, range_end=ChannelManager.CHUNK_SIZE - 1)
|
resp = self.request(range_start=0,
|
||||||
|
range_end=ChannelManager.CHUNK_SIZE - 1)
|
||||||
content_range = resp._headers.get("Content-Range")
|
content_range = resp._headers.get("Content-Range")
|
||||||
if content_range is None:
|
if content_range is None:
|
||||||
raise IOError("Missing Content-Range header!")
|
raise IOError("Missing Content-Range header!")
|
||||||
|
|
||||||
split = Utils.split(content_range, "/")
|
split = Utils.split(content_range, "/")
|
||||||
self._size = int(split[1])
|
self._size = int(split[1])
|
||||||
self._chunks = int(math.ceil(self._size / ChannelManager.CHUNK_SIZE))
|
self._chunks = int(
|
||||||
|
math.ceil(self._size / ChannelManager.CHUNK_SIZE))
|
||||||
|
|
||||||
first_chunk = resp._buffer
|
first_chunk = resp._buffer
|
||||||
|
|
||||||
self._available = [False for _ in range(self._chunks)]
|
self._available = [False for _ in range(self._chunks)]
|
||||||
self._requested = [False for _ in range(self._chunks)]
|
self._requested = [False for _ in range(self._chunks)]
|
||||||
self._buffer = [bytearray() for _ in range(self._chunks)]
|
self._buffer = [bytearray() for _ in range(self._chunks)]
|
||||||
self._internalStream = CdnManager.Streamer.InternalStream(self, False)
|
self._internalStream = CdnManager.Streamer.InternalStream(
|
||||||
|
self, False)
|
||||||
|
|
||||||
self._requested[0] = True
|
self._requested[0] = True
|
||||||
self.write_chunk(first_chunk, 0, False)
|
self.write_chunk(first_chunk, 0, False)
|
||||||
|
|
||||||
def write_chunk(self, chunk: bytes, chunk_index: int, cached: bool) -> None:
|
def write_chunk(self, chunk: bytes, chunk_index: int,
|
||||||
|
cached: bool) -> None:
|
||||||
if self._internalStream.is_closed():
|
if self._internalStream.is_closed():
|
||||||
return
|
return
|
||||||
|
|
||||||
self._session._LOGGER.debug(
|
self._session._LOGGER.debug(
|
||||||
"Chunk {}/{} completed, cached: {}, stream: {}".format(
|
"Chunk {}/{} completed, cached: {}, stream: {}".format(
|
||||||
chunk_index + 1, self._chunks, cached, self.describe()
|
chunk_index + 1, self._chunks, cached, self.describe()))
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
self._buffer[chunk_index] = self._audioDecrypt.decrypt_chunk(
|
self._buffer[chunk_index] = self._audioDecrypt.decrypt_chunk(
|
||||||
chunk_index, chunk
|
chunk_index, chunk)
|
||||||
)
|
|
||||||
self._internalStream.notify_chunk_available(chunk_index)
|
self._internalStream.notify_chunk_available(chunk_index)
|
||||||
|
|
||||||
def stream(self) -> AbsChunkedInputStream:
|
def stream(self) -> AbsChunkedInputStream:
|
||||||
@@ -266,7 +261,8 @@ class CdnManager:
|
|||||||
|
|
||||||
def describe(self) -> str:
|
def describe(self) -> str:
|
||||||
if self._streamId.is_episode():
|
if self._streamId.is_episode():
|
||||||
return "episode_gid: {}".format(self._streamId.get_episode_gid())
|
return "episode_gid: {}".format(
|
||||||
|
self._streamId.get_episode_gid())
|
||||||
return "file_id: {}".format(self._streamId.get_file_id())
|
return "file_id: {}".format(self._streamId.get_file_id())
|
||||||
|
|
||||||
def decrypt_time_ms(self) -> int:
|
def decrypt_time_ms(self) -> int:
|
||||||
@@ -276,9 +272,10 @@ class CdnManager:
|
|||||||
resp = self.request(index)
|
resp = self.request(index)
|
||||||
self.write_chunk(resp._buffer, index, False)
|
self.write_chunk(resp._buffer, index, False)
|
||||||
|
|
||||||
def request(
|
def request(self,
|
||||||
self, chunk: int = None, range_start: int = None, range_end: int = None
|
chunk: int = None,
|
||||||
) -> CdnManager.InternalResponse:
|
range_start: int = None,
|
||||||
|
range_end: int = None) -> CdnManager.InternalResponse:
|
||||||
if chunk is None and range_start is None and range_end is None:
|
if chunk is None and range_start is None and range_end is None:
|
||||||
raise TypeError()
|
raise TypeError()
|
||||||
|
|
||||||
@@ -288,7 +285,9 @@ class CdnManager:
|
|||||||
|
|
||||||
resp = self._session.client().get(
|
resp = self._session.client().get(
|
||||||
self._cdnUrl._url,
|
self._cdnUrl._url,
|
||||||
headers={"Range": "bytes={}-{}".format(range_start, range_end)},
|
headers={
|
||||||
|
"Range": "bytes={}-{}".format(range_start, range_end)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
if resp.status_code != 206:
|
if resp.status_code != 206:
|
||||||
@@ -324,21 +323,16 @@ class CdnManager:
|
|||||||
|
|
||||||
def request_chunk_from_stream(self, index: int) -> None:
|
def request_chunk_from_stream(self, index: int) -> None:
|
||||||
self.streamer._executorService.submit(
|
self.streamer._executorService.submit(
|
||||||
lambda: self.streamer.request_chunk(index)
|
lambda: self.streamer.request_chunk(index))
|
||||||
)
|
|
||||||
|
|
||||||
def stream_read_halted(self, chunk: int, _time: int) -> None:
|
def stream_read_halted(self, chunk: int, _time: int) -> None:
|
||||||
if self.streamer._haltListener is not None:
|
if self.streamer._haltListener is not None:
|
||||||
self.streamer._executorService.submit(
|
self.streamer._executorService.submit(
|
||||||
lambda: self.streamer._haltListener.stream_read_halted(
|
lambda: self.streamer._haltListener.stream_read_halted(
|
||||||
chunk, _time
|
chunk, _time))
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def stream_read_resumed(self, chunk: int, _time: int) -> None:
|
def stream_read_resumed(self, chunk: int, _time: int) -> None:
|
||||||
if self.streamer._haltListener is not None:
|
if self.streamer._haltListener is not None:
|
||||||
self.streamer._executorService.submit(
|
self.streamer._executorService.submit(
|
||||||
lambda: self.streamer._haltListener.stream_read_resumed(
|
lambda: self.streamer._haltListener.
|
||||||
chunk, _time
|
stream_read_resumed(chunk, _time))
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user