📄 m4appsampleswing.java
字号:
* 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.
* <p>
* 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);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -