Skip to content

Commit

Permalink
Feature complete: /effect/xy_pos and open-stage-control demo OSC sender
Browse files Browse the repository at this point in the history
  • Loading branch information
goodtimes-code committed Dec 26, 2023
1 parent d58f070 commit 640128d
Show file tree
Hide file tree
Showing 7 changed files with 446 additions and 45 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
venv
osc-senders/max-for-live-device/demo1/Backup
dist
log.txt
log.txt
demoshows
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Preamble
osc2laser (*OSC to laser*) is a completely free, open source, solution to **create stunning lasershows** - live or pre-programmed by timeline.

It enables you to simply control your showlasers via any OSC-compatible software (Ableton Live, TouchOSC, Vezér,...).
It enables you to simply control your showlasers via any OSC-compatible software.

![Demo](osc-senders/max-for-live-device/doc/demo1.gif)

Expand All @@ -27,6 +27,7 @@ This projects is in an early stage to get feedback and to urgently find more con
- Any supported Laser DAC:
- [Helios Laser DAC](https://bitlasers.com/helios-laser-dac/)
- Any software for sending OSC commands like:
- [open-stage-control](https://openstagecontrol.ammd.net/)
- [Ableton Live](https://www.ableton.com/live/)
- [Vezér](https://imimot.com/vezer/)
- [TouchOSC](https://hexler.net/touchosc)
Expand Down Expand Up @@ -56,6 +57,14 @@ This starts an OSC server on *localhost* at UDP port *2345*.
See *config_laser1.txt* for more optional settings.

## OSC sender
### open-stage-control
![Demo](osc-senders/open-stage-control/doc/open-stage-control-demo.gif)

1. [Download](https://openstagecontrol.ammd.net/download/) and install software.
2. Run and open profile *osc-senders/open-stage-control/osc2laser-client.config*.
3. Click *play* icon.
4. Open session *osc-senders/open-stage-control/osc2laser-template.config*.

### Max for Live device
![Demo](osc-senders/max-for-live-device/doc/setup.gif)

Expand All @@ -78,15 +87,14 @@ See *config_laser1.txt* for more optional settings.
- 5 - green static circle
- /effect/x_pos and /effect/x_pos
- -4095 to 4095: move X or Y position of laserobject
- /effect/xy_pos
- (-4095 to 4095, -4095 to 4095): move X and Y position of laserobject at once
- /effect/rgb_intensity
- 0 to 255: brightness of the RGB colors

# Roadmap
This is what needs to be worked on.

As a user, feel free to create any issue.

If you are Python developer, feel free to create a pull request.
As a developer, feel free to commit your changes via pull request.

## OSC receiver
- More binary releases
Expand Down
30 changes: 15 additions & 15 deletions osc-receiver/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,29 +81,29 @@ def __init__(self, from_point, to_point, group = 0):

class StaticCircle(LaserObject):
def __init__(self, center_x, center_y, radius, r, g, b, group=0):
import math
super().__init__()

self.group = group
self.point_list = []
self.effects = []

# the lower this value the higher quality the circle is with more points generated
step_size = 0.1
# Number of points to create the circle
points_count = 100 # This can be adjusted for smoother circles

# generated vertices
points_count = int(2 * math.pi / step_size) + 1

# calculate points
t = 0
i = 0
first_x = int(round(radius * math.cos(0) + center_x, 0))
first_y = int(round(radius * math.sin(0) + center_y, 0))
while t < 2 * math.pi:
laser_point = LaserPoint(int(round(radius * math.cos(t) + center_x, 0)), int(round(radius * math.sin(t) + center_y, 0)))
# Calculate the angle step size
step_size = 2 * math.pi / points_count

# Create points
for i in range(points_count + 1): # +1 to close the circle
t = step_size * i
x = int(round(radius * math.cos(t) + center_x, 0))
y = int(round(radius * math.sin(t) + center_y, 0))
laser_point = LaserPoint(x, y)
laser_point.set_color(r, g, b)
self.point_list.append(laser_point)
t += step_size
i += 1

# Ensure the last point is the same as the first to close the circle
self.point_list.append(self.point_list[0])


class StaticWave(LaserObject):
Expand Down
53 changes: 29 additions & 24 deletions osc-receiver/osc_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,35 @@ def handle_osc_message(address, *args):
logging.error(f'[OSC] Error while adding new laser object: {e}')

elif address.startswith("/effect/"):
pos = int(args[0])
effect_names = {
"/effect/x_pos": "X_POS",
"/effect/y_pos": "Y_POS",
"/effect/rgb_intensity": "RGB_INTENSITY"
}
effect_name = effect_names.get(address, "UNKNOWN_EFFECT")
if global_data.config['logging']['osc_server_effect_handling'] == 'yes':
logging.info(f"[OSC] Handling effect {effect_name}: {pos}")
if address == "/effect/xy_pos":
# Handle the combined XY position message
x_pos, y_pos = int(args[0]), int(args[1])
handle_effect("X_POS", x_pos)
handle_effect("Y_POS", y_pos)
else:
# Handle other effect messages
pos = int(args[0])
effect_names = {
"/effect/x_pos": "X_POS",
"/effect/y_pos": "Y_POS",
"/effect/rgb_intensity": "RGB_INTENSITY"
}
effect_name = effect_names.get(address, "UNKNOWN_EFFECT")
handle_effect(effect_name, pos)

for visible_laser_object in global_data.visible_laser_objects:
if visible_laser_object.group == 0:
if not visible_laser_object.has_effect(effect_name):
effect = Effect(effect_name, pos)
visible_laser_object.effects.append(effect)
else:
for effect in visible_laser_object.effects:
if effect.name == effect_name:
effect.level = pos
def handle_effect(effect_name, pos):
if global_data.config['logging']['osc_server_effect_handling'] == 'yes':
logging.info(f"[OSC] Handling effect {effect_name}: {pos}")

for visible_laser_object in global_data.visible_laser_objects:
if visible_laser_object.group == 0:
if not visible_laser_object.has_effect(effect_name):
effect = Effect(effect_name, pos)
visible_laser_object.effects.append(effect)
else:
for effect in visible_laser_object.effects:
if effect.name == effect_name:
effect.level = pos


def process_osc_input():
Expand All @@ -57,6 +67,7 @@ def process_osc_input():
disp.map("/laserobject", handle_osc_message)
disp.map("/effect/x_pos", handle_osc_message)
disp.map("/effect/y_pos", handle_osc_message)
disp.map("/effect/xy_pos", handle_osc_message) # Added mapping for /effect/xy_pos
disp.map("/effect/rgb_intensity", handle_osc_message)

server = osc_server.ThreadingOSCUDPServer(
Expand Down Expand Up @@ -104,9 +115,3 @@ def setup():
]

setup()

# Test
#print("[OSC] Show test laser object...")
#laser_object = global_data.NOTE_LASEROBJECT_MAPPING[0][1]
#laser_object.group = 0
#global_data.visible_laser_objects.append(laser_object)
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions osc-senders/open-stage-control/osc2laser-client.config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"debug":true,"send":["localhost:2345"]}

0 comments on commit 640128d

Please sign in to comment.