tictacsync 1.0.2a0__py3-none-any.whl → 1.2.0b0__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.

Potentially problematic release.


This version of tictacsync might be problematic. Click here for more details.

tictacsync/timeline.py CHANGED
@@ -9,7 +9,7 @@ from rich import print
9
9
  from itertools import groupby
10
10
  # import opentimelineio as otio
11
11
  from datetime import timedelta
12
- import shutil, os, sys, stat
12
+ import shutil, os, sys, stat, subprocess
13
13
  from subprocess import Popen, PIPE
14
14
  from pprint import pformat
15
15
 
@@ -401,6 +401,7 @@ class AudioStitcherVideoMerger:
401
401
  Returns audio recordings that overlap self.videoclip.
402
402
  Simply keys of self.soxed_audio dict
403
403
  """
404
+ logger.debug(f'soxed_audio {pformat(self.soxed_audio)}')
404
405
  return list(self.soxed_audio.keys())
405
406
 
406
407
  def _get_audio_devices(self):
@@ -411,15 +412,16 @@ class AudioStitcherVideoMerger:
411
412
  return devices
412
413
 
413
414
  def _get_secondary_audio_devices(self):
414
- devices = set([r.device for r in self.get_matched_audio_recs()])
415
- logger.debug('get_matched_audio_recs: %s'%
416
- pformat(self.get_matched_audio_recs()))
417
- logger.debug('devices %s'%devices)
418
- return devices
415
+ # when only audio devices are synced.
416
+ # identical to _get_audio_devices()...
417
+ # name changed for clarity
418
+ return self._get_audio_devices()
419
419
 
420
420
  def _get_all_recordings_for(self, device):
421
421
  # return recordings for a particular device, sorted by time
422
- recs = [a for a in self.get_matched_audio_recs() if a.device == device]
422
+ recs = self.get_matched_audio_recs()
423
+ logger.debug(f'device: {device.name} matched audio recs: {recs}')
424
+ recs = [a for a in recs if a.device == device]
423
425
  recs.sort(key=lambda r: r.start_time)
424
426
  return recs
425
427
 
@@ -652,14 +654,16 @@ class AudioStitcherVideoMerger:
652
654
  self.soxed_audio[audio_rec] = output_fh
653
655
  return output_fh
654
656
 
655
- def _write_ISOs(self, edited_audio_all_devices):
657
+ def _write_ISOs(self, edited_audio_all_devices,
658
+ snd_root=None, synced_root=None, raw_root=None, audio_only=False):
656
659
  """
660
+ [TODO: this multiline doc is obsolete]
657
661
  Writes isolated audio files that were synced to synced_clip_file,
658
662
  each track will have its dedicated monofile, named sequentially or with
659
663
  the name find in TRACKSFILE if any, see Scanner._get_tracks_from_file()
660
664
 
661
665
  edited_audio_all_devices:
662
- a list of (name, mono_tempfile)
666
+ a list of (name, mono_tempfile, dev) -------------------------------------------> add argument for device for calling _get_all_recordings_for() for file for metada
663
667
 
664
668
  Returns nothing, output is written to filesystem as below.
665
669
  ISOs subfolders structure when user invokes the --isos flag:
@@ -671,7 +675,7 @@ class AudioStitcherVideoMerger:
671
675
  canon24fps01.MOV ━━━━┓ name of clip is name of folder
672
676
  canon24fps01_ISO/ <━━┛
673
677
  chan_1.wav
674
- chan_2.wav
678
+ chan_2.wav [UPDATE FOR MAM mode]
675
679
  canon24fps02.MOV
676
680
  canon24fps01_ISO/
677
681
  chan_1.wav
@@ -708,8 +712,30 @@ class AudioStitcherVideoMerger:
708
712
  logger.debug('video duration %.2f s'%
709
713
  self.videoclip.get_duration())
710
714
  return out_tf
711
- synced_clip_file = self.videoclip.final_synced_file
712
- synced_clip_dir = synced_clip_file.parent
715
+ def _meta_wav_dest(p1, p2, p3):
716
+ """
717
+ takes metadata from p1, sound from p2 and combine them to create p3.
718
+ arguments are pathlib.Path or string;
719
+ returns nothing.
720
+ """
721
+ f1, f2, f3 = [_pathname(p) for p in [p1, p2, p3]]
722
+ process_list = ['ffmpeg', '-y', '-loglevel', 'quiet', '-nostats', '-hide_banner',
723
+ '-i', f1, '-i', f2, '-map', '1',
724
+ '-map_metadata', '0', '-c', 'copy', f3]
725
+ proc = subprocess.run(process_list)
726
+ logger.debug(f'synced_clip_file raw')
727
+ if snd_root == None:
728
+ # alongside mode
729
+ synced_clip_file = self.videoclip.final_synced_file
730
+ logger.debug('alongside mode')
731
+ synced_clip_dir = synced_clip_file.parent
732
+ else:
733
+ # MAM mode
734
+ synced_clip_file = self.videoclip.AVpath
735
+ logger.debug('MAM mode')
736
+ rel = synced_clip_file.parent.relative_to(raw_root)
737
+ synced_clip_dir = Path(snd_root)/Path(raw_root).name/rel
738
+ logger.debug(f'synced_clip_dir: {synced_clip_dir}')
713
739
  # build ISOs subfolders structure, see comment string below
714
740
  video_stem_WO_suffix = synced_clip_file.stem
715
741
  # ISOdir = synced_clip_dir/(video_stem_WO_suffix + 'ISO')
@@ -717,10 +743,17 @@ class AudioStitcherVideoMerger:
717
743
  os.makedirs(ISOdir, exist_ok=True)
718
744
  logger.debug('edited_audio_all_devices %s'%edited_audio_all_devices)
719
745
  logger.debug('ISOdir %s'%ISOdir)
720
- for name, mono_tmpfl in edited_audio_all_devices:
721
- destination = ISOdir/('%s.wav'%name)
746
+ for name, mono_tmpfl, device in edited_audio_all_devices:
747
+ logger.debug(f'name:{name} mono_tmpfl:{mono_tmpfl} device:{pformat(device)}')
748
+ destination = ISOdir/(f'{video_stem_WO_suffix}_{name}.wav')
722
749
  mono_tmpfl_trimpad = _fit_length(mono_tmpfl)
723
- shutil.copy(_pathname(mono_tmpfl_trimpad), destination)
750
+ # if audio_only, self.ref_audio does not have itself as matching audio
751
+ if audio_only and device == self.ref_audio.device:
752
+ first_rec = self.ref_audio
753
+ else:
754
+ first_rec = self._get_all_recordings_for(device)[0]
755
+ logger.debug(f'will use {first_rec} for metadata source to copy over {destination}')
756
+ _meta_wav_dest(first_rec.AVpath, mono_tmpfl_trimpad, destination)
724
757
  # remove_write_permissions(destination)
725
758
  logger.debug('destination:%s'%destination)
726
759
 
@@ -867,19 +900,21 @@ class AudioStitcherVideoMerger:
867
900
  stereo_files = mic_stereo_files + new_stereo_files
868
901
  return _sox_mix_files(stereo_files)
869
902
 
