I am creating a class witch loads up a few sounds. However, isPlaying keeps on throwing an exception after a while and then stops playing that particular sound permanently, while other sounds keep playing OK.
public class MySound {
int m_IdMyId;
int m_ResId;
boolean m_IsLoaded;
MediaPlayer m_Media;
public MySound(int idMyId, int resId){
m_IdMyId = idMyId;
m_ResId = resId;
m_IsLoaded = false;
m_Media = null;
}
}
In this m_IdMyId is just an id for my game. m_ResId is something like R.raw.mysound1. m_IsLoaded I think is automatically set to true as I am loading synconously. m_Media is the MediaPlayer object.
I am calling stop() very regularly, as it is a game and I need to check every second or so to make sure certain sounds are stopped. It is here that it throws an exception when snd.m_Media.isPlaying() is called.
I cannot seem to access e to see what the error is.
Also I would like to know how I can set m_IsLoaded correctly. How do I know when the sound is fully loaded and ready to use?
Here is my management class:
public class MySoundManager {
MainActivity m_Context;
ArrayList<MySound> mySounds;
public MySoundManager(MainActivity context) {
m_Context = context;
mySounds = new ArrayList<MySound>();
mySounds.add(new MySound(8, R.raw.mysound1));
mySounds.add(new MySound(10, R.raw.mysound2));
mySounds.add(new MySound(22, R.raw.mysound3));
mySounds.add(new MySound(100, R.raw.click));
mySounds.add(new MySound(101, R.raw.error));
for(MySound mysound : mySounds) {
mysound.m_Media = MediaPlayer.create(m_Context, mysound.m_ResId); // no need to call prepare(); create() does that for you
mysound.m_IsLoaded = true;
}
}
// I call this when the main thread calls onResume
public void onResume(){
for(MySound mysound : mySounds) {
if(mysound.m_Media == null) {
mysound.m_Media = MediaPlayer.create(m_Context, mysound.m_ResId); // no need to call prepare(); create() does that for you
mysound.m_IsLoaded = true;
}
}
}
// I call this when the main thread calls onPause
public void onPause(){
for(MySound mysound : mySounds) {
if(mysound.m_Media != null) {
mysound.m_Media.stop();
mysound.m_Media.release();
mysound.m_Media = null;
}
}
}
public boolean IsAllLoaded(){
for(MySound mysound : mySounds) {
if(!mysound.m_IsLoaded) return false;
}
return true;
}
public MySound FindMySoundByIdMyId(int idMyId){
try {
for(MySound mysound : mySounds) {
if (mysound.m_IdMyId == idMyId) return mysound;
}
}catch(Exception e) {
MySound snd;
snd = null; // ToDo
}
return null;
}
public void play(int idMyId){
MySound snd;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null)
snd.m_Media.start();
}catch(IllegalStateException e) {
snd = null; // ToDo
}
}
public void pause(int idMyId){
MySound snd;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null &&
snd.m_Media.isPlaying())
snd.m_Media.pause();
}catch(IllegalStateException e) {
snd = null; // ToDo
}
}
public void pauseAll(){
try{
for (MySound mysound : mySounds) {
if(mysound.m_Media.isPlaying())
mysound.m_Media.pause();
}
}catch(IllegalStateException e) {
MySound snd;
snd = null; // ToDo
}
}
public boolean isPlaying(int idMyId, MySound[] fill){
MySound snd;
fill[0] = null;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null){
fill[0] = snd;
return snd.m_Media.isPlaying();
}
}catch(IllegalStateException e) {
snd = null; // ToDo
}
return false;
}
public void stop(int idMyId){
MySound snd;
try{
if((snd = FindMySoundByIdMyId(idMyId)) != null &&
snd.m_Media.isPlaying())
snd.m_Media.stop();
}catch(IllegalStateException e) {
snd = null; // ToDo
}
}
// The str is in the format
// number id, 1 = on 0 = off,dont play if this id playing;
public void PlaySound(String str) {
boolean isplaying;
int i, len, id, idDontPlay, milliNow;
String[] strARR = str.split(";");
String[] strARR2;
Integer[] tmpIntARR;
ArrayList<Integer[]> onARR = new ArrayList<Integer[]>();
ArrayList<Integer> offARR = new ArrayList<Integer>();
MySound snd;
for (i = 0, len = strARR.length; i < len; i++) {
if(strARR[i].length() <= 0) continue;
if((strARR2 = strARR[i].split(",")) != null &&
strARR2.length >= 3 &&
strARR2[0].length() > 0 &&
strARR2[1].length() > 0 &&
strARR2[2].length() > 0){
id = Integer.parseInt(strARR2[0]);
idDontPlay = Integer.parseInt(strARR2[2]);
tmpIntARR = new Integer[2];
tmpIntARR[0] = id;
tmpIntARR[1] = idDontPlay;
if(Integer.parseInt(strARR2[1]) == 1){
onARR.add(tmpIntARR);
} else offARR.add(id);
}
}
// Turn off all sounds that need to be turned off
for (i=0,len=offARR.size();i<len;i++) {
id = offARR.get(i);
stop(id);
}
// Turn all sounds that need to be turned on,
// but only if the sound that blocks a new sound is not playing
for (i=0,len=onARR.size();i<len;i++) {
tmpIntARR = onARR.get(i);
id = tmpIntARR[0];
idDontPlay = tmpIntARR[1];
// We dont play if the idDontPlay sound is already playing
if((snd = FindMySoundByIdMyId(idDontPlay)) != null &&
snd.m_Media.isPlaying())
continue;
if((snd = FindMySoundByIdMyId(id)) != null){
isplaying = snd.m_Media.isPlaying();
milliNow = snd.m_Media.getCurrentPosition();
if(milliNow > (snd.m_Media.getDuration() - 1000) ||
(!isplaying && milliNow > 0)){
snd.m_Media.seekTo(0); // Half a second inside
}
if(!isplaying) snd.m_Media.start();
}
}
}
}
Creating a MediaPlayer instance for every sound is not a good practice to get low latency, especially for short clips. MediaPlayer is for longer clips such as Music files it uses large buffer so, larger buffer means high latency. Also, there is AudioFocus mechanism on Android that may interfere your sound playing session. So, I strongly recommend you to use SoundPool to play short clips like game sounds.
Related
Working on media browser type of application where I read files from USB with custom drivers. File expose by NanoHTTPServer. Not important point here but just for information.
The following code logic works pretty well but it looks broken and start struggling with fast scrolling.
Is there any way to load videos frame faster and avoid hanging and delay in frames. Is there any flaws in this code? As I am using rxjava.
#Override
public void onBindViewHolder(BasicHolder holder,final int position) {
...
if(multiMedia.isImage()){
Glide.with(context)
.load(multiMedia.getUrl())
.crossFade()
.into(holder.imageThumbnail);
}else{
Bitmap bitmap = mThumbnailsCache.get(multiMedia.getUrl()+THUMBNAIL_AT_PERCENT);
if(bitmap == null || multiMedia.getLength() == 0){
//check for already running task
if(holder.imageThumbnail.getTag(R.string.tag_for_video) == null){
loadVideoThumbnail(holder,multiMedia,position);
}
}else {
holder.imageThumbnail.setImageBitmap(bitmap);
}
}
....
//this method will trigger rxjava task on io and set back results emitted by
private void loadVideoThumbnail(final BasicHolder holder, final MultiMedia multiMedia,final int position){
final SoftReference<BasicHolder> mHolderRef = new SoftReference<>(holder);
final Subscription sub = extractFrameAndDuration(multiMedia.getUrl(), THUMBNAIL_AT_PERCENT)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(emittedObject -> {
if (emittedObject == null || mHolderRef.get() == null) return;
if (mHolderRef.get().getLayoutPosition() != position) {
notifyItemChanged(position);
return;
}
if (emittedObject instanceof Bitmap) {
ImageView imageThumbnail = mHolderRef.get().imageThumbnail;
if (imageThumbnail.getTag(R.string.tag_for_video) != null) {
imageThumbnail.setTag(R.string.tag_for_video, null);
imageThumbnail.setImageBitmap((Bitmap) emittedObject);
}
} else {
multiMedia.setLength((long)emittedObject);
TextView textInfo = mHolderRef.get().textInfo;
if (textInfo.getTag() == Filetype.MOVIE) {
mHolderRef.get().viewHighlight.setData(multiMedia.getSavedClips(),multiMedia.getLength());
textInfo.setText(VideoUtils.getTotalClipDuration((long) emittedObject, App.context));
}
}
}, Throwable::printStackTrace);
if(reqSubQueue.size() > 8){
//cancel previous requests
reqSubQueue.pop().unsubscribe();
}
reqSubQueue.add(sub);
holder.imageThumbnail.setTag(R.string.tag_for_video,sub);
}
...
//this method will get thumbnail from video url
private Observable<Object> extractFrameAndDuration(String url, final long atPercent){
return Observable.create(subscriber -> {
final MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
subscriber.add(new Subscription() {
#Override
public void unsubscribe() {
//this will actually cancel loading
Observable.fromCallable(() -> {
mediaMetadataRetriever.release();
return true;
}).subscribeOn(Schedulers.io())
.subscribe();
}
#Override
public boolean isUnsubscribed() {
return false;
}
});
try{
mediaMetadataRetriever.setDataSource(url, new HashMap<>());
String durationString = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
final long duration = Long.parseLong(TextUtils.isEmpty(durationString)? "0": durationString);
//cache duration
clipsDurations.put(url,duration);
subscriber.onNext(duration);
long timeUs = (long) (duration / 100.0 * atPercent);
if(timeUs > duration) timeUs = duration;
Bitmap bitmap = mThumbnailsCache.get(url+THUMBNAIL_AT_PERCENT);
if(bitmap == null){
//1 milli sec = 1000 microseconds
bitmap = MediaUtils.getFrameFromVideoAt(mediaMetadataRetriever, timeUs * 1000);
if(bitmap != null){
bitmap = MediaUtils.resize(bitmap,thumbSize,thumbSize);
mThumbnailsCache.put(url+THUMBNAIL_AT_PERCENT,bitmap);
subscriber.onNext(bitmap);
}
}else {
subscriber.onNext(bitmap);
}
}
catch (Exception e){
e.printStackTrace();
}
finally{
if (mediaMetadataRetriever != null){
mediaMetadataRetriever.release();
}
}
//remove item from queue
subscriber.onCompleted();
reqSubQueue.remove(subscriber);
});
}
All requests get canceled in Activity.onStop. reqSubQueue is ArrayDeque
Edit method description is added
I am sure some pro-developers will find out flaws.
I have just started exploring google-play-services-turnbased APIs. Till now I have been successful in creating a match. But from the documentation I haven't been able to figure out how to player's score after he completes his turn.
This is my onClickStartMatch method.
public void onStartMatchClicked() {
Intent intent =
Games.TurnBasedMultiplayer.getSelectOpponentsIntent(mHelper.getApiClient(), 1, 7, true);
startActivityForResult(intent, RC_SELECT_PLAYERS);
}
This is my onActivityResult method in my main activity class.
if (request == RC_SELECT_PLAYERS) {
if (response != RESULT_OK) {
// user canceled
return;
}
// Get the invitee list.
final ArrayList<String> invitees =
data.getStringArrayListExtra(Games.EXTRA_PLAYER_IDS);
// Get auto-match criteria.
Bundle autoMatchCriteria = null;
int minAutoMatchPlayers = data.getIntExtra(
Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);
int maxAutoMatchPlayers = data.getIntExtra(
Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);
if (minAutoMatchPlayers > 0) {
autoMatchCriteria = RoomConfig.createAutoMatchCriteria(
minAutoMatchPlayers, maxAutoMatchPlayers, 0);
} else {
autoMatchCriteria = null;
}
TurnBasedMatchConfig tbmc = TurnBasedMatchConfig.builder()
.addInvitedPlayers(invitees)
.setAutoMatchCriteria(autoMatchCriteria)
.build();
// Create and start the match.
Games.TurnBasedMultiplayer
.createMatch(mHelper.getApiClient(), tbmc)
.setResultCallback(new MatchInitiatedCallback());
}
This is my MatchInitiatedCallback class
public class MatchInitiatedCallback implements
ResultCallback<TurnBasedMultiplayer.InitiateMatchResult>,OnTurnBasedMatchUpdateReceivedListener {
#Override
public void onResult(TurnBasedMultiplayer.InitiateMatchResult result) {
// Check if the status code is not success.
Status status = result.getStatus();
if (status.isSuccess()) {
Log.d("turnbased","Turn Based Match Initiated successfully with result: "+status.getStatusMessage());
return;
}
TurnBasedMatch match = result.getMatch();
// If this player is not the first player in this match, continue.
if (match.getData() != null) {
showTurnUI(match);
return;
}
// Otherwise, this is the first player. Initialize the game state.
initGame(match);
// Let the player take the first turn
showTurnUI(match);
}
public void showTurnUI(TurnBasedMatch match){
if(match.getStatus() == TurnBasedMatch.MATCH_STATUS_ACTIVE){
if(match.getTurnStatus() == TurnBasedMatch.MATCH_TURN_STATUS_MY_TURN){
turnBasedMatchData = match.getData();
Games.TurnBasedMultiplayer.takeTurn(mHelper.getApiClient(),match.getMatchId(), "score:400".getBytes(Charset.forName("UTF-16")),null).setResultCallback(updateMatchResult());
}
}
}
public void initGame(TurnBasedMatch match){
Games.TurnBasedMultiplayer.takeTurn(mHelper.getApiClient(),match.getMatchId(),"score:605".getBytes(Charset.forName("UTF-16")),match.getParticipantId(Games.Players.getCurrentPlayerId(mHelper.getApiClient()))).setResultCallback(updateMatchResult());
}
public ResultCallback<TurnBasedMultiplayer.UpdateMatchResult> updateMatchResult(){
return null;
}
#Override
public void onTurnBasedMatchReceived(TurnBasedMatch turnBasedMatch) {
Log.d("turn-based","Player played his turn");
}
#Override
public void onTurnBasedMatchRemoved(String s) {
}
}
}
Also it would helpful if some can properly explain how to continue a game a game from start and when to submit score and how.
Figured it out. This is how you can do it.
public byte[] persist() {
JSONObject retVal = new JSONObject();
try {
retVal.put("turnCounter", 2);
retVal.put("score1",100);
retVal.put("score2",200);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String st = retVal.toString();
Log.d(TAG, "==== PERSISTING\n" + st);
return st.getBytes(Charset.forName("UTF-8"));
}
Games.TurnBasedMultiplayer.takeTurn(mHelper.getApiClient(),match.getMatchId(),persist(),null).setResultCallback(updateMatchResult());
I have a problem closing my game after the last player close the last match. My turn scheme is:
Player A
Player B
Player B
Player A
Player A
Player B
The game works well but in turn "6" when player B try to close the match, player A always see the matsh as "my turn" and not as "completed"
here there is the code thar rules turns and game ended:
#Override
public void onGameEnd(final NMXGameData updatedData) {
super.onGameEnd(updatedData);
if (updatedData.getMatchNumber() == NMXGameConfig.MATCHES) {
boolean iWin = updatedData.getResultPoints()[1] > updatedData.getResultPoints()[0];
boolean tile = updatedData.getResultPoints()[1] == updatedData.getResultPoints()[0];
ParticipantResult opponentParticipantResult;
ParticipantResult myParticipantResult;
if (tile) {
opponentParticipantResult = new ParticipantResult(getOpponentId(), ParticipantResult.MATCH_RESULT_TIE, 1);
myParticipantResult = new ParticipantResult(getCurrentPlayerId(), ParticipantResult.MATCH_RESULT_TIE, 1);
} else {
if (iWin) {
opponentParticipantResult = new ParticipantResult(getOpponentId(), ParticipantResult.MATCH_RESULT_LOSS, 2);
myParticipantResult = new ParticipantResult(getCurrentPlayerId(), ParticipantResult.MATCH_RESULT_WIN, 1);
} else {
opponentParticipantResult = new ParticipantResult(getOpponentId(), ParticipantResult.MATCH_RESULT_WIN, 1);
myParticipantResult = new ParticipantResult(getCurrentPlayerId(), ParticipantResult.MATCH_RESULT_LOSS, 2);
}
}
ArrayList<ParticipantResult> participantResultArrayList = new ArrayList<>();
participantResultArrayList.add(opponentParticipantResult);
participantResultArrayList.add(myParticipantResult);
Games.TurnBasedMultiplayer.finishMatch(getApiClient(), match.getMatchId(), new Gson().toJson(updatedData).getBytes(), opponentParticipantResult, myParticipantResult).setResultCallback(new ResultCallback<TurnBasedMultiplayer.UpdateMatchResult>() {
#Override
public void onResult(TurnBasedMultiplayer.UpdateMatchResult updateMatchResult) {
finish();
}
});
} else if (updatedData.getMatchNumber() < NMXGameConfig.MATCHES) {
if (getNextPlayerIndex(updatedData.getMatchNumber()) != getNextPlayerIndex(updatedData.getMatchNumber() - 1)) {
Games.TurnBasedMultiplayer.takeTurn(getApiClient(), match.getMatchId(), new Gson().toJson(updatedData).getBytes(), getNextParticipantId());
} else {
Games.TurnBasedMultiplayer.takeTurn(getApiClient(), match.getMatchId(), new Gson().toJson(updatedData).getBytes(), getCurrentPlayerId());
startActivity(startNewOnlineGameIntent(this, updatedData, match.getMatchId()));
}
finish();
}
}
private String getCurrentPlayerId() {
return match.getParticipantId(Games.Players.getCurrentPlayerId(getApiClient()));
}
private String getOpponentId() {
for (String id : match.getParticipantIds()) {
if (!id.equals(getCurrentPlayerId())) {
return id;
}
}
return null;
}
private int getNextPlayerIndex(int nextRoundIndex) {
nextRoundIndex = nextRoundIndex + 1;
return (nextRoundIndex / 2) % 2;
}
I finally figured it out.
I don't know if that is the desired behavior but when in round 6 player_B calls:
Games.TurnBasedMultiplayer.finishMatch(getApiClient(), match.getMatchId(), new Gson().toJson(updatedData).getBytes(), opponentParticipantResult, myParticipantResult).setResultCallback(new ResultCallback<TurnBasedMultiplayer.UpdateMatchResult>() {
#Override
public void onResult(TurnBasedMultiplayer.UpdateMatchResult updateMatchResult) {
finish();
}
});
The turn goes to player_A that see that match as "my turn". At this point player A must call Games.TurnBasedMultiplayer.finishMatch(getApiClient(), match.getMatchId()) (without playing a real game) and the game is completed for both players
Hi I've read some post with same question but can't find the exact or I must say the answer I've been looking for. Well I just want to know how I can get the playback level of the audio file that is set on the mediaplayer. I already tried the int volume_level = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); but from what I see. I only get the current volume set on my device. Well what I want to achive is to add an animation that follows with level of my audio being played. Here's my code so far:
before the call of play audio method:
audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
the playback method:
public void playAudio(String record_path) throws IOException{
if(audioPlayer!=null && mpStatus == State.Paused){
/*play from paused state*/
audioPlayer.start();
mpStatus = State.Playing;
}
else
{
/*play from start of recording*/
setMediaPlayer(record_path);
audioPlayer.start();
mpStatus = State.Playing;
}
}
and the thread:
private class playBackRunnable extends Thread {
final long start_time = System.currentTimeMillis();
public void run() {
while(chk_play.isChecked()){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
final long elapsed = System.currentTimeMillis() - start_time;
final String elapsed_time = util.getAsTime((int) elapsed);
runOnUiThread(new Runnable() {
#Override
public void run() {
int volume_level = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
int amp = (int)(volume_level * 100.f)/100;
Log.v("Volume Level", String.valueOf(amp));
if(chk_play.isChecked()){
prog_volume.setProgress(amp);
//txt_rectime.setText(elapsed_time);
if(amp <= 40 ){
prog_volume.setProgressDrawable(getResources().getDrawable(R.drawable.progress_green));
}else if(amp <= 60){
prog_volume.setProgressDrawable(getResources().getDrawable(R.drawable.progress_yellow));
}else if(amp <= 80){
prog_volume.setProgressDrawable(getResources().getDrawable(R.drawable.progress_orange));
}else {
prog_volume.setProgressDrawable(getResources().getDrawable(R.drawable.progress_red));
}
}
}
});
}
}
}
Hope someone can help me with this. Thanks in advance.
EDIT:
Added audioPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); before audioPlayer.prepare() still not working.
The only solution I know uses the Visualizer class. For convenience reason, I suggest using AudioCapture.java from KitKat live wallpaper sources, which add a data processing layer over Visualizer. The project linked above also gives some examples of uses, and here is how I use it in myself for JUnits tests :
private int getAudioOutputAmplitude(int durationInSeconds) throws InterruptedException {
AudioCapture mAudioCapture = new AudioCapture(AudioCapture.TYPE_PCM, 1024);
mAudioCapture.start();
Thread.sleep(durationInSeconds * 1000);
int [] mVizData;
mVizData = mAudioCapture.getFormattedData(1, 1);
mAudioCapture.release();
int minValue = 0;
int maxValue = 0;
for (int value:mVizData){
if (value<minValue){
minValue = value;
} else if (value>maxValue){
maxValue = value;
}
}
return maxValue-minValue;
}
I am new in SIP call using RTP, now I am trying to send and receive
voice streams using RTP for sip call. I am done with connecting
two emulators and able to send INVITE and INVITE-ACK using jain sip.
After I got an Ack I want to start RTP for media streaming, I use the RtpPacket
function to send and receive
I use RtpFunction to send media with all RTP header like this:
byte Version;
boolean Padding;
boolean Extension;
byte CC;
boolean Marker;
byte PayloadType;
short SequenceNumber;
int TimeStamp;
Please give some ideas and actual links where I can find an answer.
This can be achieved in a simpler manner
AudioManager audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audio.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioGroup = new AudioGroup();
audioGroup.setMode(AudioGroup.MODE_ECHO_SUPPRESSION);
audioStream = new AudioStream(InetAddress.getByAddress(getLocalIPAddress()));
audioStream.setCodec(AudioCodec.PCMU);
audioStream.setMode(RtpStream.MODE_NORMAL);
audioStream.associate(InetAddress.getByName(SipStackAndroid.getRemoteIp()), REMOTE_PORT);
audioStream.join(audioGroup);
We send and receive RTP data using RTPpacket.
import javax.media.rtp.*;
import javax.media.rtp.rtcp.*;
import javax.media.rtp.event.*;
import javax.media.*;
import javax.media.protocol.*;
import java.net.InetAddress;
import javax.media.format.AudioFormat;
import com.sun.media.ui.*;
import java.util.Vector;
public class RTPSourceStream < RTPPlayerWindow > implements ReceiveStreamListener,
ControllerListener {
#SuppressWarnings("rawtypes")
Vector playerlist = new Vector();
#SuppressWarnings("deprecation")
SessionManager mgr = null;
boolean terminatedbyClose = false;
#SuppressWarnings("deprecation")
public SessionManager createManager(String address,
String sport,
String sttl,
boolean listener,
boolean sendlistener) {
return createManager(address,
new Integer(sport).intValue(),
new Integer(sttl).intValue(),
listener,
sendlistener);
}
#SuppressWarnings("deprecation")
public SessionManager createManager(String address,
int port,
int ttl,
boolean listener,
boolean sendlistener) {
mgr = (SessionManager) new com.sun.media.rtp.RTPSessionMgr();
if (mgr == null) return null;
mgr.addFormat(new AudioFormat(AudioFormat.DVI_RTP, 44100, 4, 1), 18);
if (listener) mgr.addReceiveStreamListener(this);
// if (sendlistener) new RTPSendStreamWindow(mgr);
// ask RTPSM to generate the local participants CNAME
String cname = mgr.generateCNAME();
String username = null;
try {
username = System.getProperty("user.name");
} catch (SecurityException e) {
username = "jmf-user";
}
// create our local Session Address
SessionAddress localaddr = new SessionAddress();
try {
InetAddress destaddr = InetAddress.getByName(address);
SessionAddress sessaddr = new SessionAddress(destaddr,
port,
destaddr,
port + 1);
SourceDescription[] userdesclist = new SourceDescription[] {
new SourceDescription(SourceDescription
.SOURCE_DESC_EMAIL,
"jmf-user#sun.com",
1,
false),
new SourceDescription(SourceDescription
.SOURCE_DESC_CNAME,
cname,
1,
false),
new
SourceDescription(SourceDescription.SOURCE_DESC_TOOL, "JMF RTP Player v2.0",
1,
false)
};
mgr.initSession(localaddr,
userdesclist,
0.05,
0.25);
mgr.startSession(sessaddr, ttl, null);
} catch (Exception e) {
System.err.println(e.getMessage());
return null;
}
return mgr;
}
public void update(ReceiveStreamEvent event) {
Player newplayer = null;
RTPPacket playerWindow = null;
// find the sourceRTPSM for this event
SessionManager source = (SessionManager) event.getSource();
// create a new player if a new recvstream is detected
if (event instanceof NewReceiveStreamEvent) {
String cname = "Java Media Player";
ReceiveStream stream = null;
try {
// get a handle over the ReceiveStream
stream = ((NewReceiveStreamEvent) event)
.getReceiveStream();
Participant part = stream.getParticipant();
if (part != null) cname = part.getCNAME();
// get a handle over the ReceiveStream datasource
DataSource dsource = stream.getDataSource();
// create a player by passing datasource to the
// Media Manager
newplayer = Manager.createPlayer(dsource);
System.out.println("created player " + newplayer);
} catch (Exception e) {
System.err.println("NewReceiveStreamEvent exception " +
e.getMessage());
return;
}
if (newplayer == null) return;
playerlist.addElement(newplayer);
newplayer.addControllerListener(this);
// send this player to player GUI
playerWindow = new RTPPacket(newplayer, cname);
}
}
public void controllerUpdate(ControllerEvent evt) {
// get a handle over controller, remove it from the player
// list.
// if player list is empty, close the sesssion manager.
if ((evt instanceof ControllerClosedEvent) ||
(evt instanceof ControllerErrorEvent) ||
(evt instanceof DeallocateEvent)) {
Player p = (Player) evt.getSourceController();
if (!terminatedbyClose) {
if (playerlist.contains(p))
playerlist.removeElement(p);
if ((playerlist.size() == 0) && (mgr != null))
mgr.closeSession("All players are closed");
}
}
}
public void closeManager() {
terminatedbyClose = true;
// first close all the players
for (int i = 0; i < playerlist.size(); i++) {
((Player) playerlist.elementAt(i)).close();
}
if (mgr != null) {
mgr.closeSession("RTP Session Terminated");
mgr = null;
}
}
class RTPPacket extends RTPSourceStream {
public RTPPacket(Player newplayer, String cname) {
// TODO Auto-generated constructor stub
}
}
}