2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-9 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../jucedemo_headers.h"
29 //==============================================================================
30 class InterprocessCommsDemo
: public Component
,
31 public ButtonListener
,
32 public ComboBoxListener
35 //==============================================================================
36 InterprocessCommsDemo()
37 : sendButton ("send", "Fires off the message"),
38 modeLabel (String::empty
, "Mode:"),
39 pipeLabel (String::empty
, "Pipe Name:"),
40 numberLabel (String::empty
, "Socket Port:"),
41 hostLabel (String::empty
, "Socket Host:")
43 setName ("Interprocess Communication");
45 server
= new DemoInterprocessConnectionServer (*this);
47 // create all our UI bits and pieces..
48 addAndMakeVisible (&modeSelector
);
49 modeSelector
.setBounds (100, 25, 200, 24);
50 modeLabel
.attachToComponent (&modeSelector
, true);
52 modeSelector
.addItem ("(Disconnected)", 8);
53 modeSelector
.addSeparator();
54 modeSelector
.addItem ("Named pipe (listening)", 1);
55 modeSelector
.addItem ("Named pipe (connect to existing pipe)", 5);
56 modeSelector
.addSeparator();
57 modeSelector
.addItem ("Socket (listening)", 2);
58 modeSelector
.addItem ("Socket (connect to existing socket)", 6);
60 modeSelector
.setSelectedId (8);
61 modeSelector
.addListener (this);
63 addAndMakeVisible (&pipeName
);
64 pipeName
.setBounds (100, 60, 130, 24);
65 pipeName
.setMultiLine (false);
66 pipeName
.setText ("juce demo pipe");
67 pipeLabel
.attachToComponent (&pipeName
, true);
69 addAndMakeVisible (&socketNumber
);
70 socketNumber
.setBounds (350, 60, 80, 24);
71 socketNumber
.setMultiLine (false);
72 socketNumber
.setText ("12345");
73 socketNumber
.setInputRestrictions (5, "0123456789");
74 numberLabel
.attachToComponent (&socketNumber
, true);
76 addAndMakeVisible (&socketHost
);
77 socketHost
.setBounds (530, 60, 130, 24);
78 socketHost
.setMultiLine (false);
79 socketHost
.setText ("localhost");
80 socketNumber
.setInputRestrictions (512);
81 hostLabel
.attachToComponent (&socketHost
, true);
83 addChildComponent (&sendText
);
84 sendText
.setBounds (30, 120, 200, 24);
85 sendText
.setMultiLine (false);
86 sendText
.setReadOnly (false);
87 sendText
.setText ("testing 1234");
89 addChildComponent (&sendButton
);
90 sendButton
.setBounds (240, 120, 200, 24);
91 sendButton
.changeWidthToFitText();
92 sendButton
.addListener (this);
94 addChildComponent (&incomingMessages
);
95 incomingMessages
.setReadOnly (true);
96 incomingMessages
.setMultiLine (true);
97 incomingMessages
.setBounds (30, 150, 500, 250);
99 // call this to set up everything's state correctly.
103 ~InterprocessCommsDemo()
108 void buttonClicked (Button
* button
)
110 if (button
== &sendButton
)
112 // The send button has been pressed, so write out the contents of the
113 // text box to the socket or pipe, depending on which is active.
114 const String
text (sendText
.getText());
115 MemoryBlock
messageData (text
.toUTF8(), text
.getNumBytesAsUTF8());
117 for (int i
= activeConnections
.size(); --i
>= 0;)
119 if (! activeConnections
[i
]->sendMessage (messageData
))
121 // the write failed, so indicate that the connection has broken..
122 appendMessage ("send message failed!");
128 void comboBoxChanged (ComboBox
*)
130 // This is called when the user picks a different mode from the drop-down list..
131 const int modeId
= modeSelector
.getSelectedId();
137 open ((modeId
& 2) != 0,
142 //==============================================================================
143 // Just closes any connections that are currently open.
147 activeConnections
.clear();
149 // Reset the UI stuff to a disabled state.
150 sendText
.setVisible (false);
151 sendButton
.setVisible (false);
152 incomingMessages
.setText (String::empty
, false);
153 incomingMessages
.setVisible (true);
156 "To demonstrate named pipes, you'll need to run two instances of the JuceDemo application on this machine. On "
157 "one of them, select \"named pipe (listening)\", and then on the other, select \"named pipe (connect to existing pipe)\". Then messages that you "
158 "send from the 'sender' app should appear on the listener app. The \"pipe name\" field lets you choose a name for the pipe\n\n"
159 "To demonstrate sockets, you can either run two instances of the app on the same machine, or on different "
160 "machines on your network. In each one enter a socket number, then on one of the apps, select the "
161 "\"Socket (listening)\" mode. On the other, enter the host address of the listening app, and select \"Socket (connect to existing socket)\". "
162 "Messages should then be be sent between the apps in the same way as through the named pipes.");
165 void open (bool asSocket
, bool asSender
)
169 // Make the appropriate bits of UI visible..
170 sendText
.setVisible (true);
171 sendButton
.setVisible (true);
173 incomingMessages
.setText (String::empty
, false);
174 incomingMessages
.setVisible (true);
176 // and try to open the socket or pipe...
177 bool openedOk
= false;
181 // if we're connecting to an existing server, we can just create a connection object
183 ScopedPointer
<DemoInterprocessConnection
> newConnection (new DemoInterprocessConnection (*this));
187 openedOk
= newConnection
->connectToSocket (socketHost
.getText(),
188 socketNumber
.getText().getIntValue(),
193 openedOk
= newConnection
->connectToPipe (pipeName
.getText());
197 activeConnections
.add (newConnection
.release());
201 // if we're starting up a server, we need to tell the server to start waiting for
202 // clients to connect. It'll then create connection objects for us when clients arrive.
205 openedOk
= server
->beginWaitingForSocket (socketNumber
.getText().getIntValue());
208 appendMessage ("Waiting for another app to connect to this socket..");
212 ScopedPointer
<DemoInterprocessConnection
> newConnection (new DemoInterprocessConnection (*this));
214 openedOk
= newConnection
->createPipe (pipeName
.getText());
218 appendMessage ("Waiting for another app to connect to this pipe..");
219 activeConnections
.add (newConnection
.release());
226 modeSelector
.setSelectedId (8);
228 AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon
,
229 "Interprocess Comms Demo",
230 "Failed to open the socket or pipe...");
234 void appendMessage (const String
& message
)
236 incomingMessages
.setCaretPosition (INT_MAX
);
237 incomingMessages
.insertTextAtCaret (message
+ "\n");
238 incomingMessages
.setCaretPosition (INT_MAX
);
241 //==============================================================================
242 class DemoInterprocessConnection
: public InterprocessConnection
245 DemoInterprocessConnection (InterprocessCommsDemo
& owner_
)
246 : InterprocessConnection (true),
249 static int totalConnections
= 0;
250 ourNumber
= ++totalConnections
;
253 void connectionMade()
255 owner
.appendMessage ("Connection #" + String (ourNumber
) + " - connection started");
258 void connectionLost()
260 owner
.appendMessage ("Connection #" + String (ourNumber
) + " - connection lost");
263 void messageReceived (const MemoryBlock
& message
)
265 owner
.appendMessage ("Connection #" + String (ourNumber
) + " - message received: " + message
.toString());
269 InterprocessCommsDemo
& owner
;
273 //==============================================================================
274 class DemoInterprocessConnectionServer
: public InterprocessConnectionServer
277 DemoInterprocessConnectionServer (InterprocessCommsDemo
& owner_
)
282 InterprocessConnection
* createConnectionObject()
284 DemoInterprocessConnection
* newConnection
= new DemoInterprocessConnection (owner
);
286 owner
.activeConnections
.add (newConnection
);
287 return newConnection
;
291 InterprocessCommsDemo
& owner
;
294 OwnedArray
<DemoInterprocessConnection
, CriticalSection
> activeConnections
;
298 ComboBox modeSelector
;
299 TextButton sendButton
;
300 TextEditor sendText
, incomingMessages
, pipeName
, socketNumber
, socketHost
;
301 Label modeLabel
, pipeLabel
, numberLabel
, hostLabel
;
303 ScopedPointer
<DemoInterprocessConnectionServer
> server
;
305 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InterprocessCommsDemo
);
309 //==============================================================================
310 Component
* createInterprocessCommsDemo()
312 return new InterprocessCommsDemo();