870
- def build_audio_and_write_merged_media(self, top_dir,
871
- dont_write_cam_folder, asked_ISOs, audio_REC_only):
872
- # simply bifurcates depending if ref media is video (prob 99%)
873
- # (then audio_REC_only == False)
874
- # or if ref media is audio (no camera detected, 1% of cases)
875
- # (with audio_REC_only == True)
876
- if not audio_REC_only:
877
- self._build_audio_and_write_video(top_dir,
878
- dont_write_cam_folder, asked_ISOs)
879
- else:
880
- self._build_and_write_audio(top_dir, anchor_dir)
881
-
882
- def _build_and_write_audio(self, top_dir, anchor_dir):
903
+ # def build_audio_and_write_merged_media(self, top_dir,
904
+ # dont_write_cam_folder, asked_ISOs, audio_REC_only):
905
+ # # simply bifurcates depending if ref media is video (prob 99%)
906
+ # # (then audio_REC_only == False)
907
+ # # or if ref media is audio (no camera detected, 1% of cases)
908
+ # # (with audio_REC_only == True)
909
+ # if not audio_REC_only:
910
+ # # almost always syncing audio to video clips
911
+ # self._build_audio_and_write_video(top_dir,
912
+ # dont_write_cam_folder, asked_ISOs)
913
+ # else:
914
+ # # rare
915
+ # self._build_and_write_audio(top_dir, anchor_dir)
916
+
917
+ def _build_and_write_audio(self, top_dir, anchor_dir=None):
883
918
  """
884
919
  This is called when only audio recorders were found (no cam).
885
920
 
@@ -911,8 +946,7 @@ class AudioStitcherVideoMerger:
911
946
  self.synced_clip_dir = synced_clip_dir
912
947
  os.makedirs(synced_clip_dir, exist_ok=True)
913
948
  logger.debug('synced_clip_dir is: %s'%synced_clip_dir)
914
- synced_clip_file = synced_clip_dir/\
915
- Path(self.videoclip.new_rec_name).name
949
+ synced_clip_file = synced_clip_dir/self.videoclip.AVpath.name
916
950
  logger.debug('editing files for synced_clip_file%s'%synced_clip_file)
917
951
  self.ref_audio.final_synced_file = synced_clip_file # relative path
918
952
  # Collecting edited audio by device, in (Device, tempfile) pairs:
@@ -972,14 +1006,15 @@ class AudioStitcherVideoMerger:
972
1006
  logger.debug('track_name %s'%track_name)
973
1007
  if track_name[0] == '0': # muted, skip
974
1008
  continue
975
- names_audio_tempfiles.append((track_name, monotf))
976
- logger.debug('names_audio_tempfiles %s'%names_audio_tempfiles)
977
- self._write_ISOs(names_audio_tempfiles)
1009
+ names_audio_tempfiles.append((track_name, monotf, dev))
1010
+ logger.debug('names_audio_tempfiles %s'%pformat(names_audio_tempfiles))
1011
+ self._write_ISOs(names_audio_tempfiles, audio_only=True)
978
1012
  logger.debug('merged_audio_files_by_device %s'%
979
1013
  merged_audio_files_by_device)
980
1014
 
981
1015
  def _build_audio_and_write_video(self, top_dir, dont_write_cam_folder,
982
- asked_ISOs):
1016
+ asked_ISOs, synced_root = None,
1017
+ snd_root = None, raw_root = None):
983
1018
  """
984
1019
  top_dir: Path, directory where media were looked for
985
1020
 
@@ -1004,22 +1039,22 @@ class AudioStitcherVideoMerger:
1004
1039
  (top_dir, dont_write_cam_folder, asked_ISOs))
1005
1040
  logger.debug('device for rec %s: %s'%(self.videoclip,
1006
1041
  self.videoclip.device))
1007
- # eg, suppose the user called tictacsync with 'mondayPM' as top folder
1008
- # to scan for dailies (and 'somefolder' for output):
1009
- # if anchor_dir == None:
1010
- # then "alongside mode" i.e., in a folder neighboring the video clip
1011
- # WAS: synced_clip_dir = Path(top_dir)/OUT_DIR_DEFAULT # = mondayPM/SyncedMedia
1012
- logger.debug('"alongside mode" for clip: %s'%self.videoclip.AVpath)
1013
- synced_clip_dir = self.videoclip.AVpath.parent/OUT_DIR_DEFAULT
1014
- # else: # [TODO: replace original clip in a mirrored file structure]
1015
- # logger.debug('mirrored mode for clip: %s'%self.videoclip.AVpath)
1016
- # synced_clip_dir = Path(anchor_dir)/Path(top_dir).name # = somefolder/mondayPM
1017
- # if write_multicam_structure:
1018
- # device_name = self.videoclip.device.name
1019
- # synced_clip_dir = synced_clip_dir/device_name # = synced_clip_dir/ZOOM
1042
+ if synced_root == None:
1043
+ # alongside, within SyncedMedia dirs
1044
+ synced_clip_dir = self.videoclip.AVpath.parent/OUT_DIR_DEFAULT
1045
+ logger.debug('"alongside mode" for clip: %s'%self.videoclip.AVpath)
1046
+ logger.debug(f'will save in {synced_clip_dir}')
1047
+ else:
1048
+ # MAM mode
1049
+ logger.debug('MAM mode')
1050
+ synced_clip_dir = Path(synced_root)/str(self.videoclip.AVpath.parent)[1:] # strip leading /
1051
+ rel = self.videoclip.AVpath.parent.relative_to(raw_root).parent
1052
+ logger.debug(f'relative path {rel}')
1053
+ synced_clip_dir = Path(synced_root)/Path(raw_root).name/rel
1054
+ logger.debug(f'will save in {synced_clip_dir}')
1020
1055
  self.synced_clip_dir = synced_clip_dir
