def find_track(self, track_id: str = None, artist: str = None, title: str = None, duration: float = None) -> models.DjayTrack: if all([ track_id is None, artist is None, title is None, duration is None ]): raise Error("At least one of track_id, artist, title are required") results = [] for row in self.get_rows(collection='mediaItemTitleIDs'): if track_id is not None and row.key != track_id: continue title_obj = archiver.unarchive(row.data) if artist is not None and title_obj.artist != artist: continue if title is not None and title_obj.title != title: continue if (duration is not None and abs(title_obj.duration - duration) > .01): continue results.append(self.load_track(row.key)) if not results: raise Error(f"Track not found for id={track_id} artist={artist} " f"title={title} duration={duration}") if len(results) > 1: raise Error(f"More than one track matched: {results}") return results[0]
def read_nskeyedarchive(data: bytes) -> dict: """Decode binary string encoded using NSKeyedArchiver. :returns: Parsed PLIST :rtye: dict """ return archiver.unarchive(data)
def __init__(self, revgeoloc_bplist): """ revgeoloc_bplist: a binary plist blob containing a serialized PLRevGeoLocationInfo object """ self._bplist = revgeoloc_bplist # todo: check for None? self._plrevgeoloc = archiver.unarchive(revgeoloc_bplist) self._process_place_info()
def test_analyzed_data_e2e(self): expected = models.ADCMediaItemAnalyzedData( bpm=1, keySignatureIndex=10, uuid="foo", ) actual = archiver.unarchive(archiver.archive(expected)) self.assertEqual(actual, expected)
def test_cuepoint_e2e(self): expected = models.ADCCuePoint( comment="bar", number=2, time=15.2, ) actual = archiver.unarchive(archiver.archive(expected)) self.assertEqual(actual, expected)
def test_title_e2e(self): expected = models.ADCMediaItemTitleID( title='title', artist='artist', uuid='UuId', internalID='UuId', stringRepresentation='String Repr', duration=15.3, ) actual = archiver.unarchive(archiver.archive(expected)) self.assertEqual(actual, expected)
def test_location_e2e(self): expected = models.ADCMediaItemLocation( sourceURIs={ models.NSURL(NSrelative='file:///tmp/foo.wav', NSbase=None), models.NSURL(NSrelative='com.apple.iTunes:123456', NSbase=None) }, type=3, urlBookmarkData=models.NSMutableData( NSdata=b'not a b64-encoded string'), uuid='71f9') actual = archiver.unarchive(archiver.archive(expected)) self.assertEqual(actual, expected)
def auxiliary_to_pyobject(aux): m, t = struct.unpack("<ii", aux[:8]) if m != 0xa: raise ValueError("auxiliary magic error") if t == 2: l, = struct.unpack("<i", aux[8:12]) assert len(aux) == 12 + l, "bad auxiliary" return archiver.unarchive(aux[12:]) elif t == 3: n, = struct.unpack("<i", aux[8:12]) return n elif t == 4: n, = struct.unpack("<q", aux[8:16]) return n else: raise ValueError("unknown auxiliary type")
def verify_version(self): products_rows = self.get_rows( collection='products', key='com.algoriddim.direct.djay-pro-2-mac-Mac', ) if not products_rows: raise BadDataFormatError( "Didn't find database row for collection=products. " "Unsupported djay version?") products_row = products_rows[0] product = archiver.unarchive(products_row.data) if not is_supported_version(product.version): raise BadDataFormatError('Unsupported djay Pro 2 version: ' + product.version)
def load_track(self, track_id: str): rows = self.get_rows(key=track_id) collection_to_field = { 'mediaItemUserData': 'user_data', 'mediaItemTitleIDs': 'title', 'mediaItemAnalyzedData': 'analysis', 'localMediaItemLocations': 'local_location', 'globalMediaItemLocations': 'global_location', 'mediaItems': 'media_item', } field_values = {} for row in rows: field_name = collection_to_field[row.collection] field_values[field_name] = archiver.unarchive(row.data) track = models.DjayTrack(**field_values) # type: ignore return track
def test_userdata_e2e(self): expected = models.ADCMediaItemUserData( cuePoints=[ models.ADCCuePoint(comment=None, number=1, time=3.2826459407806396), models.ADCCuePoint(comment=None, number=2, time=114.29496765136719), models.ADCCuePoint(comment=None, number=3, time=114.83682250976562) ], startPoint=models.ADCCuePoint(comment=None, number=0, time=112.90266418457031), uuid='71f9ccc746630c592ceeed39cbc837b2', playCount=7, energy=15, highEQ=10.30, midEQ=2.0, lowEQ=3.0, manualBPM=117.33, manualBeatTime=1.01, manualKeySignatureIndex=7, rating=3, # TODO: Populate the fields. linkedUserDataUUIDs=None, loopRegions=None, manualFirstDownBeatIndices=None, manualGridStartPoints=None, tagUUIDs=None, endPoint=None, ) actual = archiver.unarchive(archiver.archive(expected)) self.assertEqual(actual, expected)
def test_userdata_unarchive(self): bplist = dj_tests.get_fixture_from_xml('userdata.plist.xml') expected = dj_tests.EXPECTED_USER_DATA actual = archiver.unarchive(bplist) self.assertEqual(actual, expected, f'\n{actual} != \n{expected}')
def test_analyzed_data_unarchive(self): bplist = dj_tests.get_fixture_from_xml('analyzed_data.plist.xml') expected = dj_tests.EXPECTED_ANALYZED_DATA actual = archiver.unarchive(bplist) self.assertEqual(actual, expected)
def test_cuepoint_unarchive(self): bplist = dj_tests.get_fixture_from_xml('cuepoint.plist.xml') expected = dj_tests.EXPECTED_CUEPOINT actual = archiver.unarchive(bplist) self.assertEqual(actual, expected)
# dyldNotificationReceived: coreprofile_cfg2 = load_byte_from_hexdump( """79 5B 3D 1F 20 00 00 00 00 00 01 00 22 02 00 00 18 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 59 01 00 00 12 02 00 00 00 00 00 00 F0 01 00 00 00 00 00 00 49 01 00 00 00 00 00 00 0A 00 00 00 02 00 00 00 8C 00 00 00 62 70 6C 69 73 74 30 30 D4 01 02 03 04 05 06 07 0A 58 24 76 65 72 73 69 6F 6E 59 24 61 72 63 68 69 76 65 72 54 24 74 6F 70 58 24 6F 62 6A 65 63 74 73 12 00 01 86 A0 5F 10 0F 4E 53 4B 65 79 65 64 41 72 63 68 69 76 65 72 D1 08 09 54 72 6F 6F 74 80 01 A2 0B 0C 55 24 6E 75 6C 6C 11 01 E6 08 11 1A 24 29 32 37 49 4C 51 53 56 5C 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5F 0A 00 00 00 02 00 00 00 A5 00 00 00 62 70 6C 69 73 74 30 30 D4 01 02 03 04 05 06 07 0A 58 24 76 65 72 73 69 6F 6E 59 24 61 72 63 68 69 76 65 72 54 24 74 6F 70 58 24 6F 62 6A 65 63 74 73 12 00 01 86 A0 5F 10 0F 4E 53 4B 65 79 65 64 41 72 63 68 69 76 65 72 D1 08 09 54 72 6F 6F 74 80 01 A2 0B 0C 55 24 6E 75 6C 6C 5F 10 19 64 79 6C 64 4E 6F 74 69 66 69 63 61 74 69 6F 6E 52 65 63 65 69 76 65 64 3A 08 11 1A 24 29 32 37 49 4C 51 53 56 5C 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 78 62 70 6C 69 73 74 30 30 D4 01 02 03 04 05 06 07 0A 58 24 76 65 72 73 69 6F 6E 59 24 61 72 63 68 69 76 65 72 54 24 74 6F 70 58 24 6F 62 6A 65 63 74 73 12 00 01 86 A0 5F 10 0F 4E 53 4B 65 79 65 64 41 72 63 68 69 76 65 72 D1 08 09 54 72 6F 6F 74 80 01 A2 0B 0C 55 24 6E 75 6C 6C 5F 10 2D 73 79 6D 62 6F 6C 69 63 61 74 6F 72 53 69 67 6E 61 74 75 72 65 46 6F 72 50 69 64 3A 74 72 61 63 6B 69 6E 67 53 65 6C 65 63 74 6F 72 3A 08 11 1A 24 29 32 37 49 4C 51 53 56 5C 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8C""" ) # 1 # symbolicatorSignatureForPid:trackingSelector: # 0 # dyldNotificationReceived: sig = load_byte_from_hexdump( """79 5B 3D 1F 20 00 00 00 00 00 01 00 21 02 00 00 1B 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00 58 01 00 00 11 02 00 00 00 00 00 00 F0 01 00 00 00 00 00 00 48 01 00 00 00 00 00 00 0A 00 00 00 02 00 00 00 8B 00 00 00 62 70 6C 69 73 74 30 30 D4 01 02 03 04 05 06 07 0A 58 24 76 65 72 73 69 6F 6E 59 24 61 72 63 68 69 76 65 72 54 24 74 6F 70 58 24 6F 62 6A 65 63 74 73 12 00 01 86 A0 5F 10 0F 4E 53 4B 65 79 65 64 41 72 63 68 69 76 65 72 D1 08 09 54 72 6F 6F 74 80 01 A2 0B 0C 55 24 6E 75 6C 6C 10 00 08 11 1A 24 29 32 37 49 4C 51 53 56 5C 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5E 0A 00 00 00 02 00 00 00 A5 00 00 00 62 70 6C 69 73 74 30 30 D4 01 02 03 04 05 06 07 0A 58 24 76 65 72 73 69 6F 6E 59 24 61 72 63 68 69 76 65 72 54 24 74 6F 70 58 24 6F 62 6A 65 63 74 73 12 00 01 86 A0 5F 10 0F 4E 53 4B 65 79 65 64 41 72 63 68 69 76 65 72 D1 08 09 54 72 6F 6F 74 80 01 A2 0B 0C 55 24 6E 75 6C 6C 5F 10 19 64 79 6C 64 4E 6F 74 69 66 69 63 61 74 69 6F 6E 52 65 63 65 69 76 65 64 3A 08 11 1A 24 29 32 37 49 4C 51 53 56 5C 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 78 62 70 6C 69 73 74 30 30 D4 01 02 03 04 05 06 07 0A 58 24 76 65 72 73 69 6F 6E 59 24 61 72 63 68 69 76 65 72 54 24 74 6F 70 58 24 6F 62 6A 65 63 74 73 12 00 01 86 A0 5F 10 0F 4E 53 4B 65 79 65 64 41 72 63 68 69 76 65 72 D1 08 09 54 72 6F 6F 74 80 01 A2 0B 0C 55 24 6E 75 6C 6C 5F 10 2D 73 79 6D 62 6F 6C 69 63 61 74 6F 72 53 69 67 6E 61 74 75 72 65 46 6F 72 50 69 64 3A 74 72 61 63 6B 69 6E 67 53 65 6C 65 63 74 6F 72 3A 08 11 1A 24 29 32 37 49 4C 51 53 56 5C 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8C""" ) stop = load_byte_from_hexdump( """79 5B 3D 1F 20 00 00 00 00 00 01 00 A8 00 00 00 23 00 00 00 00 00 00 00 09 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 98 00 00 00 00 00 00 00 62 70 6C 69 73 74 30 30 D4 01 02 03 04 05 06 07 0A 58 24 76 65 72 73 69 6F 6E 59 24 61 72 63 68 69 76 65 72 54 24 74 6F 70 58 24 6F 62 6A 65 63 74 73 12 00 01 86 A0 5F 10 0F 4E 53 4B 65 79 65 64 41 72 63 68 69 76 65 72 D1 08 09 54 72 6F 6F 74 80 01 A2 0B 0C 55 24 6E 75 6C 6C 5E 73 74 6F 70 43 6F 6C 6C 65 63 74 69 6F 6E 08 11 1A 24 29 32 37 49 4C 51 53 56 5C 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6B""" ) reg2 = load_byte_from_hexdump( """79 5B 3D 1F 20 00 00 00 00 00 01 00 6A 01 00 00 09 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 02 00 00 00 A6 00 00 00 5A 01 00 00 00 00 00 00 F0 01 00 00 00 00 00 00 96 00 00 00 00 00 00 00 0A 00 00 00 02 00 00 00 8A 00 00 00 62 70 6C 69 73 74 30 30 D4 01 02 03 04 05 06 07 0A 58 24 76 65 72 73 69 6F 6E 59 24 61 72 63 68 69 76 65 72 54 24 74 6F 70 58 24 6F 62 6A 65 63 74 73 12 00 01 86 A0 5F 10 0F 4E 53 4B 65 79 65 64 41 72 63 68 69 76 65 72 D1 08 09 54 72 6F 6F 74 80 01 A2 0B 0C 55 24 6E 75 6C 6C 09 08 11 1A 24 29 32 37 49 4C 51 53 56 5C 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5D 62 70 6C 69 73 74 30 30 D4 01 02 03 04 05 06 07 0A 58 24 76 65 72 73 69 6F 6E 59 24 61 72 63 68 69 76 65 72 54 24 74 6F 70 58 24 6F 62 6A 65 63 74 73 12 00 01 86 A0 5F 10 0F 4E 53 4B 65 79 65 64 41 72 63 68 69 76 65 72 D1 08 09 54 72 6F 6F 74 80 01 A2 0B 0C 55 24 6E 75 6C 6C 5F 10 28 73 65 74 41 70 70 6C 69 63 61 74 69 6F 6E 53 74 61 74 65 4E 6F 74 69 66 69 63 61 74 69 6F 6E 73 45 6E 61 62 6C 65 64 3A 08 11 1A 24 29 32 37 49 4C 51 53 56 5C 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 87""" ) startServ = load_byte_from_hexdump( """79 5B 3D 1F 20 00 00 00 00 00 01 00 A5 00 00 00 46 01 00 00 01 00 00 00 01 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 95 00 00 00 00 00 00 00 62 70 6C 69 73 74 30 30 D4 01 02 03 04 05 06 09 0A 58 24 76 65 72 73 69 6F 6E 58 24 6F 62 6A 65 63 74 73 59 24 61 72 63 68 69 76 65 72 54 24 74 6F 70 12 00 01 86 A0 A2 07 08 55 24 6E 75 6C 6C 5B 6D 61 63 68 5F 6B 65 72 6E 65 6C 5F 10 0F 4E 53 4B 65 79 65 64 41 72 63 68 69 76 65 72 D1 0B 0C 54 72 6F 6F 74 80 01 08 11 1A 23 2D 32 37 3A 40 4C 5E 61 66 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 68 """ ) dt = DTXMessage().from_bytes(startServ) print(dt.channel_code) print(archiver.unarchive(dt.get_selector())) #print(dt.parse_plist_to_xml()) for i in dt._auxiliaries: print(auxiliary_to_pyobject(i))
def test_title_unarchive(self): bplist = dj_tests.get_fixture_from_xml('adctitle.plist.xml') expected = dj_tests.EXPECTED_TITLE actual = archiver.unarchive(bplist) self.assertEqual(actual, expected)
def test_unpack_primitive_multiple_refs(self): expected = ['a', 'a'] actual = archiver.unarchive(archiver.archive(['a', 'a'])) self.assertEqual(actual, expected)
def test_verify_dataclass_has_fields(self): with self.assertRaises(archive_types.Error): bplist = dj_tests.get_fixture_from_xml( 'cuepoint_extra_field.plist.xml') archiver.unarchive(bplist)
def archive(self, obj): archived = archiver.archive(obj) unarchived = archiver.unarchive(archived) self.assertEqual(obj, unarchived)
def test_location_unarchive(self): bplist = dj_tests.get_fixture_from_xml('location.plist.xml') expected = dj_tests.EXPECTED_MEDIA_ITEM_LOCATION actual = archiver.unarchive(bplist) self.assertEqual(actual, expected)
def unarchive(self, plist): return archiver.unarchive(self.fixture(plist))
def selector_to_pyobject(sel): if not sel: return None return archiver.unarchive(sel)