TonieToolbox 0.6.0rc3__py3-none-any.whl → 0.6.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -216,16 +216,21 @@ class TeddyCloudClient:
216
216
  response = self._make_request('GET', '/api/fileIndex')
217
217
  return response.json()
218
218
 
219
- def get_file_index_v2(self) -> dict:
219
+ def get_file_index_v2(self,file_path: str = None, special: str = None) -> dict:
220
220
  """
221
221
  Get version 2 file index data from the TeddyCloud server.
222
222
 
223
223
  Returns:
224
224
  dict: JSON response containing version 2 file index data
225
225
  """
226
- response = self._make_request('GET', '/api/fileIndexV2')
226
+ params = {}
227
+ if file_path:
228
+ params['file_path'] = file_path
229
+ if special:
230
+ params['special'] = special
231
+ response = self._make_request('GET', '/api/fileIndexV2', params=params)
227
232
  return response.json()
228
-
233
+
229
234
  def get_tonieboxes_json(self) -> dict:
230
235
  """
231
236
  Get Tonieboxes JSON data from the TeddyCloud server.
@@ -333,7 +338,77 @@ class TeddyCloudClient:
333
338
  'status_code': response.status_code,
334
339
  'message': response.text
335
340
  }
336
-
341
+
342
+ def assign_tag_path(self, lib_path: str, tag_id: str, overlay: str = None, nocloud: bool = True, live: bool = False) -> dict:
343
+ """
344
+ Assign a new source path to a tag on the TeddyCloud server.
345
+
346
+ Args:
347
+ lib_path (str): Library path to assign to the tag (source path)
348
+ tag_id (str): Tag ID to assign the path to
349
+ overlay (str | None): Settings overlay ID (optional)
350
+ Returns:
351
+ dict: Response information including success status and message
352
+ """
353
+ params = {}
354
+ form_data = {}
355
+ if not lib_path.startswith('lib://'):
356
+ raise ValueError("Library path must start with 'lib://'")
357
+ api_tag_id = self._reverse_byte_order(tag_id)
358
+ if overlay:
359
+ params['overlay'] = overlay
360
+ if lib_path:
361
+ form_data['source'] = lib_path
362
+ if nocloud:
363
+ form_data['nocloud'] = 'true'
364
+ else:
365
+ form_data['nocloud'] = 'false'
366
+ if live:
367
+ form_data['live'] = 'true'
368
+ else:
369
+ form_data['live'] = 'false'
370
+ logger.debug(f"Assigning tag path '{lib_path}' to tag ID '{tag_id}' at endpoint {api_tag_id} with overlay '{overlay}'")
371
+
372
+ try:
373
+ response = self._make_request('POST', f'/content/json/set/{api_tag_id}', params=params, data=form_data)
374
+ logger.debug(f"Tag assignment request URL: {response.url}")
375
+ logger.debug(f"Tag assignment response status: {response.status_code}")
376
+ logger.debug(f"Tag assignment response text: {response.text}")
377
+
378
+ return {
379
+ 'success': True,
380
+ 'status_code': response.status_code,
381
+ 'message': response.text,
382
+ 'url': response.url
383
+ }
384
+ except Exception as e:
385
+ logger.error(f"Failed to assign tag path: {e}")
386
+ return {
387
+ 'success': False,
388
+ 'status_code': getattr(e.response, 'status_code', None) if hasattr(e, 'response') else None,
389
+ 'message': str(e),
390
+ 'url': None
391
+ }
392
+
393
+ def _reverse_byte_order(self, hex_string: str) -> str:
394
+ """
395
+ Reverse the byte order of a hex string (little-endian conversion).
396
+
397
+ Args:
398
+ hex_string (str): Hexadecimal string to reverse (e.g., "E0:04:03:50:11:AA:7E:81")
399
+
400
+ Returns:
401
+ str: Reversed hexadecimal lower string without colons (e.g., "817e11a50304e0")
402
+ """
403
+ if hex_string.endswith('04e0'):
404
+ logger.debug("Hex string ends with '04e0', returning as is")
405
+ return hex_string
406
+ else:
407
+ logger.debug(f"Reversing byte order for hex string: {hex_string}")
408
+ hex_without_colons = hex_string.replace(":", "")
409
+ byte_pairs = [hex_without_colons[i:i+2] for i in range(0, len(hex_without_colons), 2)]
410
+ return ''.join(reversed(byte_pairs)).lower()
411
+
337
412
  # ------------- Custom API Methods -------------
338
413
 
339
414
  def _get_paths_cache_file(self) -> str:
@@ -5,8 +5,11 @@ Functions for analyzing Tonie files
5
5
 
6
6
  import datetime
7
7
  import hashlib
8
- import struct
8
+ import math
9
9
  import os
10
+ import re
11
+ import struct
12
+ import tempfile
10
13
  from . import tonie_header_pb2
11
14
  from .ogg_page import OggPage
12
15
  from .logger import get_logger
@@ -58,6 +61,33 @@ def granule_to_time_string(granule: int, sample_rate: int = 1) -> str:
58
61
  return "{:02d}:{:02d}:{:02d}.{:02d}".format(hours, minutes, seconds, fraction)
59
62
 
60
63
 
64
+ def extract_bitrate_from_encoder_options(opus_comments: dict) -> int:
65
+ """
66
+ Extract bitrate from Opus encoder_options comment.
67
+
68
+ Args:
69
+ opus_comments (dict): Dictionary of Opus comments
70
+
71
+ Returns:
72
+ int: Detected bitrate in kbps, or None if not found
73
+ """
74
+ if not opus_comments or "encoder_options" not in opus_comments:
75
+ return None
76
+
77
+ encoder_options = opus_comments["encoder_options"]
78
+ logger.debug("Found encoder_options: %s", encoder_options)
79
+
80
+ # Parse encoder options like: "--bitrate 96 --vbr" or "--bitrate=96"
81
+ bitrate_match = re.search(r'--bitrate[=\s]+(\d+)', encoder_options)
82
+ if bitrate_match:
83
+ bitrate = int(bitrate_match.group(1))
84
+ logger.debug("Detected source bitrate: %d kbps", bitrate)
85
+ return bitrate
86
+
87
+ logger.debug("No bitrate found in encoder_options")
88
+ return None
89
+
90
+
61
91
  def get_header_info(in_file) -> tuple:
62
92
  """