1021
1056
  os.makedirs(synced_clip_dir, exist_ok=True)
1022
- logger.debug('synced_clip_dir is: %s'%synced_clip_dir)
1057
+ # logger.debug('synced_clip_dir is: %s'%synced_clip_dir)
1023
1058
  synced_clip_file = synced_clip_dir/self.videoclip.AVpath.name
1024
1059
  logger.debug('editing files for synced_clip_file %s'%synced_clip_file)
1025
1060
  self.videoclip.final_synced_file = synced_clip_file # relative path
@@ -1132,9 +1167,10 @@ class AudioStitcherVideoMerger:
1132
1167
  logger.debug('track_name %s'%track_name)
1133
1168
  if track_name[0] == '0': # muted, skip
1134
1169
  continue
1135
- names_audio_tempfiles.append((track_name, monotf))
1170
+ names_audio_tempfiles.append((track_name, monotf, dev))
1136
1171
  logger.debug('names_audio_tempfiles %s'%pformat(names_audio_tempfiles))
1137
- self._write_ISOs(names_audio_tempfiles)
1172
+ self._write_ISOs(names_audio_tempfiles,
1173
+ snd_root=snd_root, synced_root=synced_root, raw_root=raw_root)
1138
1174
  logger.debug('merged_audio_files_by_device %s'%
1139
1175
  merged_audio_files_by_device)
1140
1176
  # This loop below for logging purpose only:
@@ -1268,21 +1304,6 @@ class Matcher:
1268
1304
  self.recordings = recordings_list
1269
1305
  self.mergers = []
1270
1306
 
1271
- # def _rename_all_recs(self):
1272
- # """
1273
- # Add _synced to filenames of synced video files. Change stored name only:
1274
- # files have yet to be written to.
1275
- # """
1276
- # # match IO_structure:
1277
- # # case 'foldercam':
1278
- # for rec in self.recordings:
1279
- # rec_extension = rec.AVpath.suffix
1280
- # rel_path_new_name = '%s%s'%(rec.AVpath.stem, rec_extension)
1281
- # rec.new_rec_name = Path(rel_path_new_name)
1282
- # logger.debug('for %s new name: %s'%(
1283
- # _pathname(rec.AVpath),
1284
- # _pathname(rec.new_rec_name)))
1285
-
1286
1307
  def scan_audio_for_each_videoclip(self):
1287
1308
  """
1288
1309
  For each video (and for the Main Sound) in self.recordings, this finds
@@ -1294,10 +1315,11 @@ class Matcher:
1294
1315
  V3 checked against ...
1295
1316
  Main Sound checked against A1, A2, A3, A4
1296
1317
  """
1297
- video_recordings = [r for r in self.recordings if r.is_video()
1298
- or r.is_reference]
1318
+ video_recordings = [r for r in self.recordings
1319
+ if r.is_video() or r.is_audio_reference]
1320
+ # if r.is_audio_reference then audio, and will pass as video
1299
1321
  audio_recs = [r for r in self.recordings if r.is_audio()
1300
- and not r.is_reference]
1322
+ and not r.is_audio_reference]
1301
1323
  if not audio_recs:
1302
1324
  print('\nNo audio recording found, syncing of videos only not implemented yet, exiting...\n')
1303
1325
  sys.exit(1)
@@ -1453,7 +1475,7 @@ class Matcher:
1453
1475
  vid.write_file_timecode(tc)
1454
1476
  return
1455
1477
 
1456
- def move_multicam_to_dir(self):
1478
+ def move_multicam_to_dir(self, raw_root=None, synced_root=None):
1457
1479
  # creates a dedicated multicam directory and move clusters there
1458
1480
  # e.g., for "top/day01/camA/roll02"
1459
1481
  # ^ at that level
@@ -1462,6 +1484,7 @@ class Matcher:
1462
1484
  #
1463
1485
  # check for consistency: are all clips at the same level from topdir?
1464
1486
  # Only for video, not audio (which doesnt fill up cards)
1487
+ logger.debug(f'synced_root: {synced_root}')
1465
1488
  video_medias = [m for m in self.recordings if m.device.dev_type == 'CAM']
1466
1489
  video_paths = [m.AVpath.parts for m in video_medias]
1467
1490
  AV_path_lengths = [len(p) for p in video_paths]
@@ -1480,32 +1503,62 @@ class Matcher:
1480
1503
  sys.exit(0)
1481
1504
  # pick first
