import pprint import bpy import ptsl from ptsl import PTSL_pb2 as pt from .geom_utils import compute_relative_vector, room_norm_vector, speaker_active_time_range def mixdown_speaker(speaker: bpy.types.Object, scene: bpy.types.Scene) -> str: return "" def create_clip(audio_file_path: str, client: ptsl.Client) -> str: return "" def spot_clip(speaker: bpy.types.Object, clip_id: str, track_id: str, client: ptsl.Client): pass def create_track(speaker: bpy.types.Object, client: ptsl.Client): assert speaker.data result = client.run_command(pt.CId_CreateNewTracks, {'numuer_of_tracks': 1, 'track_name': speaker.data.name, 'track_format': "TFormat_Mono", 'track_type': "TType_Audio", 'track_timebase': "TTimebase_Samples", 'pagination_request': { 'limit': 1, 'offset': 0, }, 'insertion_point_position': "TIPoint_Unknown", 'insertion_point_track_name': "" }) print(result) assert result assert 'created_track_ids' in result.keys() assert len(result['created_track_ids']) == 1 return result['created_track_ids'][0] def insert_audio(speaker: bpy.types.Object, scene: bpy.types.Scene, track_id: str, client: ptsl.Client): rendered_audio_file = mixdown_speaker(speaker, scene) clip_id = create_clip(rendered_audio_file, client) spot_clip(speaker, clip_id, track_id, client) def apply_pan_automation(speaker: bpy.types.Object, scene: bpy.types.Scene, track_id: str, room_size: float, client: ptsl.Client): CId_SetTrackControlBreakpoints = 150 # fps = scene.render.fps speaker_interval = speaker_active_time_range(speaker) assert scene.camera, "Scene does not have a camera" values: list[tuple[dict, dict, dict]] = [] for frame in range(speaker_interval.start_frame, speaker_interval.end_frame + 1): scene.frame_set(frame) relative_vector = compute_relative_vector(camera=scene.camera, target=speaker) norm_vec = room_norm_vector(relative_vector, room_size=room_size) time_struct = {'location': str(frame), 'time_type': 'TLType_Frames'} x_pos = {'time': time_struct, 'value': round(norm_vec.x, 4)} y_pos = {'time': time_struct, 'value': round(norm_vec.y, 4)} z_pos = {'time': time_struct, 'value': round(norm_vec.z, 4)} values.append((x_pos, y_pos, z_pos)) for i, control in enumerate(['PCParameter_X', 'PCParameter_Y', 'PCParameter_Z']): params ={ 'track_id': track_id, 'control_id': { 'section': 'TSId_MainOut', 'control_type': 'TCType_Pan', 'pan': { 'pan_space': 'PSpace_3dCart3layer', 'parameter': control, 'channel': 'SChannel_Mono' }, }, 'breakpoints': [v[i] for v in values] } print("Sending parameter changes:") pprint.pprint(params) client.run_command(CId_SetTrackControlBreakpoints, params) def send_to_pro_tools(speakers: list[bpy.types.Object], room_size: float) -> bool: try: print("About to create client.") client = ptsl.Client(company_name="Squad 51", application_name="Send to Pro Tools Blender Extension") scene = bpy.context.scene for speaker in speakers: new_track_id = create_track(speaker, client) insert_audio(speaker, scene, new_track_id, client) apply_pan_automation(speaker, scene, new_track_id, room_size, client) client.close() return True except ptsl.CommandError as e: print("Command Error: {}".format(e)) return False except AssertionError as e: raise e