63
93
  Get header information from a Tonie file.
@@ -414,6 +444,210 @@ def split_to_opus_files(filename: str, output: str = None) -> None:
414
444
  logger.info("Successfully split Tonie file into %d individual tracks", len(tonie_header.chapterPages))
415
445
 
416
446
 
447
+ def extract_to_mp3_files(filename: str, output: str = None, bitrate: int = 128, ffmpeg_binary: str = None, auto_download: bool = False) -> None:
448
+ """
449
+ Extract a Tonie file to individual MP3 files.
450
+
451
+ Args:
452
+ filename (str): Path to the Tonie file
453
+ output (str | None): Output directory path (optional)
454
+ bitrate (int): Bitrate for MP3 encoding in kbps
455
+ ffmpeg_binary (str | None): Path to ffmpeg binary
456
+ auto_download (bool): Whether to automatically download dependencies if not found
457
+ """
458
+ logger.info("Extracting Tonie file to individual MP3 tracks: %s", filename)
459
+
460
+ with open(filename, "rb") as in_file:
461
+ # Get header info including Opus comments to detect source bitrate
462
+ header_size, tonie_header, file_size, audio_size, sha1sum, \
463
+ opus_head_found, opus_version, channel_count, sample_rate, bitstream_serial_no, \
464
+ opus_comments = get_header_info(in_file)
465
+
466
+ # Try to detect source bitrate from encoder options
467
+ detected_bitrate = extract_bitrate_from_encoder_options(opus_comments)
468
+ if detected_bitrate and bitrate == 128: # Only use detected if bitrate wasn't explicitly set
469
+ bitrate = detected_bitrate
470
+ logger.info("Using detected source bitrate: %d kbps", bitrate)
471
+ elif detected_bitrate:
472
+ logger.info("Detected source bitrate: %d kbps, but using specified bitrate: %d kbps",
473
+ detected_bitrate, bitrate)
474
+ else:
475
+ logger.info("Using specified bitrate: %d kbps", bitrate)
476
+
477
+ # Reset file position to start of audio data
478
+ in_file.seek(4 + header_size)
479
+
480
+ abs_path = os.path.abspath(filename)
481
+ if output:
482
+ if not os.path.exists(output):
483
+ logger.debug("Creating output directory: %s", output)
484
+ os.makedirs(output)
485
+ path = output
486
+ else:
487
+ path = os.path.dirname(abs_path)
488
+
489
+ logger.debug("Output path: %s", path)
490
+
491
+ name = os.path.basename(abs_path)
492
+ pos = name.rfind('.')
493
+ if pos == -1:
494
+ name = name + ".mp3"
495
+ else:
496
+ name = name[:pos] + ".mp3"
497
+
498
+ filename_template = "{{:02d}}_{}".format(name)
499
+ out_path = "{}{}".format(path, os.path.sep)
500
+ logger.debug("Output filename template: %s", out_path + filename_template)
501
+
502
+ found = OggPage.seek_to_page_header(in_file)
503
+ if not found:
504
+ logger.error("First OGG page not found")
505
+ raise RuntimeError("First ogg page not found")
506
+
507
+ first_page = OggPage(in_file)
508
+ logger.debug("Read first OGG page")
509
+
510
+ found = OggPage.seek_to_page_header(in_file)
511
+ if not found:
512
+ logger.error("Second OGG page not found")
513
+ raise RuntimeError("Second ogg page not found")
514
+
515
+ second_page = OggPage(in_file)
516
+ logger.debug("Read second OGG page")
517
+
518
+ found = OggPage.seek_to_page_header(in_file)
519
+ page = OggPage(in_file)
520
+ logger.debug("Read third OGG page")
521
+
522
+ from .audio_conversion import convert_opus_to_mp3
523
+
524
+ pad_len = math.ceil(math.log(len(tonie_header.chapterPages) + 1, 10))
525
+ format_string = "[{{:0{}d}}/{:0{}d}] {{}}".format(pad_len, len(tonie_header.chapterPages), pad_len)
526
+
527
+ for i in range(0, len(tonie_header.chapterPages)):
528
+ if (i + 1) < len(tonie_header.chapterPages):
529
+ end_page = tonie_header.chapterPages[i + 1]
530
+ else:
531
+ end_page = 0
532
+
533
+ granule = 0
534
+ output_filename = filename_template.format(i + 1)
535
+ print(format_string.format(i + 1, output_filename))
536
+ logger.info("Creating track %d: %s (end page: %d)", i + 1, out_path + output_filename, end_page)
537
+
538
+ # Create temporary Opus data in memory
539
+ with tempfile.NamedTemporaryFile() as temp_opus:
540
+ # Write Opus header pages and audio data
541
+ first_page.write_page(temp_opus)
542
+ second_page.write_page(temp_opus)
543
+ page_count = 0
544
+
545
+ while found and ((page.page_no < end_page) or (end_page == 0)):
546
+ page.correct_values(granule)
547
+ granule = page.granule_position
548
+ page.write_page(temp_opus)
549
+ page_count += 1
550
+
551
+ found = OggPage.seek_to_page_header(in_file)
552
+ if found:
553
+ page = OggPage(in_file)
554
+
555
+ logger.debug("Track %d: Collected %d pages, final granule position: %d",
556
+ i + 1, page_count, granule)
557
+
558
+ # Convert Opus data to MP3
559
+ temp_opus.seek(0)
560
+ opus_data = temp_opus.read()
561
+ mp3_output_path = "{}{}".format(out_path, output_filename)
562
+
563
+ success = convert_opus_to_mp3(
564
+ opus_data=opus_data,
565
+ output_path=mp3_output_path,
566
+ ffmpeg_binary=ffmpeg_binary,
567
+ bitrate=bitrate,
568
+ auto_download=auto_download
569
+ )
570
+
571
+ if success:
572
+ logger.debug("Successfully converted track %d to MP3", i + 1)
573
+ else:
574
+ logger.error("Failed to convert track %d to MP3", i + 1)
575
+
576
+ logger.info("Successfully extracted Tonie file to %d individual MP3 tracks", len(tonie_header.chapterPages))
577
+
578
+
579
+ def extract_full_audio_to_mp3(filename: str, output_path: str = None, bitrate: int = 128, ffmpeg_binary: str = None, auto_download: bool = False) -> bool:
580
+ """
581
+ Extract the full audio content from a Tonie file to a single MP3 file.
582
+
583
+ Args:
584
+ filename (str): Path to the Tonie file
585
+ output_path (str | None): Output MP3 file path (optional, will be generated if None)
586
+ bitrate (int): Bitrate for MP3 encoding in kbps
587
+ ffmpeg_binary (str | None): Path to ffmpeg binary
588
+ auto_download (bool): Whether to automatically download dependencies if not found Returns:
589
+ bool: True if extraction was successful, False otherwise
590
+ """
591
+ logger.info("Extracting full audio from Tonie file to MP3: %s", filename)
592
+
593
+ if output_path is None:
594
+ # Generate output path based on input filename
595
+ abs_path = os.path.abspath(filename)
596
+ name = os.path.basename(abs_path)
597
+ pos = name.rfind('.')
598
+ if pos == -1:
599
+ output_path = name + ".mp3"
600
+ else:
601
+ output_path = name[:pos] + ".mp3"
602
+ output_path = os.path.join(os.path.dirname(abs_path), output_path)
603
+
604
+ logger.debug("Output MP3 file: %s", output_path)
605
+
606
+ try:
607
+ with open(filename, "rb") as in_file:
608
+ # Get header info including Opus comments to detect source bitrate
609
+ header_size, tonie_header, file_size, audio_size, sha1sum, \
610
+ opus_head_found, opus_version, channel_count, sample_rate, bitstream_serial_no, \
611
+ opus_comments = get_header_info(in_file)
612
+
613
+ # Try to detect source bitrate from encoder options
614
+ detected_bitrate = extract_bitrate_from_encoder_options(opus_comments)
615
+ if detected_bitrate and bitrate == 128: # Only use detected if bitrate wasn't explicitly set
616
+ bitrate = detected_bitrate
617
+ logger.info("Using detected source bitrate: %d kbps", bitrate)
618
+ elif detected_bitrate:
619
+ logger.info("Detected source bitrate: %d kbps, but using specified bitrate: %d kbps",
620
+ detected_bitrate, bitrate)
621
+ else:
622
+ logger.info("Using specified bitrate: %d kbps", bitrate)
623
+
624
+ # Reset file position to start of audio data and read all remaining Opus data
625
+ in_file.seek(4 + header_size)
626
+ opus_data = in_file.read()
627
+ logger.debug("Read %d bytes of Opus audio data", len(opus_data))
628
+
629
+ from .audio_conversion import convert_opus_to_mp3
630
+
631
+ success = convert_opus_to_mp3(
632
+ opus_data=opus_data,
633
+ output_path=output_path,
634
+ ffmpeg_binary=ffmpeg_binary,
635
+ bitrate=bitrate,
636
+ auto_download=auto_download
637
+ )
638
+
639
+ if success:
640
+ logger.info("Successfully extracted full audio to MP3: %s", output_path)
641
+ return True
642
+ else:
643
+ logger.error("Failed to extract audio to MP3")
644
+ return False
645
+
646
+ except Exception as e:
647
+ logger.error("Error extracting Tonie file to MP3: %s", str(e))
648
+ return False
649
+
650
+
417
651
  def compare_taf_files(file1: str, file2: str, detailed: bool = False) -> bool:
