Implementing for ptsl in progress
This commit is contained in:
15
__init__.py
15
__init__.py
@@ -1,19 +1,20 @@
|
|||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from .operator_protools_export import ProToolsExport
|
from .operator_protools_export import SendToProTools
|
||||||
|
|
||||||
|
|
||||||
def export_pt_menu_callback(self, _):
|
def export_pt_menu_callback(self, _):
|
||||||
self.layout.operator(ProToolsExport.bl_idname, text="Send to Pro Tools")
|
layout = self.layout
|
||||||
|
layout.separator()
|
||||||
|
layout.operator(SendToProTools.bl_idname, text="Send to Pro Tools")
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
bpy.utils.register_class(ProToolsExport)
|
bpy.utils.register_class(SendToProTools)
|
||||||
bpy.types.TOPBAR_MT_file_export.append(export_pt_menu_callback)
|
bpy.types.VIEW3D_MT_object.append(export_pt_menu_callback)
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
bpy.utils.unregister_class(ProToolsExport)
|
bpy.utils.unregister_class(SendToProTools)
|
||||||
|
bpy.types.VIEW3D_MT_object.remove(export_pt_menu_callback)
|
||||||
bpy.types.TOPBAR_MT_file_export.remove(export_pt_menu_callback)
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,23 @@ license = [
|
|||||||
]
|
]
|
||||||
website = "https://git.squad51.us/jamie/soundobjects_blender_addon"
|
website = "https://git.squad51.us/jamie/soundobjects_blender_addon"
|
||||||
platforms = ["macos-arm64", "windows-x64"]
|
platforms = ["macos-arm64", "windows-x64"]
|
||||||
|
wheels = [
|
||||||
|
'./wheels/grpcio-1.74.0-cp311-cp311-macosx_11_0_universal2.whl',
|
||||||
|
'./wheels/grpcio-1.74.0-cp311-cp311-win_amd64.whl',
|
||||||
|
'./wheels/iniconfig-2.3.0-py3-none-any.whl',
|
||||||
|
'./wheels/packaging-25.0-py3-none-any.whl',
|
||||||
|
'./wheels/pluggy-1.6.0-py3-none-any.whl',
|
||||||
|
'./wheels/protobuf-6.31.1-cp39-abi3-macosx_10_9_universal2.whl',
|
||||||
|
'./wheels/protobuf-6.31.1-cp310-abi3-win_amd64.whl',
|
||||||
|
'./wheels/py_ptsl-600.1.0-py3-none-any.whl',
|
||||||
|
'./wheels/pygments-2.19.2-py3-none-any.whl',
|
||||||
|
'./wheels/pytest-8.4.2-py3-none-any.whl'
|
||||||
|
]
|
||||||
|
|
||||||
[permissions]
|
[permissions]
|
||||||
network = "Communicates with Pro Tools via RPC, only localhost"
|
network = "Communicates with Pro Tools via RPC, only localhost"
|
||||||
|
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
paths_exclude_pattern = [
|
paths_exclude_pattern = [
|
||||||
"__pycache__/",
|
"__pycache__/",
|
||||||
|
|||||||
22
intern/pro_tools.py
Normal file
22
intern/pro_tools.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import bpy
|
||||||
|
import ptsl
|
||||||
|
from ptsl import PTSL_pb2 as pt
|
||||||
|
|
||||||
|
def send_to_pro_tools(speakers: list[bpy.types.Object],
|
||||||
|
room_size: float) -> bool:
|
||||||
|
try:
|
||||||
|
client = ptsl.Client(company_name="Squad 51",
|
||||||
|
application_name="Send to Pro Tools Blender Extension")
|
||||||
|
|
||||||
|
for speaker in speakers:
|
||||||
|
assert speaker.data
|
||||||
|
result = client.run_command(pt.CId_CreateNewTracks, {
|
||||||
|
{'number_of_tracks': 1,
|
||||||
|
'track_name': speaker.data.name}
|
||||||
|
})
|
||||||
|
|
||||||
|
client.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
except:
|
||||||
|
return False
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import bpy
|
|
||||||
|
|
||||||
from bpy.types import Operator
|
|
||||||
from bpy.props import BoolProperty, StringProperty, EnumProperty, FloatProperty
|
|
||||||
|
|
||||||
from .intern.add_sound_to_meshes import add_speakers_to_meshes, TriggerMode
|
|
||||||
|
|
||||||
class AddSoundToMeshOperator(Operator):
|
|
||||||
"""Add a speaker to each selected object"""
|
|
||||||
bl_idname = "object.add_speakers_to_obj"
|
|
||||||
bl_label = "Add Sounds to Meshes"
|
|
||||||
|
|
||||||
TRIGGER_OPTIONS = (
|
|
||||||
(TriggerMode.START_FRAME,
|
|
||||||
"Start Frame",
|
|
||||||
"Sound will play on the first frame of the animation"),
|
|
||||||
(TriggerMode.MIN_DISTANCE,
|
|
||||||
"Minimum Distance",
|
|
||||||
"Sound will play when the object is closest to the camera"),
|
|
||||||
(TriggerMode.RANDOM,
|
|
||||||
"Random",
|
|
||||||
"Sound will play exactly once, at a random time"),
|
|
||||||
(TriggerMode.RANDOM_GAUSSIAN,
|
|
||||||
"Random (Gaussian)",
|
|
||||||
"Sound will play exactly once, at a guassian random time with " +
|
|
||||||
"stdev of 1 and mean in the middle of the animation")
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
sounds_avail = bpy.data.sounds
|
|
||||||
return len(context.selected_objects) > 0 and len(sounds_avail) > 0
|
|
||||||
|
|
||||||
use_sounds: StringProperty(
|
|
||||||
name="Sound Prefix",
|
|
||||||
description="Sounds having names starting with thie field will be assigned randomly to each speaker"
|
|
||||||
)
|
|
||||||
|
|
||||||
sync_audio_peak: BoolProperty(
|
|
||||||
name="Sync Audio Peak",
|
|
||||||
default=True,
|
|
||||||
description="Synchronize speaker audio to loudest peak instead of beginning of file"
|
|
||||||
)
|
|
||||||
|
|
||||||
trigger_mode: EnumProperty(
|
|
||||||
items=TRIGGER_OPTIONS,
|
|
||||||
name="Trigger",
|
|
||||||
description="Select when each sound will play",
|
|
||||||
default=TriggerMode.MIN_DISTANCE,
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
gaussian_stddev: FloatProperty(
|
|
||||||
name="Gaussian StDev",
|
|
||||||
description="Standard Deviation of Gaussian random time",
|
|
||||||
default=1.,
|
|
||||||
min=0.001,
|
|
||||||
max=6.,
|
|
||||||
)
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
|
||||||
return context.window_manager.invoke_props_dialog(self)
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
|
|
||||||
add_speakers_to_meshes(bpy.context.selected_objects, bpy.context,
|
|
||||||
sound=None,
|
|
||||||
sound_name_prefix=self.use_sounds,
|
|
||||||
trigger_mode=self.trigger_mode,
|
|
||||||
sync_peak=self.sync_audio_peak,
|
|
||||||
gaussian_stddev=self.gaussian_stddev)
|
|
||||||
return {'FINISHED'}
|
|
||||||
@@ -1,52 +1,40 @@
|
|||||||
from bpy_extras.io_utils import ExportHelper
|
import bpy
|
||||||
from bpy.props import StringProperty, BoolProperty, FloatProperty, IntProperty
|
|
||||||
from bpy.types import Operator
|
|
||||||
|
|
||||||
from .intern.generate_adm import generate_adm
|
from .intern import pro_tools
|
||||||
|
|
||||||
|
def filter_speakers(objs: list[bpy.types.Object]) -> list[bpy.types.Object]:
|
||||||
|
return [s for s in objs if s.type == 'SPEAKER']
|
||||||
|
|
||||||
class ProToolsExport(Operator, ExportHelper):
|
class SendToProTools(bpy.types.Operator):
|
||||||
"""
|
"Send Audio Objects to Pro Tools"
|
||||||
Export audio objects to a Pro Tools session
|
|
||||||
"""
|
bl_idname = "object.pro_tools_live"
|
||||||
bl_idname = "export.pro_tools_live" # important since its how
|
|
||||||
bl_label = "Send Audio Objects to Pro Tools"
|
bl_label = "Send Audio Objects to Pro Tools"
|
||||||
filepath: str
|
|
||||||
filename_ext = ".wav"
|
|
||||||
|
|
||||||
filter_glob = StringProperty(
|
room_size: bpy.props.FloatProperty(
|
||||||
default="*.wav",
|
|
||||||
options={'HIDDEN'},
|
|
||||||
maxlen=255, # Max internal buffer length, longer would be clamped.
|
|
||||||
)
|
|
||||||
|
|
||||||
room_size = FloatProperty(
|
|
||||||
default=1.0,
|
|
||||||
name="Room Size",
|
name="Room Size",
|
||||||
description="Distance from the lens to the front room boundary",
|
description="Distance from the lens to the front room boundary",
|
||||||
|
default=1.0,
|
||||||
min=0.001,
|
min=0.001,
|
||||||
step=1,
|
step=1,
|
||||||
unit='LENGTH'
|
unit='LENGTH'
|
||||||
)
|
)
|
||||||
|
|
||||||
max_objects = IntProperty(
|
@classmethod
|
||||||
name="Max Objects",
|
def poll(cls, context):
|
||||||
description="Maximum number of object tracks to create",
|
return len(filter_speakers(context.selected_objects)) > 0 and \
|
||||||
default=24,
|
bpy.app.online_access
|
||||||
min=0,
|
|
||||||
max=118
|
|
||||||
)
|
|
||||||
|
|
||||||
create_bed = BoolProperty(
|
def invoke(self, context, event):
|
||||||
name="Create 7.1 Bed",
|
wm = context.window_manager
|
||||||
description="Create a bed for all sounds not included on object "
|
return wm.invoke_props_dialog(self, confirm_text="Send to Pro Tools")
|
||||||
"tracks",
|
|
||||||
default=False,
|
|
||||||
options={'HIDDEN'}
|
|
||||||
)
|
|
||||||
|
|
||||||
def execute(self, context) -> set:
|
def execute(self, context) -> set:
|
||||||
assert self.create_bed is False, "Create Bed is not supported"
|
if pro_tools.send_to_pro_tools(
|
||||||
|
filter_speakers(context.selected_objects),
|
||||||
return generate_adm(context, self.filepath, self.room_size,
|
self.room_size):
|
||||||
self.max_objects)
|
self.report({'INFO'}, "Speaker objects sent to Pro Tools")
|
||||||
|
return {'FINISHED'}
|
||||||
|
else:
|
||||||
|
self.report({'ERROR'}, "Could not connect to Pro Tools")
|
||||||
|
return {'FINISHED'}
|
||||||
|
|||||||
Reference in New Issue
Block a user