1482
1505
  CAM_level, avp = CAM_levels[0], video_medias[0].AVpath
1483
- logger.debug('CAM_levels: %s for ex \n%s'%(CAM_level, avp))
1506
+ logger.debug('CAM_levels: %s for %s\n'%(CAM_level, avp))
1484
1507
  # MCCDIR = 'SyncedMulticamClips'
1485
- parts_up_a_level = avp.parts[:CAM_level]
1486
- multicam_dir = Path('').joinpath(*parts_up_a_level)/MCCDIR
1508
+ parts_up_a_level = [prt for prt in avp.parts[:CAM_level] if prt != '/']
1509
+ logger.debug(f'parts_up_a_level: {parts_up_a_level}')
1510
+ if synced_root == None:
1511
+ # alongside mode
1512
+ logger.debug('alongside mode')
1513
+ multicam_dir = Path('').joinpath(*parts_up_a_level)/MCCDIR
1514
+ else:
1515
+ # MAM mode
1516
+ logger.debug('MAM mode')
1517
+ abs_path_up = Path('/').joinpath(*parts_up_a_level)/MCCDIR
1518
+ logger.debug(f'abs_path_up: {abs_path_up}')
1519
+ rel_up = abs_path_up.relative_to(raw_root)
1520
+ logger.debug(f'rel_up: {rel_up}')
1521
+ multicam_dir = Path(synced_root)/Path(raw_root).name/rel_up
1522
+ # multicam_dir = Path(synced_root).joinpath(*parts_up_a_level)/MCCDIR
1487
1523
  logger.debug('multicam_dir: %s'%multicam_dir)
1488
1524
  Path.mkdir(multicam_dir, exist_ok=True)
1489
1525
  cam_clips = []
1490
1526
  [cam_clips.append(cl['vids']) for cl in self.multicam_clips_clusters]
1491
1527
  cam_clips = _flatten(cam_clips)
1492
- logger.debug('cam_clips: %s'%cam_clips)
1528
+ logger.debug('cam_clips: %s'%pformat(cam_clips))
1493
1529
  cam_names = set([r.device.name for r in cam_clips])
1494
1530
  # create new dirs for each CAM
1495
1531
  [Path.mkdir(multicam_dir/cam_name, exist_ok=True)
1496
1532
  for cam_name in cam_names]
1497
1533
  # move clips there
1498
- for r in cam_clips:
1499
- cam = r.device.name
1500
- clip_name = r.AVpath.name
1501
- dest = r.final_synced_file.replace(multicam_dir/cam/clip_name)
1502
- logger.debug('dest: %s'%dest)
1503
- origin_folder = r.final_synced_file.parent
1504
- folder_now_empty = len(list(origin_folder.glob('*'))) == 0
1505
- if folder_now_empty:
1506
- logger.debug('after moving %s, folder is now empty, removing it'%dest)
1507
- origin_folder.rmdir()
1508
- print('\nMoved %i multicam clips in %s'%(len(cam_clips), multicam_dir))
1534
+ if synced_root == None:
1535
+ # alongside mode
1536
+ for r in cam_clips:
1537
+ cam = r.device.name
1538
+ clip_name = r.AVpath.name
1539
+ dest = r.final_synced_file.replace(multicam_dir/cam/clip_name)
1540
+ logger.debug('dest: %s'%dest)
1541
+ origin_folder = r.final_synced_file.parent
1542
+ folder_now_empty = len(list(origin_folder.glob('*'))) == 0
1543
+ if folder_now_empty:
1544
+ logger.debug('after moving %s, folder is now empty, removing it'%dest)
1545
+ origin_folder.rmdir()
1546
+ print('\nMoved %i multicam clips in %s'%(len(cam_clips), multicam_dir))
1547
+ else:
1548
+ # MAM mode
1549
+ for r in cam_clips:
1550
+ cam = r.device.name
1551
+ clip_name = r.AVpath.name
1552
+ dest = r.final_synced_file.replace(multicam_dir/cam/clip_name)
1553
+ # leave a symlink behind
1554
+ os.symlink(multicam_dir/cam/clip_name, r.final_synced_file)
1555
+ logger.debug('dest: %s'%dest)
1556
+ origin_folder = r.final_synced_file.parent
1557
+ # folder_now_empty = len(list(origin_folder.glob('*'))) == 0
1558
+ # if folder_now_empty:
1559
+ # logger.debug('after moving %s, folder is now empty, removing it'%dest)
1560
+ # origin_folder.rmdir()
1561
+ print('\nMoved %i multicam clips in %s'%(len(cam_clips), multicam_dir))
1509
1562
 