418
652
  """
419
653
  Compare two .taf files for debugging purposes.
@@ -180,20 +180,23 @@ class ToniesJsonHandlerv1:
180
180
  """
181
181
  logger.trace("Entering add_entry_from_taf() with taf_file=%s, input_files=%s, artwork_url=%s",
182
182
  taf_file, input_files, artwork_url)
183
-
184
183
  if not self.is_loaded:
185
184
  logger.error("Cannot add entry: tonies.custom.json not loaded")
186
185
  return False
187
186
 
188
187
  try:
189
- logger.info("Adding entry for %s to tonies.custom.json", taf_file)
188
+ logger.info("Adding entry for %s to tonies.custom.json", taf_file)
190
189
  logger.debug("Extracting metadata from input files")
191
190
  metadata = self._extract_metadata_from_files(input_files)
192
191
  logger.debug("Extracted metadata: %s", metadata)
192
+ logger.debug("Extracting hash and timestamp from TAF file header")
193
+ from .tonie_analysis import get_header_info
193
194
  with open(taf_file, 'rb') as f:
194
- taf_hash = hashlib.sha1(f.read()).hexdigest().upper()
195
-
196
- timestamp = str(int(time.time()))
195
+ header_size, tonie_header, file_size, audio_size, sha1, opus_head_found, \
196
+ opus_version, channel_count, sample_rate, bitstream_serial_no, opus_comments = get_header_info(f)
197
+ taf_hash = tonie_header.dataHash.hex().upper()
198
+ timestamp = str(bitstream_serial_no)
199
+ logger.debug("Extracted hash: %s, timestamp: %s", taf_hash, timestamp)
197
200
  series = metadata.get('albumartist', metadata.get('artist', 'Unknown Artist'))
