package Projeto; /******************************************************************************\ ** ** ** Licensed Materials - Property of IBM ** ** IBM Toolkit for MPEG-4 ** ** Copyright IBM Corp. 1998-2005 All Rights Reserved ** ** ** \******************************************************************************/ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import javax.swing.ButtonGroup; import javax.swing.JCheckBoxMenuItem; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JRadioButtonMenuItem; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.UIManager; import player.PlayerAdapter; import player.PlayerControl; import player.PlayerControlPanel; import player.PlayerControlPanelFactory; import player.PlayerFactory; /******************************************************************************* * IBM Toolkit for MPEG-4 Sample Player application for Swing. This code has * been adapted from the M4AppSample which was written using the AWT for the UI. * */ public class M4AppSampleSwing extends JFrame implements Runnable { private final static String kPlayerName = "IBM Toolkit for MPEG-4 Sample Player"; static { // Set the Swing UI to have the look and feel of the system its running on. We do this here in // a static initialization block so its done ahead of the menu and menu items being created // when the class is instantiated below. // try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ignored) {/* ignored - will use default look and feel should this fail */} } // The menus for the player; indented to show highlight the actual layout // private JMenu fileMenu = new JMenu("File"); private JMenuItem openMenuItem = new JMenuItem("Open..."); private JMenuItem closeMenuItem = new JMenuItem("Close"); private JMenuItem exitMenuItem = new JMenuItem("Exit"); private JMenu viewMenu = new JMenu("View"); private JCheckBoxMenuItem autosizeMenuItem = new JCheckBoxMenuItem("Size window to new content"); private JCheckBoxMenuItem scaleMenuItem = new JCheckBoxMenuItem("Scale content to window"); private JCheckBoxMenuItem speedScaleMenuItem = new JCheckBoxMenuItem("Scaling; speed (vs. quality)"); private JMenu sizeMenu = new JMenu("Window size"); private JMenuItem size50MenuItem = new JMenuItem("50%"); private JMenuItem size100MenuItem = new JMenuItem("100%"); private JMenuItem size200MenuItem = new JMenuItem("200%"); private JMenuItem sizeHalfMenuItem = new JMenuItem("x \u00BD"); private JMenuItem sizeTwiceMenuItem = new JMenuItem("x 2"); private JCheckBoxMenuItem ctlBarMenuItem = new JCheckBoxMenuItem("Control Bar"); private JMenu playMenu = new JMenu("Play"); private JMenuItem playPauseMenuItem = new JMenuItem("Play/Pause"); private JMenuItem stopMenuItem = new JMenuItem("Stop"); private JMenu atDurActMenu = new JMenu("At duration"); private JRadioButtonMenuItem endContMenuItem = new JRadioButtonMenuItem("Continue"); private JRadioButtonMenuItem endStopMenuItem = new JRadioButtonMenuItem("Stop"); private JRadioButtonMenuItem endRptMenuItem = new JRadioButtonMenuItem("Restart"); private JCheckBoxMenuItem muteMenuItem = new JCheckBoxMenuItem("Mute"); private PlayerControl m4Player; // This is the control interface for the player private PlayerControlPanel m4PlayerPanel; // This is for the control panel bar private JProgressBar barraDeProgresso; private boolean playerAdded; // True when player renderer component is added to our frame /***************************************************************************** * The constructor creates the player, sets up listeners, sets up * behavior using the player control, adds a player control panel * and shows the application */ public M4AppSampleSwing() { // Create the MPEG-4 player and add our listener class that has been derived from the PlayerAdapter // /* * // This commented code is the orginal code for this sample used with IBM Toolkit For MPEG-4 * // versions up to 1.2.6. In version 1.2.6 a new lightweight rendering player was introduced and * // that is now created below. With that we can put lightwight swing components over the player * // and we don't need anymore the line of code to set JPopupMenu so menus come above the player. * // The heavweight version can still be used, hence the lines of code have been kept here to show * // how its done for that case. * * m4Player = PlayerFactory.createMPEG4Player(); * * // Make sure we use have menus that will come up over the heavyweight player component * // * javax.swing.JPopupMenu.setDefaultLightWeightPopupEnabled(false); * */ m4Player = PlayerFactory.createLightweightMPEG4Player(); // From 1.2.6 we can now create a lightweight player m4Player.addListener(new M4AppPlayerAdapter()); // This is to allow the frame to close when we click the close button // addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {exit();} }); // This is for when we are showing the title in the main frame to update as it resizes // addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) {if (!playerAdded) repaint();} }); // Put in our custom pane which will show our text 'logo' // setContentPane(new MyJPanel()); // We use a border layout with the player's renderer component in the center and the control panel // to the south // getContentPane().setLayout(new BorderLayout()); // Create the menus bar and setup the player // createMenuBar(); // m4Player.setAutoSize(false); // We don't want the forced autosize, we do any resize ourself m4Player.setScaling(scaleMenuItem.getState()); // Scaling is set as per the menu state m4Player.setSpeedScaling(speedScaleMenuItem.getState()); setEndAction(PlayerControl.END_ACTION_CONTINUE); // We set a default end behavior to carry on playing endContMenuItem.setSelected(true); atDurActMenu.setEnabled(false); // wait until we have content to enable this (see M4AppPlayerAdapter) m4Player.setMute(muteMenuItem.getState()); // Mute is as per the menu state // Create a control panel and set the menus to match // m4PlayerPanel = PlayerControlPanelFactory.createPlayerControlPanel("Basic", m4Player); if (m4PlayerPanel != null) { m4PlayerPanel.setBackground(Color.lightGray); showControlBar(true); ctlBarMenuItem.setEnabled(true); ctlBarMenuItem.setState(true); } // Lastly put the sample into the window title and show the player at a reasonable starting size // setTitle(kPlayerName); setSize(360, 280); show(); } /***************************************************************************** * Creates the menus bar, sets up listeners for the menus and initializes * menus according to an initial setup (Note: some menu settings could be * saved as persistent preferences and reloaded, but that is beyond the scope * of this sample player) */ private void createMenuBar() { JMenuBar mb = new JMenuBar(); mb.add(fileMenu); // openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, java.awt.Event.CTRL_MASK)); openMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {open();} }); fileMenu.add(openMenuItem); // closeMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {close();} }); fileMenu.add(closeMenuItem); // fileMenu.addSeparator(); exitMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {exit();} }); fileMenu.add(exitMenuItem); mb.add(viewMenu); // viewMenu.add(autosizeMenuItem); // scaleMenuItem.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) {m4Player.setScaling(scaleMenuItem.getState());} }); viewMenu.add(scaleMenuItem); // speedScaleMenuItem.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) {m4Player.setSpeedScaling(speedScaleMenuItem.getState());} }); viewMenu.add(speedScaleMenuItem); // viewMenu.add(sizeMenu); // sizeMenu.add(size50MenuItem); size50MenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_0, java.awt.Event.CTRL_MASK)); size50MenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {setSizePercent(50);} }); // sizeMenu.add(size100MenuItem); size100MenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, java.awt.Event.CTRL_MASK)); size100MenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {setSizePercent(100);} }); // sizeMenu.add(size200MenuItem); size200MenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, java.awt.Event.CTRL_MASK)); size200MenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {setSizePercent(200);} }); // sizeMenu.addSeparator(); sizeMenu.add(sizeHalfMenuItem); sizeHalfMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, java.awt.Event.CTRL_MASK)); sizeHalfMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {setSizeActual(50);} }); // sizeMenu.add(sizeTwiceMenuItem); sizeTwiceMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2, java.awt.Event.CTRL_MASK)); sizeTwiceMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {setSizeActual(200);} }); // viewMenu.addSeparator(); viewMenu.add(ctlBarMenuItem); ctlBarMenuItem.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) {showControlBar(ctlBarMenuItem.getState());} }); mb.add(playMenu); // playMenu.add(playPauseMenuItem); playPauseMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, java.awt.Event.CTRL_MASK)); playPauseMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {playPauseAction();} }); // playMenu.add(stopMenuItem); stopMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, java.awt.Event.CTRL_MASK)); stopMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {stopAction();} }); // playMenu.addSeparator(); playMenu.add(atDurActMenu); // atDurActMenu.add(endContMenuItem); endContMenuItem.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) {setEndAction(PlayerControl.END_ACTION_CONTINUE);} }); // atDurActMenu.add(endStopMenuItem); endStopMenuItem.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) {setEndAction(PlayerControl.END_ACTION_STOP);} }); // atDurActMenu.add(endRptMenuItem); endRptMenuItem.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) {setEndAction(PlayerControl.END_ACTION_REPEAT);} }); ButtonGroup bg = new ButtonGroup(); // The end action menus are to act as a radio button group bg.add(endContMenuItem); bg.add(endStopMenuItem); bg.add(endRptMenuItem); // playMenu.addSeparator(); playMenu.add(muteMenuItem); muteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, java.awt.Event.CTRL_MASK)); muteMenuItem.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) {m4Player.setMute(muteMenuItem.getState());} }); closeMenuItem.setEnabled(false); autosizeMenuItem.setState(true); sizeMenu.setEnabled(false); ctlBarMenuItem.setEnabled(false); playPauseMenuItem.setEnabled(false); stopMenuItem.setEnabled(false); setJMenuBar(mb); } /***************************************************************************** * Main entry point for the sample application. We can pass a url from the * command line here; a local file or remote server e.g. rtsp:// type url. * With this sample application passing a remote url here is the only way to * access remote content as this sample player has only a file open dialog. * (An OpenURL dialog could be added but again is beyond the scope of this * sample). * * @param args A string as a url point to media content */ public static void main(String[] args) { // Create a new instance of our application M4AppSampleSwing app = new M4AppSampleSwing(); //if (args.length > 0) // { System.out.println("OK"); app.openPlayUrl("Mundo.mp4"); // invoke content directly from the command line //} } /***************************************************************************** * This opens and plays the content referenced by the url. The * player renderer component is added if it has not already been added. * (i.e. we can Open a new content without closing the prior one). * * @param url String referencing the content e.g. myfile.mp4, * rtsp://myserver.com/myfile.mp4 */ private void openPlayUrl(String url) { // Stop & close any playback that may be running still // m4Player.stopUrl(); try { // We title our window as per the content and added the player renderer // component if needed. Now we have the player added we can enable the size // menu to allow the content display size to be set. // setTitle(url); if (!playerAdded) { getContentPane().add("Center", m4Player.getRendererComponent()); playerAdded = true; sizeMenu.setEnabled(true); validate(); // m4Player.stop(); } m4Player.open(url); m4Player.start(); } catch (Exception e) { m4Player.stopUrl(); // Stop MPEG-4 player setTitle(e.toString()); // and set error in title bar } } /***************************************************************************** * Opens a local file from the file dialog and plays it */ private void open() { JFileChooser openFileChooser = new JFileChooser(); int retVal = openFileChooser.showOpenDialog(this); if (retVal == JFileChooser.APPROVE_OPTION) { openPlayUrl(openFileChooser.getSelectedFile().getAbsolutePath()); } } /***************************************************************************** * Stop playing and close any content, remove the player renderer * component. By closing the content we close any connection to it, e.g.. over * RTSP stopURL() will teardown and end the session. */ private void close() { m4Player.stopUrl(); getContentPane().remove(m4Player.getRendererComponent()); sizeMenu.setEnabled(false); playerAdded = false; setTitle(kPlayerName); } /***************************************************************************** * We want to exit the application. Stop and close any content * that may be playing before exiting. */ private void exit() { m4Player.stopUrl(); dispose(); System.exit(0); } /***************************************************************************** * This sets the player size as a ratio of the preferred content size. The * menus are not enabled unless there is a preferred size. An * optional preferred size is signalled in MPEG-4 content. * * @param percent Percentage of preferred size. Currently 50%, 100% and 200% */ private void setSizePercent(int percent) { int wTarget = m4Player.getPreferredSceneSize().width; int hTarget = m4Player.getPreferredSceneSize().height; switch (percent) { case 50: wTarget /= 2; hTarget /= 2; break; case 100: break; case 200: wTarget *= 2; hTarget *= 2; break; default: throw new IllegalArgumentException(); } m4Player.setSize(wTarget, hTarget); validate(); pack(); pack(); } /***************************************************************************** * This sets the player size as a ratio of its current size * whatever that is. * * @param percent Percentage of current size to set as new size (50% or 200%) */ private void setSizeActual(int percent) { int wTarget = m4Player.getSize().width; int hTarget = m4Player.getSize().height; switch (percent) { case 50: wTarget /= 2; hTarget /= 2; break; case 200: wTarget *= 2; hTarget *= 2; break; default: throw new IllegalArgumentException(); } m4Player.setSize(wTarget, hTarget); validate(); pack(); pack(); } /***************************************************************************** * This allows the control bar panel to be hidden or shown. If there * is no player renderer component added then the panel is added. If * the player renderer component has been added then the layout is * adjusted to keep the player size and add the panel. * * @param show Set to true to show (add) the panel. False to hide (remove). */ private void showControlBar(boolean show) { if (show) { getContentPane().add("South", m4PlayerPanel); m4PlayerPanel.attachToPlayer(); } else { getContentPane().remove(m4PlayerPanel); m4PlayerPanel.detachFromPlayer(); } if (playerAdded) { validate(); pack(); pack(); } } /***************************************************************************** * Handle our pause/play menu by playing (start()), or pausing or resuming * dependent on state. Menus are set as per state callbacks on our listener * class that extends PlayerAdapter. * * Error handling could be better; IOExceptions may occur for example if we * are using RTSP to communicate with a server over a network. */ void playPauseAction() { try { switch (m4Player.getState()) { case PlayerControl.STOPPED: m4Player.start(); break; case PlayerControl.PAUSED: m4Player.resume(); break; case PlayerControl.PLAYING: m4Player.pause(); break; } } catch (IOException e){/*nothing*/} catch (IllegalStateException ie){/*nothing*/} } /***************************************************************************** * Handle our stop menu by stopping the player */ void stopAction() { try { m4Player.stop(); } catch (IOException e){/*nothing*/} catch (IllegalStateException ie){/*nothing*/} } /***************************************************************************** * Set the action that the player will take when the indicated duration of * the content is reached (if the content duration is indefinite/unknown * then this has no net effect) * * @param endAction The action to take */ private void setEndAction(int endAction) { m4Player.setPlayerEndAction(endAction); } /***************************************************************************** * Extends the PlayerAdapter class so we can implement the methods only for * those events we are interested in here. *
* Since the methods here do UI actions we must ensure they are done on the * UI thread. To avoid any possibility of deadlock with the player, if/when * any methods need to call back to the player, we use the invokeLater() * rather than the invokedAndWait(). * * @see player.PlayerAdapter * @see player.PlayerListener */ private class M4AppPlayerAdapter extends PlayerAdapter { private boolean autoSized; // Used when autosizing from content to content so we can prevent // resizing when stopping/playing same content /*************************************************************************** * Enable close/play/pause/stop menus according to state. This allows us to * work in conjunction with the player control panel that can also affect * state. * * @param state State as per PlayerControl i.e.. Closed. Playing etc * * @see player.PlayerListener#changedState(int) */ public void changedState(final int state) { try { SwingUtilities.invokeLater(new Runnable() { public void run() { switch (state) { case PlayerControl.CLOSED: closeMenuItem.setEnabled(false); playPauseMenuItem.setEnabled(false); break; case PlayerControl.STOPPED: closeMenuItem.setEnabled(true); playPauseMenuItem.setEnabled(true); stopMenuItem.setEnabled(false); // The player is in Stopped state after the content is opened. In this // state we now have access to content specific info such as duration, // whether we can seek etc. Here this is used to show that we can // access if the content has a duration and enable/disable the // endAction menu accordingly (Note: since this is more a player // preference type behavior it may be preferable to keep the menu // enabled, whether specific content has duration or not, as it done // in our M4Play application. But this is shown here to illustrate // that certain info is available once the content is opened. See the // PlayerControl javadoc for more info.) // // atDurActMenu.setEnabled(m4Player.hasDuration()); break; case PlayerControl.PLAYING: stopMenuItem.setEnabled(true); break; case PlayerControl.PAUSED: break; } } }); } catch (Exception ignored) {/*ignore*/} } /*************************************************************************** * Reflect mute state on our menu * * @param isMuted True when audio playback is muted * * @see player.PlayerListener#muteChanged(boolean) */ public void muteChanged(final boolean isMuted) { try { SwingUtilities.invokeLater(new Runnable() { public void run() { muteMenuItem.setState(isMuted); } }); } catch (Exception ignored) {/*ignore*/} } /*************************************************************************** * This is called to signal optional preferred size from the content. If we * have a preferred size we can enable the menus that allow the size to be * set as a ratio of preferred size. Also, if we autosize to new content we * will adjust the player size accordingly. We use the autoSized flag as we * get signalled for this preferred size each time if/when we stop and play * the content and for our application we will leave the size at whatever * the user wants as long as we don't change to another piece of content. * In the latter case we change size only then if the menu preference is * selected. * * @param w Preferred width or -1 if no preferred size * @param h Preferred height or -1 if no preferred size * * @see player.PlayerListener#preferSize(int, int) */ public void preferSize(final int w, final int h) { try { SwingUtilities.invokeLater(new Runnable() { public void run() { boolean hasPreferredSize = (w > 0 && h > 0); size50MenuItem.setEnabled(hasPreferredSize); size100MenuItem.setEnabled(hasPreferredSize); size200MenuItem.setEnabled(hasPreferredSize); if (autosizeMenuItem.getState() && hasPreferredSize) { if (!autoSized) { autoSized = true; m4Player.setSize(w, h); validate(); pack(); } } // Speed scaling is only when we have a preferred size // speedScaleMenuItem.setEnabled(hasPreferredSize); } }); } catch (Exception ignored) {/*ignore*/} } /***************************************************************************** * Indicates pixel or meter metrics from presentation * * @param usePixelMetrics True if using pixel metrics, false is meter metrics */ public void usingMetrics(final boolean usePixelMetrics) { try { SwingUtilities.invokeLater(new Runnable() { public void run() { // Scaling is always on in meter metrics so only enable the menu in pixel // metrics. This is a choice we could leave the menu always enabled. // scaleMenuItem.setEnabled(usePixelMetrics); } }); } catch (Exception ignored) {/*ignore*/} } /*************************************************************************** * Content has been opened. Allow any auto resizing to occur and * set the window title to reflect the content. This is the first indication * we get following content being opened and precedes the preferredSize and * usingMetrics indications. Hence this is a suitable point to reset the * autosizing flag since the content has changed (it may be the same url if * the content is closed and re-opened but we handle that as if it was new * content and enable the autosizing again). * * @param url The string for the content url. * * @see player.PlayerListener#urlChanged(java.lang.String) */ public void urlChanged(final String url) { try { SwingUtilities.invokeLater(new Runnable() { public void run() { autoSized = false; setTitle(url); } }); } catch (Exception ignored) {/*ignore*/} } } /***************************************************************************** * Extends the standard JPanel class. This is just a convenience to allow the * painting of the sample 'logo' by setting this as the contentPane. * */ private class MyJPanel extends JPanel { /**************************************************************************** * This method is just to display the sample player string in the main frame * before we add the player renderer component, i.e. before we Open any * content. or after the component is removed which is after when we Close * the content (i.e when the player is not added to the frame) * * @param g Graphics context */ public void paintComponent(Graphics g) { super.paintComponent(g); if (!playerAdded) { Rectangle r = getBounds(); int w = r.width; int h = r.height; g.setColor(Color.black); g.fillRect(0, 0, w, h); Insets i = getInsets(); w -= i.left + i.right; h -= i.top + i.bottom; g.setFont(logoFont); FontMetrics fm = g.getFontMetrics(); int sWidth = fm.stringWidth(kPlayerName); int iLeft = i.left + (w - sWidth)/2; int y = i.top + h/2; g.setColor(Color.blue); g.drawString(kPlayerName, iLeft, y); } } // private Font logoFont = new Font("Helvetica", Font.BOLD, 16); } public void run(){ System.out.println("OK"); openPlayUrl("Mundo.mp4"); } }