Stefan Schuermans commited on 2011-09-10 19:42:12
Showing 3 changed files, with 201 additions and 3 deletions.
... | ... |
@@ -3,6 +3,10 @@ Copyright (C) 2004-2011: Stefan Schuermans <stefan@schuermans.info> |
3 | 3 |
Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html |
4 | 4 |
a blinkenarea.org project |
5 | 5 |
|
6 |
+1.4.0 2011-09-10 |
|
7 |
+---------------- |
|
8 |
+added MCUF output feature |
|
9 |
+ |
|
6 | 10 |
1.3.9 2011-09-10 |
7 | 11 |
---------------- |
8 | 12 |
version information available in class file |
... | ... |
@@ -75,7 +75,8 @@ public class Blimp extends JApplet |
75 | 75 |
JFrame frame; //main window (if running as full application) |
76 | 76 |
Component dialogParent; //parent to use for dialogs |
77 | 77 |
JMenuBar menubar; //menubar in main window |
78 |
- JMenu menuFile, menuInfo, menuEdit, menuFrameSel, menuPlay, menuHelp; //menus |
|
78 |
+ JMenu menuFile, menuInfo, menuEdit, menuFrameSel, menuPlay; //menus |
|
79 |
+ JMenu menuOutput, menuHelp; |
|
79 | 80 |
JMenuItem menuFileNew, menuFileLoad, menuFileSave, menuFileSaveAs, menuFileQuit; |
80 | 81 |
JMenuItem menuInfoShow, menuInfoAdd, menuInfoDelete; |
81 | 82 |
JMenu menuEditResize, menuEditScale; |
... | ... |
@@ -87,6 +88,8 @@ public class Blimp extends JApplet |
87 | 88 |
JMenuItem menuEditImportImages, menuEditImportMovie; |
88 | 89 |
JMenuItem menuPlayStart, menuPlayStop; |
89 | 90 |
JCheckBoxMenuItem menuPlayBegin, menuPlayLoop; |
91 |
+ ButtonGroup groupOutput; |
|
92 |
+ JRadioButtonMenuItem menuOutputNone, menuOutputMcuf; |
|
90 | 93 |
JMenuItem menuHelpAbout; |
91 | 94 |
JPanel panel, panelStatus, panelMain, panelFrames, panelOuterFrame; //panels of main window |
92 | 95 |
JPanel panelMiddleFrame, panelFrame, panelDuration, panelColors; |
... | ... |
@@ -124,6 +127,7 @@ public class Blimp extends JApplet |
124 | 127 |
Color colors[]; //current colors |
125 | 128 |
ImageIcon iconsColor[], iconColorsColor; //color icons shown in color panel |
126 | 129 |
javax.swing.Timer timerPlay; //timer used for playing movies |
130 |
+ javax.swing.Timer timerOut; //timer used for output |
|
127 | 131 |
|
128 | 132 |
//file, movie, frame |
129 | 133 |
File curDir = null, curFile = null; //current directory and file |
... | ... |
@@ -132,6 +136,12 @@ public class Blimp extends JApplet |
132 | 136 |
BlinkenFrame curFrame = null; //current frame |
133 | 137 |
int frameSelStart = -1, frameSelEnd = -1; //selected frames (none selected yet) |
134 | 138 |
|
139 |
+ //output |
|
140 |
+ String outMcufDest = "127.0.0.1:2323"; //destination to send MCUF frames to |
|
141 |
+ InetAddress outMcufHost; //host part of destination |
|
142 |
+ int outMcufPort; //port part of destination |
|
143 |
+ DatagramSocket outMcufSock; // UDP socket to send MCUF output on |
|
144 |
+ |
|
135 | 145 |
//other variables |
136 | 146 |
boolean noRecurseZoomAspect = false; //set when changing zoom or aspect value per program to inhibit recursion triggered by events |
137 | 147 |
|
... | ... |
@@ -1080,6 +1090,113 @@ public class Blimp extends JApplet |
1080 | 1090 |
stateFrames( ); //value does not change, no event will be sent, execute callback by hand |
1081 | 1091 |
} |
1082 | 1092 |
|
1093 |
+ //"Output None" was chosen from menu |
|
1094 |
+ private void actionOutputNone( ) |
|
1095 |
+ { |
|
1096 |
+ //stop output timer |
|
1097 |
+ timerOut.stop( ); |
|
1098 |
+ |
|
1099 |
+ //close MCUF output |
|
1100 |
+ if( outMcufSock != null ) { |
|
1101 |
+ outMcufSock.close( ); |
|
1102 |
+ outMcufSock = null; |
|
1103 |
+ } |
|
1104 |
+ |
|
1105 |
+ //set status to no output |
|
1106 |
+ menuOutputNone.setSelected( true ); |
|
1107 |
+ labelStatus.setText( "output turned off..." ); |
|
1108 |
+ } |
|
1109 |
+ |
|
1110 |
+ //"Output Mcuf" was chosen from menu |
|
1111 |
+ private void actionOutputMcuf( ) |
|
1112 |
+ { |
|
1113 |
+ Object dest; |
|
1114 |
+ Pattern destPattern; |
|
1115 |
+ Matcher destMatcher; |
|
1116 |
+ String hostname; |
|
1117 |
+ int port; |
|
1118 |
+ InetAddress host; |
|
1119 |
+ DatagramSocket sock; |
|
1120 |
+ |
|
1121 |
+ // reset outputs |
|
1122 |
+ actionOutputNone( ); |
|
1123 |
+ |
|
1124 |
+ //ask for destination address |
|
1125 |
+ dest = JOptionPane.showInputDialog( dialogParent, |
|
1126 |
+ "Please enter the UDP destination port for the MCUF stream:\n\n" + |
|
1127 |
+ "The format is: <IP>:<port>\n", |
|
1128 |
+ "Blimp - Output MCUF...", |
|
1129 |
+ JOptionPane.QUESTION_MESSAGE, |
|
1130 |
+ null, null, outMcufDest ); |
|
1131 |
+ if( dest == null ) |
|
1132 |
+ { |
|
1133 |
+ //dialog was cancelled -> turn off output |
|
1134 |
+ actionOutputNone( ); |
|
1135 |
+ labelStatus.setText( "MCUF output: cancelled..." ); |
|
1136 |
+ return; |
|
1137 |
+ } |
|
1138 |
+ |
|
1139 |
+ //parse IP:port |
|
1140 |
+ destPattern = Pattern.compile( "^([-.a-zA-Z0-9]+):([0-9]+)$" ); |
|
1141 |
+ |
|
1142 |
+ //check format |
|
1143 |
+ if( ! (destMatcher = destPattern.matcher( dest.toString( ) )).find( ) ) |
|
1144 |
+ { |
|
1145 |
+ //invalid format -> turn off output |
|
1146 |
+ actionOutputNone( ); |
|
1147 |
+ labelStatus.setText( "MCUF output: invalid destination \"" + dest + "\" ..." ); |
|
1148 |
+ return; |
|
1149 |
+ } |
|
1150 |
+ hostname = destMatcher.group( 1 ); |
|
1151 |
+ port = Integer.parseInt( destMatcher.group( 2 ) ); |
|
1152 |
+ |
|
1153 |
+ //resolve hostname |
|
1154 |
+ try |
|
1155 |
+ { |
|
1156 |
+ host = InetAddress.getByName( hostname ); |
|
1157 |
+ } |
|
1158 |
+ catch( UnknownHostException e ) |
|
1159 |
+ { |
|
1160 |
+ //unknown hostname -> turn off output |
|
1161 |
+ actionOutputNone( ); |
|
1162 |
+ labelStatus.setText( "MCUF output: unknown hostname \"" + hostname + "\" ..." ); |
|
1163 |
+ return; |
|
1164 |
+ } |
|
1165 |
+ |
|
1166 |
+ // create socket |
|
1167 |
+ try |
|
1168 |
+ { |
|
1169 |
+ sock = new DatagramSocket( ); |
|
1170 |
+ } |
|
1171 |
+ catch( SocketException e ) |
|
1172 |
+ { |
|
1173 |
+ //cannot create socket -> turn off output |
|
1174 |
+ actionOutputNone( ); |
|
1175 |
+ labelStatus.setText( "MCUF output: cannot create socket..." ); |
|
1176 |
+ return; |
|
1177 |
+ } |
|
1178 |
+ |
|
1179 |
+ //remember new destination, host, port, socket |
|
1180 |
+ outMcufDest = dest.toString( ); |
|
1181 |
+ outMcufHost = host; |
|
1182 |
+ outMcufPort = port; |
|
1183 |
+ outMcufSock = sock; |
|
1184 |
+ |
|
1185 |
+ //set status to MCUF output |
|
1186 |
+ menuOutputMcuf.setSelected( true ); |
|
1187 |
+ labelStatus.setText( "MCUF output to \"" + dest + "\" ..." ); |
|
1188 |
+ |
|
1189 |
+ //output current frame |
|
1190 |
+ outFrame( ); |
|
1191 |
+ } |
|
1192 |
+ |
|
1193 |
+ //output timer elapsed |
|
1194 |
+ private void actionOutTimer( ) |
|
1195 |
+ { |
|
1196 |
+ //output current frame |
|
1197 |
+ outFrame( ); |
|
1198 |
+ } |
|
1199 |
+ |
|
1083 | 1200 |
//"Help About" was chosen from menu |
1084 | 1201 |
private void actionHelpAbout( ) |
1085 | 1202 |
{ |
... | ... |
@@ -1162,6 +1279,9 @@ public class Blimp extends JApplet |
1162 | 1279 |
//update frame |
1163 | 1280 |
frameEditor.setFrame( curFrame ); |
1164 | 1281 |
|
1282 |
+ //output new frame |
|
1283 |
+ outFrame( ); |
|
1284 |
+ |
|
1165 | 1285 |
//show duration |
1166 | 1286 |
showDuration( ); |
1167 | 1287 |
|
... | ... |
@@ -1855,6 +1975,12 @@ public class Blimp extends JApplet |
1855 | 1975 |
actionPlayStop( ); |
1856 | 1976 |
else if( e.getSource( ) == timerPlay ) |
1857 | 1977 |
actionPlayTimer( ); |
1978 |
+ else if( e.getSource( ) == menuOutputNone ) |
|
1979 |
+ actionOutputNone( ); |
|
1980 |
+ else if( e.getSource( ) == menuOutputMcuf ) |
|
1981 |
+ actionOutputMcuf( ); |
|
1982 |
+ else if( e.getSource( ) == timerOut ) |
|
1983 |
+ actionOutTimer( ); |
|
1858 | 1984 |
else if( e.getSource( ) == menuHelpAbout ) |
1859 | 1985 |
actionHelpAbout( ); |
1860 | 1986 |
else if( e.getSource( ) == textZoom ) |
... | ... |
@@ -2061,6 +2187,9 @@ public class Blimp extends JApplet |
2061 | 2187 |
public void blinkenFrameEditorFrameChanged( ) |
2062 | 2188 |
{ |
2063 | 2189 |
curMovieChanged = true; |
2190 |
+ |
|
2191 |
+ //output current frame |
|
2192 |
+ outFrame( ); |
|
2064 | 2193 |
} |
2065 | 2194 |
|
2066 | 2195 |
//the possibility to perfon an undo or redo operation changed |
... | ... |
@@ -2070,6 +2199,50 @@ public class Blimp extends JApplet |
2070 | 2199 |
buttonActionsRedo.setEnabled( canRedo ); |
2071 | 2200 |
} |
2072 | 2201 |
|
2202 |
+ //output current frame |
|
2203 |
+ private void outFrame( ) |
|
2204 |
+ { |
|
2205 |
+ //stop output timer |
|
2206 |
+ timerOut.stop( ); |
|
2207 |
+ |
|
2208 |
+ //exit if no frame |
|
2209 |
+ if( curFrame == null ) |
|
2210 |
+ return; |
|
2211 |
+ |
|
2212 |
+ //MCUF output |
|
2213 |
+ if( menuOutputMcuf.isSelected( ) ) |
|
2214 |
+ outMcuf( ); |
|
2215 |
+ |
|
2216 |
+ //re-output after 1 s |
|
2217 |
+ timerOut.setInitialDelay( 1000 ); |
|
2218 |
+ timerOut.restart( ); |
|
2219 |
+ } |
|
2220 |
+ |
|
2221 |
+ //output current frame via MCUF |
|
2222 |
+ private void outMcuf( ) |
|
2223 |
+ { |
|
2224 |
+ byte [] data; |
|
2225 |
+ DatagramPacket pack; |
|
2226 |
+ |
|
2227 |
+ // exit if nos socket |
|
2228 |
+ if( outMcufSock == null ) |
|
2229 |
+ return; |
|
2230 |
+ |
|
2231 |
+ //convert current frame into MCUF |
|
2232 |
+ data = curFrame.toNetwork( BlinkenConstants.BlinkenProtoMcuf ); |
|
2233 |
+ if( data == null || data.length == 0 ) |
|
2234 |
+ return; |
|
2235 |
+ |
|
2236 |
+ //send packet |
|
2237 |
+ pack = new DatagramPacket( data, data.length, outMcufHost, outMcufPort ); |
|
2238 |
+ try { |
|
2239 |
+ outMcufSock.send( pack ); |
|
2240 |
+ } |
|
2241 |
+ catch( java.io.IOException e ) |
|
2242 |
+ { |
|
2243 |
+ } |
|
2244 |
+ } |
|
2245 |
+ |
|
2073 | 2246 |
//entry point of main thread |
2074 | 2247 |
public void run( ) |
2075 | 2248 |
{ |
... | ... |
@@ -2303,6 +2476,22 @@ public class Blimp extends JApplet |
2303 | 2476 |
menuPlayLoop.setMnemonic( KeyEvent.VK_L ); |
2304 | 2477 |
menuPlayLoop.addActionListener( this ); |
2305 | 2478 |
menuPlay.add( menuPlayLoop ); |
2479 |
+ //output menu |
|
2480 |
+ menuOutput = new JMenu( "Output" ); |
|
2481 |
+ menuOutput.setMnemonic( KeyEvent.VK_O ); |
|
2482 |
+ menubar.add( menuOutput ); |
|
2483 |
+ groupOutput = new ButtonGroup( ); |
|
2484 |
+ menuOutputNone = new JRadioButtonMenuItem( "none", false ); |
|
2485 |
+ menuOutputNone.setMnemonic( KeyEvent.VK_N ); |
|
2486 |
+ menuOutputNone.addActionListener( this ); |
|
2487 |
+ menuOutput.add( menuOutputNone ); |
|
2488 |
+ groupOutput.add( menuOutputNone ); |
|
2489 |
+ menuOutputMcuf = new JRadioButtonMenuItem( "MCUF", false ); |
|
2490 |
+ menuOutputMcuf.setMnemonic( KeyEvent.VK_M ); |
|
2491 |
+ menuOutputMcuf.addActionListener( this ); |
|
2492 |
+ menuOutput.add( menuOutputMcuf ); |
|
2493 |
+ groupOutput.add( menuOutputMcuf ); |
|
2494 |
+ menuOutputNone.setSelected( true ); |
|
2306 | 2495 |
//help menu |
2307 | 2496 |
menuHelp = new JMenu( "Help" ); |
2308 | 2497 |
menuHelp.setMnemonic( KeyEvent.VK_H ); |
... | ... |
@@ -2670,6 +2859,11 @@ public class Blimp extends JApplet |
2670 | 2859 |
timerPlay.setRepeats( false ); |
2671 | 2860 |
timerPlay.stop( ); |
2672 | 2861 |
|
2862 |
+ //create output timer |
|
2863 |
+ timerOut = new javax.swing.Timer( 1000, this ); |
|
2864 |
+ timerOut.setRepeats( false ); |
|
2865 |
+ timerOut.stop( ); |
|
2866 |
+ |
|
2673 | 2867 |
//update display and controls |
2674 | 2868 |
setZoomAspect( ); |
2675 | 2869 |
showZoom( ); |
2676 | 2870 |