198
201
  episodes = metadata.get('album', os.path.splitext(os.path.basename(taf_file))[0])
199
202
  copyright = metadata.get('copyright', '')
@@ -829,15 +832,20 @@ class ToniesJsonHandlerv2:
829
832
 
830
833
  try:
831
834
  logger.info("Adding entry for %s to tonies.custom.json", taf_file)
832
-
833
835
  logger.debug("Extracting metadata from input files")
834
836
  metadata = self._extract_metadata_from_files(input_files)
835
837
  logger.debug("Extracted metadata: %s", metadata)
838
+
839
+ logger.debug("Extracting hash and timestamp from TAF file header")
840
+ from .tonie_analysis import get_header_info
836
841
  with open(taf_file, 'rb') as f:
837
- taf_hash = hashlib.sha1(f.read()).hexdigest()
842
+ header_size, tonie_header, file_size, audio_size, sha1, opus_head_found, \
843
+ opus_version, channel_count, sample_rate, bitstream_serial_no, opus_comments = get_header_info(f)
844
+ taf_hash = tonie_header.dataHash.hex().upper()
845
+ timestamp = bitstream_serial_no
846
+ logger.debug("Extracted hash: %s, timestamp: %s", taf_hash, timestamp)
838
847
 
839
848
  taf_size = os.path.getsize(taf_file)
