@Test
 public void testAddItemIPlayItem() {
   System.out.println("testAddItemIPlayItem");
   SimplePlayItem item = new SimplePlayItem();
   item.setName("IronMan.flv");
   pss.addItem(item);
 }
 @Test
 public void testStart() {
   System.out.println("testStart");
   SimplePlayItem item = new SimplePlayItem();
   item.setName("DarkKnight.flv");
   pss.addItem(item);
   pss.start();
 }
  /**
   * Plays back a stream based on the supplied name, from the specified position for the given
   * length of time.
   *
   * @param name - The name of a recorded file, or the identifier for live data. If
   * @param start - The start time, in seconds. Allowed values are -2, -1, 0, or a positive number.
   *     The default value is -2, which looks for a live stream, then a recorded stream, and if it
   *     finds neither, opens a live stream. If -1, plays only a live stream. If 0 or a positive
   *     number, plays a recorded stream, beginning start seconds in.
   * @param length - The duration of the playback, in seconds. Allowed values are -1, 0, or a
   *     positive number. The default value is -1, which plays a live or recorded stream until it
   *     ends. If 0, plays a single frame that is start seconds from the beginning of a recorded
   *     stream. If a positive number, plays a live or recorded stream for length seconds.
   * @param reset - Whether to clear a playlist. The default value is 1 or true, which clears any
   *     previous play calls and plays name immediately. If 0 or false, adds the stream to a
   *     playlist. If 2, maintains the playlist and returns all stream messages at once, rather than
   *     at intervals. If 3, clears the playlist and returns all stream messages at once.
   */
  public void play(String name, int start, int length, Object reset) {
    if (reset instanceof Boolean) {
      play(name, start, length, ((Boolean) reset).booleanValue());
    } else {
      if (reset instanceof Integer) {
        int value = (Integer) reset;
        switch (value) {
          case 0:
            // adds the stream to a playlist
            IStreamCapableConnection streamConn =
                (IStreamCapableConnection) Red5.getConnectionLocal();
            IPlaylistSubscriberStream playlistStream =
                (IPlaylistSubscriberStream) streamConn.getStreamById(streamConn.getStreamId());
            IPlayItem item = SimplePlayItem.build(name);
            playlistStream.addItem(item);
            play(name, start, length, false);
            break;
          case 2:
            // maintains the playlist and returns all stream messages at once, rather than at
            // intervals

            break;
          case 3:
            // clears the playlist and returns all stream messages at once

            break;
          default:
            // clears any previous play calls and plays name immediately
            play(name, start, length, true);
        }
      } else {
        play(name, start, length);
      }
    }
  }
 /** {@inheritDoc} */
 public void addItem(IPlayItem item, int index) {
   IPlayItem prev = items.get(index);
   if (prev != null && prev instanceof SimplePlayItem) {
     // since it replaces the item in the current spot, reset the items time so the sort will work
     ((SimplePlayItem) item).setCreated(((SimplePlayItem) prev).getCreated() - 1);
   }
   items.add(index, item);
   if (index <= currentItemIndex) {
     // item was added before the currently playing
     currentItemIndex++;
   }
 }
 /**
  * Dynamic streaming play method.
  *
  * <p>The following properties are supported on the play options:
  *
  * <pre>
  * streamName: String. The name of the stream to play or the new stream to switch to.
  * oldStreamName: String. The name of the initial stream that needs to be switched out. This is not needed and ignored
  * when play2 is used for just playing the stream and not switching to a new stream.
  * start: Number. The start time of the new stream to play, just as supported by the existing play API. and it has the
  * same defaults. This is ignored when the method is called for switching (in other words, the transition
  * is either NetStreamPlayTransition.SWITCH or NetStreamPlayTransitions.SWAP)
  * len: Number. The duration of the playback, just as supported by the existing play API and has the same defaults.
  * transition: String. The transition mode for the playback command. It could be one of the following:
  * NetStreamPlayTransitions.RESET
  * NetStreamPlayTransitions.APPEND
  * NetStreamPlayTransitions.SWITCH
  * NetStreamPlayTransitions.SWAP
  * </pre>
  *
  * NetStreamPlayTransitions:
  *
  * <pre>
  * APPEND : String = "append" - Adds the stream to a playlist and begins playback with the first stream.
  * APPEND_AND_WAIT : String = "appendAndWait" - Builds a playlist without starting to play it from the first stream.
  * RESET : String = "reset" - Clears any previous play calls and plays the specified stream immediately.
  * RESUME : String = "resume" - Requests data from the new connection starting from the point at which the previous connection ended.
  * STOP : String = "stop" - Stops playing the streams in a playlist.
  * SWAP : String = "swap" - Replaces a content stream with a different content stream and maintains the rest of the playlist.
  * SWITCH : String = "switch" - Switches from playing one stream to another stream, typically with streams of the same content.
  * </pre>
  *
  * @see <a
  *     href="http://www.adobe.com/devnet/flashmediaserver/articles/dynstream_actionscript.html">ActionScript
  *     guide to dynamic streaming</a>
  * @see <a
  *     href="http://www.adobe.com/devnet/flashmediaserver/articles/dynstream_advanced_pt1.html">Dynamic
  *     streaming in Flash Media Server - Part 1: Overview of the new capabilities</a>
  * @see <a
  *     href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetStreamPlayTransitions.html">NetStreamPlayTransitions</a>
  * @param playOptions play options
  */
 public void play2(Map<String, ?> playOptions) {
   log.debug("play2 options: {}", playOptions.toString());
   /* { streamName=streams/new.flv, oldStreamName=streams/old.flv,
   start=0, len=-1, offset=12.195, transition=switch } */
   // get the transition type
   String transition = (String) playOptions.get("transition");
   String streamName = (String) playOptions.get("streamName");
   String oldStreamName = (String) playOptions.get("oldStreamName");
   // now initiate new playback
   int start = (Integer) playOptions.get("start");
   int length = (Integer) playOptions.get("len");
   // get the clients connection
   IConnection conn = Red5.getConnectionLocal();
   if (conn != null && conn instanceof IStreamCapableConnection) {
     // get the stream id
     int streamId = conn.getStreamId();
     IStreamCapableConnection streamConn = (IStreamCapableConnection) conn;
     if ("stop".equals(transition)) {
       play(Boolean.FALSE);
     } else if ("reset".equals(transition)) {
       // just reset the currently playing stream
       play(streamName);
     } else if ("switch".equals(transition)) {
       try {
         // set the playback type
         simplePlayback.set(Boolean.FALSE);
         // send the "start" of transition
         sendNSStatus(
             conn,
             StatusCodes.NS_PLAY_TRANSITION,
             String.format("Transitioning from %s to %s.", oldStreamName, streamName),
             streamName,
             streamId);
         // support offset?
         // playOptions.get("offset")
         play(streamName, start, length);
       } finally {
         // clean up
         simplePlayback.remove();
       }
     } else if ("append".equals(transition) || "appendAndWait".equals(transition)) {
       IPlaylistSubscriberStream playlistStream =
           (IPlaylistSubscriberStream) streamConn.getStreamById(streamId);
       IPlayItem item = SimplePlayItem.build(streamName);
       playlistStream.addItem(item);
       if ("append".equals(transition)) {
         play(streamName, start, length, false);
       }
     } else if ("swap".equals(transition)) {
       IPlaylistSubscriberStream playlistStream =
           (IPlaylistSubscriberStream) streamConn.getStreamById(streamId);
       IPlayItem item = SimplePlayItem.build(streamName);
       int itemCount = playlistStream.getItemSize();
       for (int i = 0; i < itemCount; i++) {
         IPlayItem tmpItem = playlistStream.getItem(i);
         if (tmpItem.getName().equals(oldStreamName)) {
           if (!playlistStream.replace(tmpItem, item)) {
             log.warn("Playlist item replacement failed");
             sendNSFailed(
                 streamConn,
                 StatusCodes.NS_PLAY_FAILED,
                 "Playlist swap failed.",
                 streamName,
                 streamId);
           }
           break;
         }
       }
     } else {
       log.warn("Unhandled transition: {}", transition);
       sendNSFailed(
           conn, StatusCodes.NS_FAILED, "Transition type not supported", streamName, streamId);
     }
   } else {
     log.info("Connection was null ?");
   }
 }
 /** {@inheritDoc} */
 public void play(String name, int start, int length, boolean flushPlaylist) {
   log.debug(
       "Play called - name: {} start: {} length: {} flush playlist: {}",
       new Object[] {name, start, length, flushPlaylist});
   IConnection conn = Red5.getConnectionLocal();
   if (conn instanceof IStreamCapableConnection) {
     IScope scope = conn.getScope();
     IStreamCapableConnection streamConn = (IStreamCapableConnection) conn;
     int streamId = conn.getStreamId();
     if (StringUtils.isEmpty(name)) {
       sendNSFailed(
           streamConn, StatusCodes.NS_FAILED, "The stream name may not be empty.", name, streamId);
       return;
     }
     IStreamSecurityService security =
         (IStreamSecurityService) ScopeUtils.getScopeService(scope, IStreamSecurityService.class);
     if (security != null) {
       Set<IStreamPlaybackSecurity> handlers = security.getStreamPlaybackSecurity();
       for (IStreamPlaybackSecurity handler : handlers) {
         if (!handler.isPlaybackAllowed(scope, name, start, length, flushPlaylist)) {
           sendNSFailed(
               streamConn,
               StatusCodes.NS_FAILED,
               "You are not allowed to play the stream.",
               name,
               streamId);
           return;
         }
       }
     }
     boolean created = false;
     IClientStream stream = streamConn.getStreamById(streamId);
     if (stream == null) {
       if (streamId <= 0) {
         streamId = streamConn.reserveStreamId();
       }
       stream = streamConn.newPlaylistSubscriberStream(streamId);
       stream.setBroadcastStreamPublishName(name);
       stream.start();
       created = true;
     }
     if (stream != null && stream instanceof ISubscriberStream) {
       ISubscriberStream subscriberStream = (ISubscriberStream) stream;
       IPlayItem item =
           simplePlayback.get()
               ? SimplePlayItem.build(name, start, length)
               : DynamicPlayItem.build(name, start, length);
       if (subscriberStream instanceof IPlaylistSubscriberStream) {
         IPlaylistSubscriberStream playlistStream = (IPlaylistSubscriberStream) subscriberStream;
         if (flushPlaylist) {
           playlistStream.removeAllItems();
         }
         playlistStream.addItem(item);
       } else if (subscriberStream instanceof ISingleItemSubscriberStream) {
         ISingleItemSubscriberStream singleStream = (ISingleItemSubscriberStream) subscriberStream;
         singleStream.setPlayItem(item);
       } else {
         // not supported by this stream service
         log.warn(
             "Stream instance type: {} is not supported", subscriberStream.getClass().getName());
         return;
       }
       try {
         subscriberStream.play();
       } catch (IOException err) {
         if (created) {
           stream.close();
           streamConn.deleteStreamById(streamId);
         }
         sendNSFailed(streamConn, StatusCodes.NS_FAILED, err.getMessage(), name, streamId);
       }
     }
   } else {
     log.debug("Connection was not stream capable");
   }
 }