View Javadoc

1   /*
2   * The contents of this file are subject to the BT "ZEUS" Open Source 
3   * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file 
4   * except in compliance with the Licence. You may obtain a copy of the Licence
5   * from $ZEUS_INSTALL/licence.html or alternatively from
6   * http://www.labs.bt.com/projects/agents/zeus/licence.htm
7   * 
8   * Except as stated in Clause 7 of the Licence, software distributed under the
9   * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or 
10  * implied. See the Licence for the specific language governing rights and 
11  * limitations under the Licence.
12  * 
13  * The Original Code is within the package zeus.*.
14  * The Initial Developer of the Original Code is British Telecommunications
15  * public limited company, whose registered office is at 81 Newgate Street, 
16  * London, EC1A 7AJ, England. Portions created by British Telecommunications 
17  * public limited company are Copyright 1996-9. All Rights Reserved.
18  * 
19  * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20  */
21  
22  
23  
24  /********************************************************************
25   *                    Video Tools for Zeus                         *
26   *   Provides functionality to use record and playback feature     *
27   *******************************************************************/
28  
29  package zeus.visualiser.basic;
30  
31  import java.util.*;
32  import java.awt.*;
33  import java.awt.event.*;
34  import javax.swing.*;
35  
36  import zeus.util.*;
37  import zeus.concepts.*;
38  import zeus.gui.*;
39  import zeus.actors.*;
40  import zeus.visualiser.*;
41  
42  
43  public abstract class VideoTool extends BasicTool {
44    protected static final int PLAYBACK = 0;
45    protected static final int ONLINE   = 1;
46  
47    protected static final int FORWARD  = 0;
48    protected static final int BACKWARD = 1;
49  
50    private NumberDialog                    number_dialog = null;
51    private EditableMultipleSelectionDialog dialog = null;
52    private EditableDoubleSelectionDialog   proxy_dialog = null;
53  
54    protected VideoToolBar videoToolbar = null;
55    protected StateInfo    state;
56  
57    public VideoTool(AgentContext context, VisualiserModel model) {
58       super(context,model);
59       state = new StateInfo();
60       state.animating = true;
61       state.mode = ONLINE;
62       state.saving = false;
63       videoToolbar = new VideoToolBar();
64    }
65  
66    public void Exit() {
67       this.setVisible(false);
68       removeSubscriptions();
69       if ( state.player != null ) {
70          state.player.terminate();
71          state.player = null;
72       }
73       this.dispose();
74    }
75  
76    protected boolean stopPlayback() {
77       if ( state.mode == PLAYBACK ) {
78          int result = JOptionPane.showConfirmDialog(this,
79             "There is an open database connection\nClose connection?",
80             "Warning", JOptionPane.YES_NO_OPTION);
81          if ( result == JOptionPane.YES_OPTION )
82             Close();
83       }
84       return state.mode == ONLINE;
85    }
86  
87    public void Sessions() {
88       /***
89         send a query to a DbProxy to return the names of
90         saved sessions belonging to this agent
91       */
92  
93       if ( !hubOK() ) return;
94  
95       String[] db_servers = model.getDbProxys();
96       if ( dialog == null ) {
97          dialog = new EditableMultipleSelectionDialog(this,"Select DbProxy");
98          dialog.setLocationRelativeTo(this);
99       }
100 
101      dialog.setListData(db_servers);
102      Object[] selection = dialog.getSelection();
103 
104      if ( selection != null ) {
105         model.addDbProxys(Misc.stringArray(dialog.getListData()));
106 
107         query("db_sessions " + getClass().getName(),
108            Misc.stringArray(selection), "db_sessions");
109      }
110   }
111 
112   public void Delete() {
113      /***
114         send a request to a DbProxy to delete the specified
115         saved session belonging to this agent
116      */
117 
118      if ( !hubOK() ) return;
119 
120      String sessionType = this.getClass().getName();
121      Hashtable input = model.getDbSessions(sessionType);
122      if ( proxy_dialog == null ) {
123         proxy_dialog = new EditableDoubleSelectionDialog(this,
124 	   "Select DbProxy & Session Name","DbProxy Agent","Session Name");
125         proxy_dialog.setLocationRelativeTo(this);
126      }
127 
128      proxy_dialog.setListData(input);
129      Object[] selection = proxy_dialog.getSelection();
130 
131      if ( selection != null ) {
132         Hashtable output = proxy_dialog.getListData();
133 	model.addDbSessions(sessionType,output);
134 
135         request("db_delete " + sessionType + " " + selection[1],
136            (String)selection[0], "db_delete");
137      }
138   }
139 
140   public void Purge() {
141      /***
142         send a request to a DbProxy to purge all
143         saved sessions belonging to this agent
144      */
145 
146      if ( !hubOK() ) return;
147 
148      String[] db_servers = model.getDbProxys();
149      if ( dialog == null ) {
150         dialog = new EditableMultipleSelectionDialog(this,"Select DbProxy");
151         dialog.setLocationRelativeTo(this);
152      }
153 
154      dialog.setListData(db_servers);
155      Object[] selection = dialog.getSelection();
156 
157      if ( selection != null ) {
158         model.addDbProxys(Misc.stringArray(dialog.getListData()));
159 
160         request("db_purge " + getClass().getName(),
161            Misc.stringArray(selection), "db_purge");
162      }
163   }
164 
165   public void Load() {
166      if ( !hubOK() ) return;
167      if ( !stopPlayback() ) return;
168 
169      if ( state.saving ) {
170         int result = JOptionPane.showConfirmDialog(this,
171             "There is an open database connection\n" +
172             "and saving is in progress.\nClose current connection?",
173 	    "Warning", JOptionPane.YES_NO_OPTION);
174         if ( result == JOptionPane.YES_OPTION)
175            Close();
176         else
177            return;
178      }
179 
180      String sessionType = this.getClass().getName();
181      Hashtable input = model.getDbSessions(sessionType);
182      if ( proxy_dialog == null ) {
183         proxy_dialog = new EditableDoubleSelectionDialog(this,
184 	   "Select DbProxy & Session Name", "DbProxy Agent","Session Name");
185         proxy_dialog.setLocationRelativeTo(this);
186      }
187 
188      proxy_dialog.setListData(input);
189      Object[] selection = proxy_dialog.getSelection();
190 
191      if ( selection != null ) {
192         Hashtable output = proxy_dialog.getListData();
193 	model.addDbSessions(sessionType,output);
194 
195         // adjust buttons etc
196         setMode(PLAYBACK);
197 
198         state.proxy = (String)selection[0];
199         state.session = (String)selection[1];
200         state.key = context.newId("LoadSessionKey");
201         state.mode = PLAYBACK;
202         state.player = new Player(this);
203 
204 	request("db_open " + sessionType + " " + state.session +
205 	   " " + state.key, state.proxy, "db_open");
206      }
207   }
208 
209   public void Record() {
210      if ( state.saving ) {
211         int result = JOptionPane.showConfirmDialog(this,
212             "There is an open database connection\n" +
213             "and saving is in progress.\nClose current connection?",
214 	    "Warning", JOptionPane.YES_NO_OPTION);
215         if ( result == JOptionPane.YES_OPTION)
216            Close();
217         else
218            return;
219      }
220 
221      String sessionType = this.getClass().getName();
222      Hashtable input = model.getDbSessions(sessionType);
223      if ( proxy_dialog == null ) {
224         proxy_dialog = new EditableDoubleSelectionDialog(this,
225 	   "Select DbProxy & Session Name", "DbProxy Agent","Session Name");
226         proxy_dialog.setLocationRelativeTo(this);
227      }
228 
229      proxy_dialog.setListData(input);
230      Object[] selection = proxy_dialog.getSelection();
231 
232      if ( selection != null ) {
233         Hashtable output = proxy_dialog.getListData();
234 	model.addDbSessions(sessionType,output);
235 
236         state.proxy = (String)selection[0];
237         state.session = (String)selection[1];
238         state.key = context.newId("SaveSessionKey");
239         state.errored = false;
240 
241 	request("db_create " + sessionType + " " + state.session +
242            " " + state.key, state.proxy, "db_create");
243      }
244   }
245 
246   public void Close() {
247      if ( hubOK() && state.key != null ) {
248         // close db connection
249 	request("db_close " + state.key, state.proxy, "db_close");
250         state.key = null;
251         // initialize view & reconstruct online society view
252         if ( state.mode == PLAYBACK ) {
253            if ( state.player != null ) {
254               state.player.terminate();
255               state.player = null;
256            }
257         }
258      }
259      setMode(ONLINE);
260      state.mode = ONLINE;
261      state.saving = false;
262      state.errored = false;
263   }
264 
265   public void Forward() {
266      if ( state.mode == PLAYBACK && !state.errored )
267         state.player.forward();
268   }
269 
270   public void Rewind() {
271      if ( state.mode == PLAYBACK && !state.errored )
272         state.player.rewind();
273   }
274 
275   public void FForward() {
276      if ( state.mode == PLAYBACK && !state.errored )
277         state.player.fforward();
278   }
279 
280   public void FRewind() {
281      if ( state.mode == PLAYBACK && !state.errored )
282         state.player.frewind();
283   }
284 
285   public void Stop() {
286      if ( state.mode == PLAYBACK && !state.errored )
287         state.player.pause();
288   }
289 
290   public void StepForward() {
291      if ( state.mode == PLAYBACK && !state.errored )
292         state.player.forward_step();
293   }
294 
295   public void ForwardEnd() {
296      if ( state.mode == PLAYBACK && !state.errored )
297         state.player.last();
298   }
299 
300   public void StepRewind() {
301      if ( state.mode == PLAYBACK && !state.errored )
302         state.player.rewind_step();
303   }
304 
305   public void RewindBegin() {
306      if ( state.mode == PLAYBACK && !state.errored )
307         state.player.first();
308   }
309 
310   protected boolean checkErrorMsg(Performative msg, String message) {
311      String type = msg.getType();
312      if ( type.equals("failure") || type.equals("not-understood") ||
313           type.equals("refuse") ) {
314         JOptionPane.showMessageDialog(this, message, "Error",
315 	   JOptionPane.ERROR_MESSAGE);
316         return true;
317      }
318      return false;
319   }
320 
321   public void db_sessions(Performative msg) {
322      if ( checkErrorMsg(msg,"Cannot list sessions") ) return;
323      if ( msg.getType().equals("inform") ) {
324         String sessionType = this.getClass().getName();
325         String agent = msg.getSender();
326         StringTokenizer st = new StringTokenizer(msg.getContent());
327         while( st.hasMoreTokens() )
328            model.addDbSession(sessionType,agent,st.nextToken());
329      }
330   }
331 
332   public void db_delete(Performative msg) {
333      checkErrorMsg(msg,"Cannot delete database session");
334   }
335 
336   public void db_purge(Performative msg) {
337      checkErrorMsg(msg,"Cannot purge database");
338   }
339 
340   public void db_close(Performative msg) {
341      checkErrorMsg(msg,"Cannot close database");
342   }
343 
344   public void db_save(Performative msg) {
345      if ( checkErrorMsg(msg,"Cannot save item") )
346         Close();
347   }
348 
349   protected boolean record_item(Performative msg) {
350      if ( state.mode != ONLINE || !state.saving || state.errored ) 
351         return false;
352 
353      String s = msg.getSender();
354      String r = msg.getReceiver();
355      if ( (s.equals(context.whoami()) && r.equals(state.proxy)) ||
356           (r.equals(context.whoami()) && s.equals(state.proxy))  )
357         return false;
358 
359      request("db_save " + state.key + " " + msg, state.proxy, "db_save");
360      return true;
361   }
362 
363 
364   public void db_create(Performative msg) {
365      state.errored = checkErrorMsg(msg,
366         "Cannot create database session.\nClosing link.");
367      if ( state.errored ) {
368         setMode(ONLINE);
369         state.mode = ONLINE;
370         state.saving = false;
371         state.errored = false;
372      }
373      else
374         state.saving = true;
375   }
376 
377   public void db_prior(Performative msg) {
378      if ( checkErrorMsg(msg,"End of file reached") )
379         state.player.setCommand(Player.READY);
380      else {
381         Performative imsg = ZeusParser.performative(msg.getContent());
382         visualiseVideoData(BACKWARD,imsg);
383      }
384   }
385   public void db_next(Performative msg) {
386      if ( checkErrorMsg(msg,"End of file reached") )
387         state.player.setCommand(Player.READY);
388      else {
389         Performative imsg = ZeusParser.performative(msg.getContent());
390         visualiseVideoData(FORWARD,imsg);
391      }
392   }
393 
394   public void db_first(Performative msg) {
395      if ( checkErrorMsg(msg,"End of file reached") )
396         state.player.setCommand(Player.READY);
397   }
398 
399   public void db_last(Performative msg) {
400      if ( checkErrorMsg(msg,"End of file reached") )
401         state.player.setCommand(Player.READY);
402   }
403 
404   public void db_open(Performative msg) {
405      if ( checkErrorMsg(msg,"Cannot open database") ) {
406         state.key = null;
407         Close();
408         return;
409      }
410      // db_open acknowledged; send LIST cmd
411      state.player.setCommand(Player.LIST);
412      query("db_list " + state.key, state.proxy, "db_list");
413   }
414 
415   public void db_list(Performative msg) {
416      if ( checkErrorMsg(msg,"Cannot obtain list of agents") ) {
417         Close();
418         return;
419      }
420      // db_list replied to; process list; cmd = COUNT
421      StringTokenizer st = new StringTokenizer(msg.getContent());
422      Vector info = new Vector();
423      while( st.hasMoreTokens() )
424         info.addElement(st.nextToken());
425      registerListOfPlaybackAgents(info);
426      state.player.setCommand(Player.COUNT);
427      query("db_count " + state.key, state.proxy, "db_count");
428   }
429 
430   public void db_count(Performative msg) {
431      if ( checkErrorMsg(msg,"Cannot obtain count of itens") ) {
432         Close();
433         return;
434      }
435      // count replied to; intialize player; cmd = REDAY
436      int max_count = Integer.parseInt(msg.getContent());
437      state.player.setCount(max_count);
438      state.player.setCommand(Player.READY);
439   }
440 
441   void doPlayerCommand(String cmd) {
442      query(cmd + " " + state.key, state.proxy, cmd);
443   }
444 
445   public void PlayerSpeed() {
446      long speed;
447 
448      speed = (state != null && state.player != null)
449              ? state.player.getSpeed()
450              : Player.getDefaultSpeed();
451      if ( number_dialog == null ) {
452         number_dialog = new NumberDialog(this,"Set Player Speed",
453                                      "Enter speed:");
454         number_dialog.setLocationRelativeTo(this);
455      }
456 
457      number_dialog.setValue(speed);
458      Long speedValue = number_dialog.getValue();
459      if (speedValue != null) {
460         if ( state != null && state.player != null)
461            state.player.setSpeed(speedValue.longValue());
462         else
463            Player.setDefaultSpeed(speedValue.longValue());
464      }
465   }
466 
467   protected abstract void registerListOfPlaybackAgents(Vector info);
468   protected abstract void visualiseVideoData(int dir, Performative msg);
469   protected abstract void setMode(int mode);
470 
471   protected class VideoToolBar extends JToolBar implements ActionListener {
472      protected JButton  firstBtn, fastRewindBtn;
473      protected JButton  rewindBtn, stepRewindBtn;
474      protected JButton  stopBtn, stepForwardBtn;
475      protected JButton  forwardBtn, fastForwardBtn;
476      protected JButton  lastBtn, recordBtn;
477    
478      public VideoToolBar() {
479         setFloatable(false);
480     
481         String sep = System.getProperty("file.separator");
482         String path = SystemProps.getProperty("gif.dir") + sep +
483            "visualiser" + sep;
484     
485         // Last Button
486         firstBtn = new JButton(new ImageIcon(path + "first.gif"));
487         add(firstBtn);
488         firstBtn.setPreferredSize(new Dimension(24,24));
489         firstBtn.setToolTipText("First");
490         firstBtn.setMargin(new Insets(0,0,0,0));
491     
492         // Fast Rewind Button
493         fastRewindBtn = new JButton(new ImageIcon(path + "fbwd.gif"));
494         add(fastRewindBtn);
495         fastRewindBtn.setPreferredSize(new Dimension(24,24));
496         fastRewindBtn.setToolTipText("Fast Rewind");
497         fastRewindBtn.setMargin(new Insets(0,0,0,0));
498     
499         // Rewind Button
500         rewindBtn = new JButton(new ImageIcon(path + "bwd.gif"));
501         add(rewindBtn);
502         rewindBtn.setPreferredSize(new Dimension(24,24));
503         rewindBtn.setToolTipText("Rewind");
504         rewindBtn.setMargin(new Insets(0,0,0,0));
505     
506         // Step Rewind Button
507         stepRewindBtn = new JButton(new ImageIcon(path + "prior.gif"));
508         add(stepRewindBtn);
509         stepRewindBtn.setPreferredSize(new Dimension(24,24));
510         stepRewindBtn.setToolTipText("Prior");
511         stepRewindBtn.setMargin(new Insets(0,0,0,0));
512         addSeparator();
513     
514         // Stop Button
515         stopBtn = new JButton(new ImageIcon(path + "stop.gif"));
516         add(stopBtn);
517         stopBtn.setPreferredSize(new Dimension(24,24));
518         stopBtn.setToolTipText("Stop");
519         stopBtn.setMargin(new Insets(0,0,0,0));
520         addSeparator();
521     
522         // Step Forward Button
523         stepForwardBtn = new JButton(new ImageIcon(path + "next.gif"));
524         add(stepForwardBtn);
525         stepForwardBtn.setPreferredSize(new Dimension(24,24));
526         stepForwardBtn.setToolTipText("Next");
527         stepForwardBtn.setMargin(new Insets(0,0,0,0));
528     
529         // Forward Button
530         forwardBtn = new JButton(new ImageIcon(path + "fwd.gif"));
531         add(forwardBtn);
532         forwardBtn.setPreferredSize(new Dimension(24,24));
533         forwardBtn.setToolTipText("Play");
534         forwardBtn.setMargin(new Insets(0,0,0,0));
535     
536         // Fast Forward Button
537         fastForwardBtn = new JButton(new ImageIcon(path + "ffwd.gif"));
538         add(fastForwardBtn);
539         fastForwardBtn.setPreferredSize(new Dimension(24,24));
540         fastForwardBtn.setToolTipText("Fast Forward");
541         fastForwardBtn.setMargin(new Insets(0,0,0,0));
542     
543         // Last Button
544         lastBtn = new JButton(new ImageIcon(path + "last.gif"));
545         add(lastBtn);
546         lastBtn.setPreferredSize(new Dimension(24,24));
547         lastBtn.setToolTipText("Last");
548         lastBtn.setMargin(new Insets(0,0,0,0));
549         addSeparator();
550     
551         // Record Button
552         recordBtn = new JButton(new ImageIcon(path + "rec.gif"));
553         add(recordBtn);
554         recordBtn.setPreferredSize(new Dimension(24,24));
555         recordBtn.setToolTipText("Record");
556         recordBtn.setMargin(new Insets(0,0,0,0));
557     
558         firstBtn.addActionListener(this);
559         fastRewindBtn.addActionListener(this);
560         rewindBtn.addActionListener(this);
561         stepRewindBtn.addActionListener(this);
562         stopBtn.addActionListener(this);
563         stepForwardBtn.addActionListener(this);
564         forwardBtn.addActionListener(this);
565         fastForwardBtn.addActionListener(this);
566         lastBtn.addActionListener(this);
567         recordBtn.addActionListener(this);
568     
569         setPreferredSize(new Dimension(300,32));
570      }
571    
572      public void setStatus(boolean b)  {
573         firstBtn.setEnabled(b);
574         fastRewindBtn.setEnabled(b);
575         rewindBtn.setEnabled(b);
576         stepRewindBtn.setEnabled(b);
577         stopBtn.setEnabled(b);
578         stepForwardBtn.setEnabled(b);
579         forwardBtn.setEnabled(b);
580         fastForwardBtn.setEnabled(b);
581         lastBtn.setEnabled(b);
582         recordBtn.setEnabled(!b);
583      }
584    
585      public void actionPerformed(ActionEvent evt) {
586         Object src = evt.getSource();
587     
588         if ( src == firstBtn )
589            RewindBegin();
590         else if ( src == fastRewindBtn )
591            FRewind();
592         else if ( src == rewindBtn )
593            Rewind();
594         else if ( src == stepRewindBtn )
595            StepRewind();
596         else if ( src == stopBtn )
597            Stop();
598         else if ( src == stepForwardBtn )
599            StepForward();
600         else if ( src == forwardBtn )
601            Forward();
602         else if ( src == fastForwardBtn )
603            FForward();
604         else if ( src == lastBtn )
605            ForwardEnd();
606         else if ( src == recordBtn )
607            Record();
608      }
609   }
610 }