840
- timestamp = int(time.time())
841
849
  series = metadata.get('albumartist', metadata.get('artist', 'Unknown Artist'))
842
850
  episode = metadata.get('album', os.path.splitext(os.path.basename(taf_file))[0])
843
851
  track_desc = metadata.get('track_descriptions', [])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TonieToolbox
3
- Version: 0.6.0rc3
3
+ Version: 0.6.4
4
4
  Summary: Convert audio files to Toniebox compatible format (.TAF) and interact with TeddyCloud.
5
5
  Home-page: https://github.com/Quentendo64/TonieToolbox
6
6
  Author: Quentendo64
@@ -14,6 +14,12 @@ Classifier: Programming Language :: Python :: 3.7
14
14
  Classifier: Programming Language :: Python :: 3.8
15
15
  Classifier: Programming Language :: Python :: 3.9
16
16
  Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
17
23
  Classifier: Operating System :: OS Independent
18
24
  Classifier: Topic :: Multimedia :: Sound/Audio :: Conversion
19
25
  Requires-Python: >=3.6
@@ -0,0 +1,32 @@
1
+ TonieToolbox/__init__.py,sha256=Y6sRh2CRrkuQERkpNF3CX7sIBcAxO27wfumaBeMPYfU,115
2
+ TonieToolbox/__main__.py,sha256=yYRY8uuBQ2fYbsn_r9e-Xsjq1weSyjGwx3hyD3MQksM,52818
3
+ TonieToolbox/artwork.py,sha256=BhAjLWqzui8zUOU9z9P4H3zbCCTOB94aT0MPlqEvZoY,5605
4
+ TonieToolbox/audio_conversion.py,sha256=-MD_np11KoJC19H7cbYA45HcEmQxY4gkFEgo-NrtfHo,20459
5
+ TonieToolbox/constants.py,sha256=nTKDBy55PTv6Tazda3rsZZcckcm3AZOyWXa1LDuTuEk,33989
6
+ TonieToolbox/dependency_manager.py,sha256=hmEWVDuBoC8nkd7U_quSUnzYVZKRWyR80yz2963QKEo,51951
7
+ TonieToolbox/filename_generator.py,sha256=NJrRxv0sm_9G5ZDp1QG39mktgJnz5yGC8HUs7NhLYFg,5293
8
+ TonieToolbox/integration.py,sha256=mTCZHej925AXeZa2FjWtv-BjWSsRolMHOo_6qjdSn8M,5249
9
+ TonieToolbox/integration_kde.py,sha256=Yz5n0g6_OcwsJwcOJlvVV5axi5X6Bv1RwP2cGxImQDo,28320
10
+ TonieToolbox/integration_macos.py,sha256=YxK7gIqiy1QTp7EM1M1OPC-mgb3gaIoI6Xfu3eUAyX0,27311
11
+ TonieToolbox/integration_ubuntu.py,sha256=_Da2s7CmuP7kts0W-yyt4odZA8jr14d8iisVF_ipLDA,52
12
+ TonieToolbox/integration_windows.py,sha256=ZaZmU7OeX3c3LJRHfPW_ZAs0HAxT3DTuPc9HW_qtBNw,24234
13
+ TonieToolbox/logger.py,sha256=ppAnOJAKNwwbt5q3NdF2WHgHemZjP0QWRaUx8UrkQK8,3139
14
+ TonieToolbox/media_tags.py,sha256=Qe47lAZBdX5s76n9KyG-iToTI3xD4pJB3CUPLCQu7Bk,25297
15
+ TonieToolbox/ogg_page.py,sha256=CpL3mHoRsfHBBrT2r4x5p3LBPgHfYQxb_WQsCZq6SI0,22341
16
+ TonieToolbox/opus_packet.py,sha256=skKzr5sVpL7L77JisqqGL4Kz86acOGDzwbFRqRL2oSM,8017
17
+ TonieToolbox/player.py,sha256=-8EhEP1AdogThUWFIRgR0UPEDttv0WPBrqQ9hyXuX_8,25279
18
+ TonieToolbox/recursive_processor.py,sha256=kHinFtj2wU8HGCTEJRClsdztcFP0r1ep6yoWDjI7wjQ,14911
19
+ TonieToolbox/tags.py,sha256=usNcZxMEAMP7vEfeNOtg70YBJpHiWuHb_XKCyEafsYc,2702
20
+ TonieToolbox/teddycloud.py,sha256=kbyPsB0RCoeqWkrr646S8pGMxabgcDqUJQFjltnS_mQ,21654
21
+ TonieToolbox/tonie_analysis.py,sha256=LevpG_WO_BJqpMyz6W8nu5LWyXuPpdlnrDJMqoBZ6kM,40677
22
+ TonieToolbox/tonie_file.py,sha256=z7yRmK0ujZ6SjF78-xJImGmQ2bS-Q7b-6d2ryYJnmwA,21769
23
+ TonieToolbox/tonie_header.proto,sha256=WaWfwO4VrwGtscK2ujfDRKtpeBpaVPoZhI8iMmR-C0U,202
24
+ TonieToolbox/tonie_header_pb2.py,sha256=s5bp4ULTEekgq6T61z9fDkRavyPM-3eREs20f_Pxxe8,3665
25
+ TonieToolbox/tonies_json.py,sha256=EULEKA8qYmL5QTLC9jds1o9iiCjJGWZQv4gwrvajkkg,61628
26
+ TonieToolbox/version_handler.py,sha256=Q-i5_0r5lX3dlwDLI2lMAx4X10UZGN2rvMcntmyuiT4,9862
27
+ tonietoolbox-0.6.4.dist-info/licenses/LICENSE.md,sha256=rGoga9ZAgNco9fBapVFpWf6ri7HOBp1KRnt1uIruXMk,35190
28
+ tonietoolbox-0.6.4.dist-info/METADATA,sha256=wQo-2RgFzIx0TF85GH7qDWZW_dzV0k0ur5JS5wKIzhA,29390
29
+ tonietoolbox-0.6.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ tonietoolbox-0.6.4.dist-info/entry_points.txt,sha256=oqpeyBxel7aScg35Xr4gZKnf486S5KW9okqeBwyJxxc,60
31
+ tonietoolbox-0.6.4.dist-info/top_level.txt,sha256=Wkkm-2p7I3ENfS7ZbYtYUB2g-xwHrXVlERHfonsOPuE,13
32
+ tonietoolbox-0.6.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.7.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,30 +0,0 @@
1
- TonieToolbox/__init__.py,sha256=SnLbjapelQMeop1rcfF4RL0Kmq7TLiIQfGk2MnhySp8,118
2
- TonieToolbox/__main__.py,sha256=KSDasW-QaTzStXSKtemMKxoFV8IWvCmq1Oig5yo8BQs,41573
3
- TonieToolbox/artwork.py,sha256=BhAjLWqzui8zUOU9z9P4H3zbCCTOB94aT0MPlqEvZoY,5605
4
- TonieToolbox/audio_conversion.py,sha256=xXXsRGPS_yQ_mqtFJiqupLbeXN8__Q2Hg05C94EPC_8,17199
5
- TonieToolbox/constants.py,sha256=nTKDBy55PTv6Tazda3rsZZcckcm3AZOyWXa1LDuTuEk,33989
6
- TonieToolbox/dependency_manager.py,sha256=sQv0vNE7Gp_RqdR9GOwF8jJgu8GTw0Krppg5MjG5qJU,49432
7
- TonieToolbox/filename_generator.py,sha256=NJrRxv0sm_9G5ZDp1QG39mktgJnz5yGC8HUs7NhLYFg,5293
8
- TonieToolbox/integration.py,sha256=a-GBynecxwozUqEe3NjXbePcBpolzWKBZLQ5BeHsG2E,3302
9
- TonieToolbox/integration_macos.py,sha256=YxK7gIqiy1QTp7EM1M1OPC-mgb3gaIoI6Xfu3eUAyX0,27311
10
- TonieToolbox/integration_ubuntu.py,sha256=_Da2s7CmuP7kts0W-yyt4odZA8jr14d8iisVF_ipLDA,52
11
- TonieToolbox/integration_windows.py,sha256=ycPKKswA90auzzns7bSJ9-HhH6UGRKgK_lAwPoBU0YI,24017
12
- TonieToolbox/logger.py,sha256=ppAnOJAKNwwbt5q3NdF2WHgHemZjP0QWRaUx8UrkQK8,3139
13
- TonieToolbox/media_tags.py,sha256=pOLcqnY4sUudI-gBre0A7le3nA7ZDkhUNkozUdRVHiE,20843
14
- TonieToolbox/ogg_page.py,sha256=CpL3mHoRsfHBBrT2r4x5p3LBPgHfYQxb_WQsCZq6SI0,22341
15
- TonieToolbox/opus_packet.py,sha256=skKzr5sVpL7L77JisqqGL4Kz86acOGDzwbFRqRL2oSM,8017
16
- TonieToolbox/recursive_processor.py,sha256=IcTmQY6OF01KUfqjYE7F0CFl1SeWcSLzkB_Du6R8deI,13910
17
- TonieToolbox/tags.py,sha256=usNcZxMEAMP7vEfeNOtg70YBJpHiWuHb_XKCyEafsYc,2702
18
- TonieToolbox/teddycloud.py,sha256=1fpRzhJrOiUXTBhX9JNL9rlO5obIl32WMoYz5RWz0zA,18486
19
- TonieToolbox/tonie_analysis.py,sha256=KkaZ6vt4sntMTfutyQApI8gvCirMjTW8aeIBSbhtllA,30798
20
- TonieToolbox/tonie_file.py,sha256=z7yRmK0ujZ6SjF78-xJImGmQ2bS-Q7b-6d2ryYJnmwA,21769
21
- TonieToolbox/tonie_header.proto,sha256=WaWfwO4VrwGtscK2ujfDRKtpeBpaVPoZhI8iMmR-C0U,202
22
- TonieToolbox/tonie_header_pb2.py,sha256=s5bp4ULTEekgq6T61z9fDkRavyPM-3eREs20f_Pxxe8,3665
23
- TonieToolbox/tonies_json.py,sha256=Icu5ClFbRK0gFuefJkHQNRjeOW79tQV-GZ3hoIATo3M,60768
24
- TonieToolbox/version_handler.py,sha256=Q-i5_0r5lX3dlwDLI2lMAx4X10UZGN2rvMcntmyuiT4,9862
25
- tonietoolbox-0.6.0rc3.dist-info/licenses/LICENSE.md,sha256=rGoga9ZAgNco9fBapVFpWf6ri7HOBp1KRnt1uIruXMk,35190
26
- tonietoolbox-0.6.0rc3.dist-info/METADATA,sha256=2tycPL42jf92Um34ATsD24dePbCIMH97HsIcV-Sc5Q0,29087
27
- tonietoolbox-0.6.0rc3.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
28
- tonietoolbox-0.6.0rc3.dist-info/entry_points.txt,sha256=oqpeyBxel7aScg35Xr4gZKnf486S5KW9okqeBwyJxxc,60
29
- tonietoolbox-0.6.0rc3.dist-info/top_level.txt,sha256=Wkkm-2p7I3ENfS7ZbYtYUB2g-xwHrXVlERHfonsOPuE,13
30
- tonietoolbox-0.6.0rc3.dist-info/RECORD,,