A newer version of Max is available. Click here to access the latest version of the Max documentation

Max Basic Tutorial 16: Remote Messaging

Tutorial 16: Remote Messaging

Introduction

So far in these tutorials, all messages between objects have been sent using patch cords. Here we investigate another way to transfer messages between objects – by using the remote messaging mechanism built into Max. There are specific objects for this called, send and receive, as well as methods for sending a message box's contents to an object. Finally, we use some objects that allow the storage of variable data and can share values throughout complex patches.

As our designs get more complex, we need to take advantage of more techniques to modularize and compartmentalize our patches, making them easier to understand, maintain and extend. When our patches contain a lot of objects, long winding patch cord connections can cause unnecessary visual complexity. Using tools that allow message passing without patch cords can clean up our patches without changing how they operate.

To open the tutorial patch, click on the Open Tutorial button in the upper right-hand corner of the documentation window.

Playing with send and receive

Technical note: Many of the objects in the tutorial patch are colored to help you find related pairs of objects, but color has nothing to do with routing messages.

The most common way to send messages without patch cords is through the use of the send and receive objects. If we look at the tutorial patcher, the top left part of the patch shows a pairing of send and receive objects that pass an integer value. When we change the top number box, the integer value is passed to the send fred object. This value is “broadcast” throughout the Max environment, and can be “received” by any receive object with the name fred. In this case, the receive fred object immediately below gets the message, and outputs it to be displayed in the attached number box.

Since a message is broadcast by name, any receive object sharing the send object's name can receive the message. Hence, you can have more than one receive object for a message, and more than one send object sending messages using a single name. In our test patch, the slider system connected to the send bob object does just that – it sends the value (set with either the slider or the number box) to all receive objects of bob messages. At the lower right of the patch are two different receive bob objects: one connected to a slider system, while another is connected directly to a number box. Changing the top slider value changes both of the receiving values simultaneously.

When working with pairs of send and receive objects, it’s important to realize that the message will be grabbed by any receive object anywhere in the Max environment – even in another patcher. To test this, open a new patcher (selecting New Patcher from the File menu). Add a new object, and enter receive bob. Connect the output of the receive object to a number box, then return to the tutorial patch. If you change our test slider, you will see the output received in the new patch as well as all other receive bob objects in the main patcher.

When working with other people’s patches, you may see objects named “s” or “r”. Since the send and receive objects are so popular, they have alias (or shorthand) names of “s” and “r” respectively. In addition to being easier to type, these shortcut names also allow you to keep the object small!

Working with ; and forward

Another common use of remote messaging is to send the contents of a message box to one or more receive objects. Rather than always having to connect message boxes to send objects, there is a special format of the message box that can directly send messages to receive objects. This involves placing a semicolon (;) and the name of a receive object in front of the message. Thus, ; bob 155 is the equivalent of sending the value 155 to any receive object named bob.

The large gold message box at the bottom-left of the patch is an example of direct message sending. Four messages are generated: two are sent to lcd1 destinations, and two are sent to lcd2 destinations. If you click on the message box, you will see that the two lcd objects each receive the appropriate draw commands through their respective receive objects - the top lcd (lcd1) draws a blue circle; the bottom lcd (lcd2) draws a green rectangle.

Another common need we might have is to send messages to one of several destinations based on some logical criteria. This can be done using switching logic (e.g. the gate object connected to different send objects). However, we can also use the forward object to route messages to selected locations. Just above our green message box example is a forward object with supporting logic.

You can select which named destination should receive the messages from forward: the send message, sent to the forward object, will set the destination name for any incoming messages. Once a destination has been set, all messages will be routed appropriately. If we click on the send lcd1 message, changes to the number box will cause a colored rectangle to be created in the first lcd object. If we click on the send lcd2 message, it changes the output destination of the forward object to the receive lcd2 object. Now, any changes to the number box will cause the creation of a rectangle in the second lcd object.

By a similar token, a receive object with no arguments can be used to receive messages from any named send or appropriately configured forward or message box. The set message to the receive object allows it to "switch names", so to speak, so that it can listen to different parts of the patcher. Next to our forward object is one such receive object. By switching it between listening to bob and fred (using the message boxes) and then manipulating the number box and slider object sending to those names, we can see how this works. Setting the receive to a name that doesn't exist (e.g. none) will disconnect it from listening to anything in our patch. Note that in order for a receive object to be "switchable", it needs to be created without an argument (otherwise it has no inlet).

The int, float, and value objects

Sometimes, when working with patch programming, we need a place to stash a value until we need to use it. While we could use integer and floating-point number boxes, those objects have the possibility of having the user change the value through their UI. In order to provide simple variable storage and recall, there are a set of objects specifically used for this purpose. The int and float objects can act as temporary storage of values; values coming in the left inlet are stored and sent out the outlet immediately, while values coming in the right inlet are stored without output. If you want to retrieve the value stored in an int or float object, you need to send a bang message (such as from a button object) into the left inlet.

One of the advantages of the int and float objects is that you can initialize the value without using any other message. The argument provided with the object gives it an initial value; there is no need to set these up with loadbang messages or other functions. If we look at the int and float objects to the right of our patch, we can see how they work. They do not send their value when the patch is loaded; sending a bang into them with the button objects outputs their initialized value. Once we start entering numbers into them from the number boxes, those new values are stored inside the objects until we bang them again.

In our patch, just below the int and float object, we find a pair of objects called value. The value object is like a combination of an int/float object and a send/receive pair – each of the value objects has a name (in this case, joe), and any values placed in one of the objects is shared with all of the other value objects with that name. One thing to notice is that sending a message into a value object does not trigger output – you need to explicitly force output by sending a bang message to the object. In our test patch, change the value of one object then bang the other: you will see that the value is magically transferred from one to the other.

Unlike the int and float objects, the value object can take messages of any type; symbols, integers and floats can all be stored by the value object, as can a list. While this is convenient, it also means that you need to be careful about the objects that you connect to a value object to display the output. Our test patch has number boxes connected to the value objects; however, it might be better to connect a message object (by the right inlet) or other display object that can accept a diverse set of values.

Summary

Being able to send messages without having to connect patch cords can give us more flexibility in patch layout, and can also allow us to produce and route messages throughout very complex patches. The send and receive objects are the most common way of passing messages around a patch, but the use of ; notation in message boxes and the use of the forward object for routing can help minimize the visual complexity of our work. Finally, we saw how values can be stored in the int and float objects, and how a value object can be used to both store and forward data that is sent into it. All of these objects and techniques are important for working with complex patching systems.

See Also

Name Description
send Send messages without patch cords
receive Receive messages without patch cords
forward Send messages to specified receive objects
int Store an integer value
float Store a decimal number
value Share data between other value objects