NekoX/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java

457 lines
18 KiB
Java
Raw Normal View History

/*
* This is the source code of Telegram for Android v. 1.3.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2014.
*/
package org.telegram.messenger;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Vibrator;
import org.telegram.objects.MessageObject;
import org.telegram.ui.ApplicationLoader;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
public class MediaController implements NotificationCenter.NotificationCenterDelegate {
public static interface FileDownloadProgressListener {
public void onFailedDownload(String fileName);
public void onSuccessDownload(String fileName);
public void onProgressDownload(String fileName, float progress);
public int getObserverTag();
}
public final static int audioProgressDidChanged = 50001;
public final static int audioDidReset = 50002;
public final static int recordProgressChanged = 50003;
public static MediaController Instance = new MediaController();
private HashMap<String, ArrayList<WeakReference<FileDownloadProgressListener>>> loadingFileObservers = new HashMap<String, ArrayList<WeakReference<FileDownloadProgressListener>>>();
private HashMap<Integer, String> observersByTag = new HashMap<Integer, String>();
private boolean listenerInProgress = false;
private HashMap<String, FileDownloadProgressListener> addLaterArray = new HashMap<String, FileDownloadProgressListener>();
private ArrayList<FileDownloadProgressListener> deleteLaterArray = new ArrayList<FileDownloadProgressListener>();
private boolean isPaused = false;
private MediaPlayer audioPlayer = null;
private int lastProgress = 0;
private MessageObject playingMessageObject;
private MediaRecorder audioRecorder = null;
private TLRPC.TL_audio recordingAudio = null;
private File recordingAudioFile = null;
private long recordStartTime;
private long recordDialogId;
private final Integer sync = 1;
private int lastTag = 0;
public MediaController () {
NotificationCenter.Instance.addObserver(this, FileLoader.FileDidFailedLoad);
NotificationCenter.Instance.addObserver(this, FileLoader.FileDidLoaded);
NotificationCenter.Instance.addObserver(this, FileLoader.FileLoadProgressChanged);
2014-03-10 10:27:49 +01:00
if (ConnectionsManager.enableAudio) {
Timer progressTimer = new Timer();
progressTimer.schedule(new TimerTask() {
@Override
public void run() {
synchronized (sync) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (playingMessageObject != null && audioPlayer != null && !isPaused) {
try {
int progress = audioPlayer.getCurrentPosition();
if (progress <= lastProgress) {
return;
}
lastProgress = progress;
final float value = (float)lastProgress / (float)audioPlayer.getDuration();
playingMessageObject.audioProgress = value;
playingMessageObject.audioProgressSec = lastProgress / 1000;
NotificationCenter.Instance.postNotificationName(audioProgressDidChanged, playingMessageObject.messageOwner.id, value);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
2014-03-10 10:27:49 +01:00
}
if (audioRecorder != null) {
NotificationCenter.Instance.postNotificationName(recordProgressChanged, System.currentTimeMillis() - recordStartTime);
}
}
2014-03-10 10:27:49 +01:00
});
}
}
2014-03-10 10:27:49 +01:00
}, 100, 17);
}
}
public void cleanup() {
clenupPlayer(false);
}
public int generateObserverTag() {
return lastTag++;
}
public void addLoadingFileObserver(String fileName, FileDownloadProgressListener observer) {
if (listenerInProgress) {
addLaterArray.put(fileName, observer);
return;
}
removeLoadingFileObserver(observer);
ArrayList<WeakReference<FileDownloadProgressListener>> arrayList = loadingFileObservers.get(fileName);
if (arrayList == null) {
arrayList = new ArrayList<WeakReference<FileDownloadProgressListener>>();
loadingFileObservers.put(fileName, arrayList);
}
arrayList.add(new WeakReference<FileDownloadProgressListener>(observer));
observersByTag.put(observer.getObserverTag(), fileName);
}
public void removeLoadingFileObserver(FileDownloadProgressListener observer) {
if (listenerInProgress) {
deleteLaterArray.add(observer);
return;
}
String fileName = observersByTag.get(observer.getObserverTag());
if (fileName != null) {
ArrayList<WeakReference<FileDownloadProgressListener>> arrayList = loadingFileObservers.get(fileName);
if (arrayList != null) {
for (int a = 0; a < arrayList.size(); a++) {
WeakReference<FileDownloadProgressListener> reference = arrayList.get(a);
if (reference.get() == null || reference.get() == observer) {
arrayList.remove(a);
a--;
}
}
if (arrayList.isEmpty()) {
loadingFileObservers.remove(fileName);
}
}
observersByTag.remove(observer.getObserverTag());
}
}
private void processLaterArrays() {
for (HashMap.Entry<String, FileDownloadProgressListener> listener : addLaterArray.entrySet()) {
addLoadingFileObserver(listener.getKey(), listener.getValue());
}
addLaterArray.clear();
for (FileDownloadProgressListener listener : deleteLaterArray) {
removeLoadingFileObserver(listener);
}
deleteLaterArray.clear();
}
@Override
public void didReceivedNotification(int id, Object... args) {
if (id == FileLoader.FileDidFailedLoad) {
listenerInProgress = true;
String fileName = (String)args[0];
ArrayList<WeakReference<FileDownloadProgressListener>> arrayList = loadingFileObservers.get(fileName);
if (arrayList != null) {
for (WeakReference<FileDownloadProgressListener> reference : arrayList) {
if (reference.get() != null) {
reference.get().onFailedDownload(fileName);
observersByTag.remove(reference.get().getObserverTag());
}
}
loadingFileObservers.remove(fileName);
}
listenerInProgress = false;
processLaterArrays();
} else if (id == FileLoader.FileDidLoaded) {
listenerInProgress = true;
String fileName = (String)args[0];
ArrayList<WeakReference<FileDownloadProgressListener>> arrayList = loadingFileObservers.get(fileName);
if (arrayList != null) {
for (WeakReference<FileDownloadProgressListener> reference : arrayList) {
if (reference.get() != null) {
reference.get().onSuccessDownload(fileName);
observersByTag.remove(reference.get().getObserverTag());
}
}
loadingFileObservers.remove(fileName);
}
listenerInProgress = false;
processLaterArrays();
} else if (id == FileLoader.FileLoadProgressChanged) {
listenerInProgress = true;
String fileName = (String)args[0];
ArrayList<WeakReference<FileDownloadProgressListener>> arrayList = loadingFileObservers.get(fileName);
if (arrayList != null) {
Float progress = (Float)args[1];
for (WeakReference<FileDownloadProgressListener> reference : arrayList) {
if (reference.get() != null) {
reference.get().onProgressDownload(fileName, progress);
}
}
}
listenerInProgress = false;
processLaterArrays();
}
}
private void clenupPlayer(boolean notify) {
if (audioPlayer != null) {
try {
audioPlayer.stop();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
try {
audioPlayer.release();
audioPlayer = null;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
lastProgress = 0;
isPaused = false;
MessageObject lastFile = playingMessageObject;
playingMessageObject.audioProgress = 0.0f;
playingMessageObject.audioProgressSec = 0;
playingMessageObject = null;
if (notify) {
NotificationCenter.Instance.postNotificationName(audioDidReset, lastFile.messageOwner.id);
}
}
}
public boolean seekToProgress(MessageObject messageObject, float progress) {
if (audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id) {
return false;
}
try {
int seekTo = (int)(audioPlayer.getDuration() * progress);
audioPlayer.seekTo(seekTo);
lastProgress = seekTo;
} catch (Exception e) {
FileLog.e("tmessages", e);
return false;
}
return true;
}
public boolean playAudio(MessageObject messageObject) {
if (messageObject == null) {
return false;
}
if (audioPlayer != null && playingMessageObject != null && messageObject.messageOwner.id == playingMessageObject.messageOwner.id) {
if (isPaused) {
resumeAudio(messageObject);
}
return true;
}
clenupPlayer(true);
try {
audioPlayer = new MediaPlayer();
audioPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
File cacheFile = new File(Utilities.getCacheDir(), messageObject.getFileName());
audioPlayer.setDataSource(cacheFile.getAbsolutePath());
audioPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
clenupPlayer(true);
}
});
audioPlayer.prepare();
audioPlayer.start();
} catch (Exception e) {
FileLog.e("tmessages", e);
if (audioPlayer != null) {
audioPlayer.release();
audioPlayer = null;
isPaused = false;
playingMessageObject = null;
}
return false;
}
isPaused = false;
lastProgress = 0;
playingMessageObject = messageObject;
try {
if (playingMessageObject.audioProgress != 0) {
int seekTo = (int)(audioPlayer.getDuration() * playingMessageObject.audioProgress);
audioPlayer.seekTo(seekTo);
}
} catch (Exception e2) {
playingMessageObject.audioProgress = 0;
playingMessageObject.audioProgressSec = 0;
FileLog.e("tmessages", e2);
}
return true;
}
public void stopAudio() {
if (audioPlayer == null || playingMessageObject == null) {
return;
}
try {
audioPlayer.stop();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
try {
audioPlayer.release();
audioPlayer = null;
} catch (Exception e) {
FileLog.e("tmessages", e);
}
playingMessageObject = null;
isPaused = false;
}
public boolean pauseAudio(MessageObject messageObject) {
if (audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id) {
return false;
}
try {
audioPlayer.pause();
isPaused = true;
} catch (Exception e) {
FileLog.e("tmessages", e);
isPaused = false;
return false;
}
return true;
}
public boolean resumeAudio(MessageObject messageObject) {
if (audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id) {
return false;
}
try {
audioPlayer.start();
isPaused = false;
} catch (Exception e) {
FileLog.e("tmessages", e);
return false;
}
return true;
}
public boolean isPlayingAudio(MessageObject messageObject) {
return !(audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id);
}
public boolean isAudioPaused() {
return isPaused;
}
public boolean startRecording(long dialog_id) {
if (audioRecorder != null) {
return false;
}
recordingAudio = new TLRPC.TL_audio();
recordingAudio.dc_id = Integer.MIN_VALUE;
recordingAudio.id = UserConfig.lastLocalId;
recordingAudio.user_id = UserConfig.clientUserId;
UserConfig.lastLocalId--;
UserConfig.saveConfig(false);
recordingAudioFile = new File(Utilities.getCacheDir(), MessageObject.getAttachFileName(recordingAudio));
audioRecorder = new MediaRecorder();
audioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
audioRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
audioRecorder.setOutputFile(recordingAudioFile.getAbsolutePath());
if(android.os.Build.VERSION.SDK_INT >= 10) {
audioRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
} else {
audioRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
}
audioRecorder.setAudioSamplingRate(16000);
audioRecorder.setAudioChannels(1);
audioRecorder.setAudioEncodingBitRate(16000*4*1);
try {
audioRecorder.prepare();
audioRecorder.start();
recordStartTime = System.currentTimeMillis();
recordDialogId = dialog_id;
} catch (Exception e) {
FileLog.e("tmessages", e);
recordingAudio = null;
recordingAudioFile.delete();
recordingAudioFile = null;
try {
audioRecorder.release();
audioRecorder = null;
} catch (Exception e2) {
FileLog.e("tmessages", e2);
}
return false;
}
try {
Vibrator v = (Vibrator) ApplicationLoader.applicationContext.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(20);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return true;
}
public void stopRecording(boolean send) {
if (audioRecorder == null) {
return;
}
try {
audioRecorder.stop();
if (send) {
recordingAudio.date = ConnectionsManager.Instance.getCurrentTime();
recordingAudio.size = (int)recordingAudioFile.length();
recordingAudio.path = recordingAudioFile.getAbsolutePath();
long duration = System.currentTimeMillis() - recordStartTime;
recordingAudio.duration = (int)(duration / 1000);
if (duration > 500) {
MessagesController.Instance.sendMessage(recordingAudio, recordDialogId);
} else {
recordingAudioFile.delete();
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
if (recordingAudioFile != null) {
recordingAudioFile.delete();
}
}
try {
if (audioRecorder != null) {
audioRecorder.release();
audioRecorder = null;
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
recordingAudio = null;
recordingAudioFile = null;
try {
Vibrator v = (Vibrator) ApplicationLoader.applicationContext.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(20);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
}