1510
1563
 
1511
1564
 
tictacsync/yaltc.py CHANGED
@@ -561,7 +561,7 @@ class Recording:
561
561
  sync_position : int
562
562
  position of first detected syn pulse
563
563
 
564
- is_reference : bool (True for ref rec only)
564
+ is_audio_reference : bool (True for ref rec only)
565
565
  in multi recorders set-ups, user decides if a sound-only recording
566
566
  is the time reference for all other audio recordings. By
567
567
  default any video recording is the time reference for other audio,
@@ -647,7 +647,7 @@ class Recording:
647
647
  self.decoder = None
648
648
  self.probe = None
649
649
  self.TicTacCode_channel = None
650
- self.is_reference = False
650
+ self.is_audio_reference = False
651
651
  self.device_relative_speed = 1.0
652
652
  # self.valid_sound = None
653
653
  self.final_synced_file = None
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tictacsync
3
- Version: 1.0.2a0
4
- Summary: command for syncing audio video recordings
3
+ Version: 1.2.0b0
4
+ Summary: commands for syncing audio video recordings
5
5
  Home-page: https://tictacsync.org/
6
6
  Author: Raymond Lutz
7
7
  Author-email: lutzrayblog@mac.com
8
- Classifier: Development Status :: 2 - Pre-Alpha
8
+ Classifier: Development Status :: 4 - Beta
9
9
  Classifier: Environment :: Console
10
10
  Classifier: Intended Audience :: End Users/Desktop
11
11
  Classifier: License :: OSI Approved :: MIT License
@@ -68,7 +68,7 @@ Then pip install the syncing program:
68
68
  This should install python dependencies _and_ the `tictacsync` command.
69
69
  ## Usage
70
70
 
