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 |