71
- Download multiple sample files [here](https://nuage.lutz.quebec/s/D4DgzHrLaAjqNmY) (625 MB, sorry) unzip and run:
71
+ Download multiple sample files [here](https://nuage.lutz.quebec/s/4jw4xgqysLPS8EQ/download/dailies1_3.zip) (700+ MB, sorry) unzip and run:
72
72
 
73
73
  > tictacsync dailies/loose
74
74
  The program `tictacsync` will recursively scan the directory given as argument, find all audio that coincide with any video and merge them into a subfolder named `SyncedMedia`. When the argument is an unique media file (not a directory), no syncing will occur but the decoded starting time will be printed to stdout:
@@ -0,0 +1,19 @@
1
+ tictacsync/LTCcheck.py,sha256=IEfpB_ZajWuRTWtqji0H-B2g7GQvWmGVjfT0Icumv7o,15704
2
+ tictacsync/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ tictacsync/device_scanner.py,sha256=ZF4ufRQGUv-6zMFW4fzNZpcFYGr8uUPKRK6jM9_b-P4,36435
4
+ tictacsync/entry.py,sha256=xwqziTH1M1m1-6ZUOVO_B7xht9zRZ22G_6ITBtRsEXE,15911
5
+ tictacsync/mamconf.py,sha256=FCgwsAadFzrhEUHa7IFSA0nBJV1SyKK55iSTAFR5Nwc,6974
6
+ tictacsync/mamsync.py,sha256=2XPhlw2P6IBUoNFUjBhpV4eKP3JqD501zy0iZFXXEjo,16696
7
+ tictacsync/multi2polywav.py,sha256=78W5yzKBfWy4nmD837VKwmcHAUZm10zRNe8ARUBJWCI,7439
8
+ tictacsync/newmix.py,sha256=-zDxr6_O-rjyo1QfgktvHgwqy_un07eFI4zKi8nygIQ,19188
9
+ tictacsync/remergemix.py,sha256=bRyi1hyNcyM1rTkHh8DmSsIQjYpwPprxSyyVipnxz30,9909
10
+ tictacsync/remrgmx.py,sha256=FxaAo5qqynpj6O56ekQGD31YP6X2g-kEdwVpHSCoh4Q,4265
11
+ tictacsync/synciso.py,sha256=XmUcdUF9rl4VdCm7XW4PeYWYWM0vgAY9dC2hapoul9g,4821
12
+ tictacsync/timeline.py,sha256=wcj3n5nAWavJlrZ5Ia-WFmdI2lflU8V1uL13yhrUI7s,75836
13
+ tictacsync/yaltc.py,sha256=1XlOmdz-8ZUKF97A30MEkIA0F5oThqDgWPV8Ik3CHn4,53179
14
+ tictacsync-1.2.0b0.dist-info/LICENSE,sha256=ZAOPXLh1zlQAnhHUd7oLslKM01YZ5UiAu3STYjwIxck,1068
15
+ tictacsync-1.2.0b0.dist-info/METADATA,sha256=SzpJguMsyz9ZRg6uhP7Csw-oa2URSuCNKjj4kWVj66E,5694
16
+ tictacsync-1.2.0b0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
17
+ tictacsync-1.2.0b0.dist-info/entry_points.txt,sha256=EZrwgJ0nlXDdVUDcMEijMnha5lb1YCkkg4DY9iz97BE,199
18
+ tictacsync-1.2.0b0.dist-info/top_level.txt,sha256=eaCWG-BsYTRR-gLTJbK4RfcaXajr0gjQ6wG97MkGRrg,11
19
+ tictacsync-1.2.0b0.dist-info/RECORD,,
@@ -1,4 +1,6 @@
1
1
  [console_scripts]
2
+ mamconf = tictacsync.mamconf:main
3
+ mamsync = tictacsync.mamsync:main
2
4
  multi2polywav = tictacsync.multi2polywav:main
3
5
  newmix = tictacsync.newmix:main
4
6
  tictacsync = tictacsync.entry:main
@@ -1,18 +0,0 @@
1
- tictacsync/LTCcheck.py,sha256=IEfpB_ZajWuRTWtqji0H-B2g7GQvWmGVjfT0Icumv7o,15704
2
- tictacsync/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- tictacsync/device_scanner.py,sha256=GtAlL1pKj32S-I7Uo2fCi5pWRNNYJ2mmRkKPPEdV76A,37611
4
- tictacsync/entry.py,sha256=7qrPmxW0cwK2k4OWWkL9nOoCgww6aiYNdZDKKPUBNLE,15936
5
- tictacsync/mamsync.py,sha256=v8krJ0OSgh9WkdAZa9vFrKpEKSw9cMb5SBSC1rrCbYs,20005
6
- tictacsync/multi2polywav.py,sha256=Tt1xWfvQtuAi3aAVcXPDRu9ZGgDk2gmYyCRBSi6pTgk,7296
7
- tictacsync/newmix.py,sha256=HB5lThhSr1oVtUyIordaB-lwAxm4bbuijRr-MBdZWhA,13161
8
- tictacsync/remergemix.py,sha256=bRyi1hyNcyM1rTkHh8DmSsIQjYpwPprxSyyVipnxz30,9909
9
- tictacsync/remrgmx.py,sha256=FxaAo5qqynpj6O56ekQGD31YP6X2g-kEdwVpHSCoh4Q,4265
10
- tictacsync/synciso.py,sha256=XmUcdUF9rl4VdCm7XW4PeYWYWM0vgAY9dC2hapoul9g,4821
11
- tictacsync/timeline.py,sha256=aMu1ntVrpFtH1YfyIgp80k7DT2RFo5B0E-BlMWE8wAs,72723
12
- tictacsync/yaltc.py,sha256=xbMucI19UJKrEvIzyfpOsi3piSWzqM1gKgooeT9DV8g,53167
13
- tictacsync-1.0.2a0.dist-info/LICENSE,sha256=ZAOPXLh1zlQAnhHUd7oLslKM01YZ5UiAu3STYjwIxck,1068
14
- tictacsync-1.0.2a0.dist-info/METADATA,sha256=pkMWne2OEJ_m4gxeOXxpF2ww_0SXqTT43z4X4OUmJyo,5673
15
- tictacsync-1.0.2a0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
16
- tictacsync-1.0.2a0.dist-info/entry_points.txt,sha256=bMsk7T_7fwCtAOUbFyvECvHOzCJb2fmWjkUKQTkwbsc,131
17
- tictacsync-1.0.2a0.dist-info/top_level.txt,sha256=eaCWG-BsYTRR-gLTJbK4RfcaXajr0gjQ6wG97MkGRrg,11
18
- tictacsync-1.0.2a0.dist-info/RECORD,,