2014-02-28 22:28:25 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
2014-03-22 22:31:55 +00:00
|
|
|
import android.app.ProgressDialog;
|
2014-02-28 22:28:25 +00:00
|
|
|
import android.content.Context;
|
2014-04-04 17:58:33 +00:00
|
|
|
import android.database.ContentObserver;
|
|
|
|
import android.database.Cursor;
|
2014-03-22 22:31:55 +00:00
|
|
|
import android.media.AudioFormat;
|
2014-02-28 22:28:25 +00:00
|
|
|
import android.media.AudioManager;
|
2014-03-22 22:31:55 +00:00
|
|
|
import android.media.AudioRecord;
|
|
|
|
import android.media.AudioTrack;
|
2014-02-28 22:28:25 +00:00
|
|
|
import android.media.MediaPlayer;
|
|
|
|
import android.media.MediaRecorder;
|
2014-03-22 22:31:55 +00:00
|
|
|
import android.media.audiofx.AutomaticGainControl;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Environment;
|
2014-04-05 17:11:44 +00:00
|
|
|
import android.os.ParcelFileDescriptor;
|
2014-02-28 22:28:25 +00:00
|
|
|
import android.os.Vibrator;
|
2014-04-04 17:58:33 +00:00
|
|
|
import android.provider.MediaStore;
|
2014-03-31 14:14:49 +00:00
|
|
|
import android.view.View;
|
2014-02-28 22:28:25 +00:00
|
|
|
|
|
|
|
import org.telegram.objects.MessageObject;
|
|
|
|
import org.telegram.ui.ApplicationLoader;
|
2014-03-31 14:14:49 +00:00
|
|
|
import org.telegram.ui.Cells.ChatMediaCell;
|
|
|
|
import org.telegram.ui.Views.GifDrawable;
|
2014-02-28 22:28:25 +00:00
|
|
|
|
|
|
|
import java.io.File;
|
2014-03-22 22:31:55 +00:00
|
|
|
import java.io.FileInputStream;
|
|
|
|
import java.io.FileOutputStream;
|
2014-02-28 22:28:25 +00:00
|
|
|
import java.lang.ref.WeakReference;
|
2014-03-22 22:31:55 +00:00
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
import java.nio.channels.FileChannel;
|
2014-02-28 22:28:25 +00:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.HashMap;
|
2014-04-05 17:11:44 +00:00
|
|
|
import java.util.Locale;
|
2014-02-28 22:28:25 +00:00
|
|
|
import java.util.Timer;
|
|
|
|
import java.util.TimerTask;
|
2014-03-22 22:31:55 +00:00
|
|
|
import java.util.concurrent.Semaphore;
|
2014-02-28 22:28:25 +00:00
|
|
|
|
|
|
|
public class MediaController implements NotificationCenter.NotificationCenterDelegate {
|
|
|
|
|
2014-03-22 22:31:55 +00:00
|
|
|
private native int startRecord(String path);
|
|
|
|
private native int writeFrame(ByteBuffer frame, int len);
|
|
|
|
private native void stopRecord();
|
|
|
|
private native int openOpusFile(String path);
|
|
|
|
private native int seekOpusFile(float position);
|
|
|
|
private native int isOpusFile(String path);
|
|
|
|
private native void closeOpusFile();
|
2014-03-27 14:25:53 +00:00
|
|
|
private native void readOpusFile(ByteBuffer buffer, int capacity, int[] args);
|
2014-03-22 22:31:55 +00:00
|
|
|
private native long getTotalPcmDuration();
|
|
|
|
|
2014-03-27 14:25:53 +00:00
|
|
|
public static int[] readArgs = new int[3];
|
2014-03-22 22:31:55 +00:00
|
|
|
|
2014-02-28 22:28:25 +00:00
|
|
|
public static interface FileDownloadProgressListener {
|
|
|
|
public void onFailedDownload(String fileName);
|
|
|
|
public void onSuccessDownload(String fileName);
|
|
|
|
public void onProgressDownload(String fileName, float progress);
|
2014-03-31 14:14:49 +00:00
|
|
|
public void onProgressUpload(String fileName, float progress, boolean isEncrypted);
|
2014-02-28 22:28:25 +00:00
|
|
|
public int getObserverTag();
|
|
|
|
}
|
|
|
|
|
2014-03-22 22:31:55 +00:00
|
|
|
private class AudioBuffer {
|
|
|
|
public AudioBuffer(int capacity) {
|
|
|
|
buffer = ByteBuffer.allocateDirect(capacity);
|
|
|
|
bufferBytes = new byte[capacity];
|
|
|
|
}
|
|
|
|
|
|
|
|
ByteBuffer buffer;
|
|
|
|
byte[] bufferBytes;
|
|
|
|
int size;
|
|
|
|
int finished;
|
|
|
|
long pcmOffset;
|
|
|
|
}
|
|
|
|
|
2014-02-28 22:28:25 +00:00
|
|
|
public final static int audioProgressDidChanged = 50001;
|
|
|
|
public final static int audioDidReset = 50002;
|
|
|
|
public final static int recordProgressChanged = 50003;
|
2014-03-23 00:09:24 +00:00
|
|
|
public final static int recordStarted = 50004;
|
|
|
|
public final static int recordStartError = 50005;
|
2014-03-23 00:24:19 +00:00
|
|
|
public final static int recordStopped = 50006;
|
2014-04-04 17:58:33 +00:00
|
|
|
public final static int screenshotTook = 50007;
|
2014-02-28 22:28:25 +00:00
|
|
|
|
|
|
|
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>();
|
2014-03-22 22:31:55 +00:00
|
|
|
private int lastTag = 0;
|
2014-02-28 22:28:25 +00:00
|
|
|
|
2014-03-31 14:14:49 +00:00
|
|
|
private GifDrawable currentGifDrawable;
|
|
|
|
private MessageObject currentGifMessageObject;
|
|
|
|
private ChatMediaCell currentMediaCell;
|
|
|
|
|
2014-02-28 22:28:25 +00:00
|
|
|
private boolean isPaused = false;
|
|
|
|
private MediaPlayer audioPlayer = null;
|
2014-03-22 22:31:55 +00:00
|
|
|
private AudioTrack audioTrackPlayer = null;
|
2014-02-28 22:28:25 +00:00
|
|
|
private int lastProgress = 0;
|
|
|
|
private MessageObject playingMessageObject;
|
2014-03-22 22:31:55 +00:00
|
|
|
private int playerBufferSize = 0;
|
|
|
|
private boolean decodingFinished = false;
|
|
|
|
private long currentTotalPcmDuration;
|
|
|
|
private long lastPlayPcm;
|
|
|
|
private int ignoreFirstProgress = 0;
|
2014-02-28 22:28:25 +00:00
|
|
|
|
2014-03-22 22:31:55 +00:00
|
|
|
private AudioRecord audioRecorder = null;
|
|
|
|
private Object audioGainObj = null;
|
2014-02-28 22:28:25 +00:00
|
|
|
private TLRPC.TL_audio recordingAudio = null;
|
|
|
|
private File recordingAudioFile = null;
|
|
|
|
private long recordStartTime;
|
2014-03-22 22:31:55 +00:00
|
|
|
private long recordTimeCount;
|
2014-02-28 22:28:25 +00:00
|
|
|
private long recordDialogId;
|
2014-03-22 22:31:55 +00:00
|
|
|
private DispatchQueue fileDecodingQueue;
|
|
|
|
private DispatchQueue playerQueue;
|
|
|
|
private ArrayList<AudioBuffer> usedPlayerBuffers = new ArrayList<AudioBuffer>();
|
|
|
|
private ArrayList<AudioBuffer> freePlayerBuffers = new ArrayList<AudioBuffer>();
|
|
|
|
private final Integer playerSync = 2;
|
|
|
|
private final Integer playerObjectSync = 3;
|
2014-02-28 22:28:25 +00:00
|
|
|
|
|
|
|
private final Integer sync = 1;
|
|
|
|
|
2014-03-22 22:31:55 +00:00
|
|
|
private ArrayList<ByteBuffer> recordBuffers = new ArrayList<ByteBuffer>();
|
|
|
|
private ByteBuffer fileBuffer;
|
|
|
|
private int recordBufferSize;
|
|
|
|
private boolean sendAfterDone;
|
2014-02-28 22:28:25 +00:00
|
|
|
|
2014-03-22 22:31:55 +00:00
|
|
|
private DispatchQueue recordQueue;
|
|
|
|
private DispatchQueue fileEncodingQueue;
|
|
|
|
private Runnable recordRunnable = new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (audioRecorder != null) {
|
|
|
|
ByteBuffer buffer = null;
|
|
|
|
if (!recordBuffers.isEmpty()) {
|
|
|
|
buffer = recordBuffers.get(0);
|
|
|
|
recordBuffers.remove(0);
|
|
|
|
} else {
|
|
|
|
buffer = ByteBuffer.allocateDirect(recordBufferSize);
|
|
|
|
}
|
|
|
|
buffer.rewind();
|
|
|
|
int len = audioRecorder.read(buffer, buffer.capacity());
|
|
|
|
if (len > 0) {
|
|
|
|
buffer.limit(len);
|
|
|
|
final ByteBuffer finalBuffer = buffer;
|
|
|
|
final boolean flush = len != buffer.capacity();
|
|
|
|
if (len != 0) {
|
|
|
|
fileEncodingQueue.postRunnable(new Runnable() {
|
2014-03-10 09:27:49 +00:00
|
|
|
@Override
|
|
|
|
public void run() {
|
2014-03-22 22:31:55 +00:00
|
|
|
while (finalBuffer.hasRemaining()) {
|
|
|
|
int oldLimit = -1;
|
|
|
|
if (finalBuffer.remaining() > fileBuffer.remaining()) {
|
|
|
|
oldLimit = finalBuffer.limit();
|
|
|
|
finalBuffer.limit(fileBuffer.remaining() + finalBuffer.position());
|
|
|
|
}
|
|
|
|
fileBuffer.put(finalBuffer);
|
|
|
|
if (fileBuffer.position() == fileBuffer.limit() || flush) {
|
|
|
|
if (writeFrame(fileBuffer, !flush ? fileBuffer.limit() : finalBuffer.position()) != 0) {
|
|
|
|
fileBuffer.rewind();
|
|
|
|
recordTimeCount += fileBuffer.limit() / 2 / 16;
|
2014-03-10 09:27:49 +00:00
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
}
|
|
|
|
if (oldLimit != -1) {
|
|
|
|
finalBuffer.limit(oldLimit);
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
2014-03-10 09:27:49 +00:00
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
recordQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
recordBuffers.add(finalBuffer);
|
|
|
|
}
|
|
|
|
});
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
2014-03-10 09:27:49 +00:00
|
|
|
});
|
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
recordQueue.postRunnable(recordRunnable);
|
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(recordProgressChanged, System.currentTimeMillis() - recordStartTime);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
recordBuffers.add(buffer);
|
|
|
|
stopRecordingInternal(sendAfterDone);
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-04-04 17:58:33 +00:00
|
|
|
private class InternalObserver extends ContentObserver {
|
|
|
|
public InternalObserver() {
|
|
|
|
super(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onChange(boolean selfChange) {
|
|
|
|
super.onChange(selfChange);
|
|
|
|
processMediaObserver(MediaStore.Images.Media.INTERNAL_CONTENT_URI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private class ExternalObserver extends ContentObserver {
|
|
|
|
public ExternalObserver() {
|
|
|
|
super(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onChange(boolean selfChange) {
|
|
|
|
super.onChange(selfChange);
|
|
|
|
processMediaObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private ExternalObserver externalObserver = null;
|
|
|
|
private InternalObserver internalObserver = null;
|
|
|
|
private long lastSecretChatEnterTime = 0;
|
|
|
|
private long lastSecretChatLeaveTime = 0;
|
|
|
|
private long lastMediaCheckTime = 0;
|
|
|
|
private TLRPC.EncryptedChat lastSecretChat = null;
|
|
|
|
private ArrayList<Long> lastSecretChatVisibleMessages = null;
|
|
|
|
private int startObserverToken = 0;
|
|
|
|
private StopMediaObserverRunnable stopMediaObserverRunnable = null;
|
|
|
|
private final class StopMediaObserverRunnable implements Runnable {
|
|
|
|
public int currentObserverToken = 0;
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (currentObserverToken == startObserverToken) {
|
|
|
|
try {
|
|
|
|
if (internalObserver != null) {
|
|
|
|
ApplicationLoader.applicationContext.getContentResolver().unregisterContentObserver(internalObserver);
|
|
|
|
internalObserver = null;
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (externalObserver != null) {
|
|
|
|
ApplicationLoader.applicationContext.getContentResolver().unregisterContentObserver(externalObserver);
|
|
|
|
externalObserver = null;
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private String[] mediaProjections = new String[] {
|
|
|
|
MediaStore.Images.ImageColumns.DATA,
|
|
|
|
MediaStore.Images.ImageColumns.DISPLAY_NAME,
|
|
|
|
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
|
|
|
|
MediaStore.Images.ImageColumns.DATE_TAKEN,
|
|
|
|
MediaStore.Images.ImageColumns.TITLE
|
|
|
|
};
|
|
|
|
|
2014-03-22 22:31:55 +00:00
|
|
|
private static volatile MediaController Instance = null;
|
|
|
|
public static MediaController getInstance() {
|
|
|
|
MediaController localInstance = Instance;
|
|
|
|
if (localInstance == null) {
|
|
|
|
synchronized (MediaController.class) {
|
|
|
|
localInstance = Instance;
|
|
|
|
if (localInstance == null) {
|
|
|
|
Instance = localInstance = new MediaController();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return localInstance;
|
|
|
|
}
|
|
|
|
|
|
|
|
public MediaController () {
|
|
|
|
try {
|
|
|
|
recordBufferSize = AudioRecord.getMinBufferSize(16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
|
|
|
|
if (recordBufferSize <= 0) {
|
|
|
|
recordBufferSize = 1280;
|
|
|
|
}
|
|
|
|
playerBufferSize = AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
|
|
|
|
if (playerBufferSize <= 0) {
|
|
|
|
playerBufferSize = 3840;
|
|
|
|
}
|
|
|
|
for (int a = 0; a < 5; a++) {
|
|
|
|
ByteBuffer buffer = ByteBuffer.allocateDirect(4096);
|
|
|
|
recordBuffers.add(buffer);
|
|
|
|
}
|
|
|
|
for (int a = 0; a < 3; a++) {
|
|
|
|
freePlayerBuffers.add(new AudioBuffer(playerBufferSize));
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
2014-03-10 09:27:49 +00:00
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
fileBuffer = ByteBuffer.allocateDirect(1920);
|
|
|
|
recordQueue = new DispatchQueue("recordQueue");
|
|
|
|
recordQueue.setPriority(Thread.MAX_PRIORITY);
|
|
|
|
fileEncodingQueue = new DispatchQueue("fileEncodingQueue");
|
|
|
|
fileEncodingQueue.setPriority(Thread.MAX_PRIORITY);
|
|
|
|
playerQueue = new DispatchQueue("playerQueue");
|
|
|
|
fileDecodingQueue = new DispatchQueue("fileDecodingQueue");
|
|
|
|
|
|
|
|
|
|
|
|
NotificationCenter.getInstance().addObserver(this, FileLoader.FileDidFailedLoad);
|
|
|
|
NotificationCenter.getInstance().addObserver(this, FileLoader.FileDidLoaded);
|
|
|
|
NotificationCenter.getInstance().addObserver(this, FileLoader.FileLoadProgressChanged);
|
2014-03-31 14:14:49 +00:00
|
|
|
NotificationCenter.getInstance().addObserver(this, FileLoader.FileUploadProgressChanged);
|
2014-03-22 22:31:55 +00:00
|
|
|
|
|
|
|
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 || audioTrackPlayer != null) && !isPaused) {
|
|
|
|
try {
|
|
|
|
if (ignoreFirstProgress != 0) {
|
|
|
|
ignoreFirstProgress--;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int progress = 0;
|
|
|
|
float value = 0;
|
|
|
|
if (audioPlayer != null) {
|
|
|
|
progress = audioPlayer.getCurrentPosition();
|
|
|
|
value = (float) lastProgress / (float) audioPlayer.getDuration();
|
|
|
|
if (progress <= lastProgress) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (audioTrackPlayer != null) {
|
|
|
|
progress = (int)(lastPlayPcm / 48.0f);
|
|
|
|
value = (float)lastPlayPcm / (float)currentTotalPcmDuration;
|
|
|
|
if (progress == lastProgress) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lastProgress = progress;
|
|
|
|
playingMessageObject.audioProgress = value;
|
|
|
|
playingMessageObject.audioProgressSec = lastProgress / 1000;
|
|
|
|
NotificationCenter.getInstance().postNotificationName(audioProgressDidChanged, playingMessageObject.messageOwner.id, value);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, 100, 17);
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void cleanup() {
|
|
|
|
clenupPlayer(false);
|
2014-03-31 14:14:49 +00:00
|
|
|
if (currentGifDrawable != null) {
|
|
|
|
currentGifDrawable.recycle();
|
|
|
|
currentGifDrawable = null;
|
|
|
|
}
|
|
|
|
currentMediaCell = null;
|
|
|
|
currentGifMessageObject = null;
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
|
|
|
|
2014-04-04 17:58:33 +00:00
|
|
|
public void startMediaObserver() {
|
|
|
|
if (android.os.Build.VERSION.SDK_INT > 0) { //disable while it's not perferct
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ApplicationLoader.applicationHandler.removeCallbacks(stopMediaObserverRunnable);
|
|
|
|
startObserverToken++;
|
|
|
|
try {
|
|
|
|
if (internalObserver == null) {
|
|
|
|
ApplicationLoader.applicationContext.getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, false, externalObserver = new ExternalObserver());
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (externalObserver == null) {
|
|
|
|
ApplicationLoader.applicationContext.getContentResolver().registerContentObserver(MediaStore.Images.Media.INTERNAL_CONTENT_URI, false, internalObserver = new InternalObserver());
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void stopMediaObserver() {
|
|
|
|
if (android.os.Build.VERSION.SDK_INT < 10) { //disable while it's not perferct
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (stopMediaObserverRunnable == null) {
|
|
|
|
stopMediaObserverRunnable = new StopMediaObserverRunnable();
|
|
|
|
}
|
|
|
|
stopMediaObserverRunnable.currentObserverToken = startObserverToken;
|
|
|
|
ApplicationLoader.applicationHandler.postDelayed(stopMediaObserverRunnable, 5000);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void processMediaObserver(Uri uri) {
|
|
|
|
try {
|
|
|
|
Cursor cursor = ApplicationLoader.applicationContext.getContentResolver().query(uri, mediaProjections, null, null, "date_added DESC LIMIT 1");
|
|
|
|
final ArrayList<Long> screenshotDates = new ArrayList<Long>();
|
|
|
|
if (cursor != null) {
|
|
|
|
while (cursor.moveToNext()) {
|
|
|
|
String val = "";
|
|
|
|
String data = cursor.getString(0);
|
|
|
|
String display_name = cursor.getString(1);
|
|
|
|
String album_name = cursor.getString(2);
|
|
|
|
String title = cursor.getString(4);
|
|
|
|
long date = cursor.getLong(3);
|
|
|
|
if (data != null && data.toLowerCase().contains("screenshot") ||
|
|
|
|
display_name != null && display_name.toLowerCase().contains("screenshot") ||
|
|
|
|
album_name != null && album_name.toLowerCase().contains("screenshot") ||
|
|
|
|
title != null && title.toLowerCase().contains("screenshot")) {
|
|
|
|
/*BitmapRegionDecoder bitmapRegionDecoder = null;
|
|
|
|
boolean added = false;
|
|
|
|
try {
|
|
|
|
int waitCount = 0;
|
|
|
|
while (waitCount < 5 && bitmapRegionDecoder == null) {
|
|
|
|
try {
|
|
|
|
bitmapRegionDecoder = BitmapRegionDecoder.newInstance(data, true);
|
|
|
|
if (bitmapRegionDecoder != null) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
Thread.sleep(1000);
|
|
|
|
}
|
|
|
|
if (bitmapRegionDecoder != null) {
|
|
|
|
Bitmap bitmap = bitmapRegionDecoder.decodeRegion(new Rect(0, 0, Utilities.dp(44), Utilities.dp(44)), null);
|
|
|
|
int w = bitmap.getWidth();
|
|
|
|
int h = bitmap.getHeight();
|
|
|
|
for (int y = 0; y < h; y++) {
|
|
|
|
int rowCount = 0;
|
|
|
|
for (int x = 0; x < w; x++) {
|
|
|
|
int px = bitmap.getPixel(x, y);
|
|
|
|
if (px == 0xffffffff) {
|
|
|
|
rowCount++;
|
|
|
|
} else {
|
|
|
|
rowCount = 0;
|
|
|
|
}
|
|
|
|
if (rowCount > 8) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rowCount > 8) {
|
|
|
|
screenshotDates.add(date);
|
|
|
|
added = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bitmapRegionDecoder.recycle();
|
|
|
|
try {
|
|
|
|
if (bitmap != null) {
|
|
|
|
bitmap.recycle();
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
try {
|
|
|
|
if (bitmapRegionDecoder != null) {
|
|
|
|
bitmapRegionDecoder.recycle();
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
}
|
|
|
|
if (!added) {
|
|
|
|
screenshotDates.add(date);
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
screenshotDates.add(date);
|
|
|
|
}
|
|
|
|
FileLog.e("tmessages", "screenshot!");
|
|
|
|
}
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
if (!screenshotDates.isEmpty()) {
|
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(screenshotTook);
|
|
|
|
checkScreenshots(screenshotDates);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void checkScreenshots(ArrayList<Long> dates) {
|
|
|
|
if (dates == null || dates.isEmpty() || lastSecretChatEnterTime == 0 || lastSecretChat == null || !(lastSecretChat instanceof TLRPC.TL_encryptedChat)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
long dt = 2000;
|
|
|
|
boolean send = false;
|
|
|
|
for (Long date : dates) {
|
|
|
|
if (lastMediaCheckTime != 0 && date <= lastMediaCheckTime) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (date >= lastSecretChatEnterTime) {
|
|
|
|
if (lastSecretChatLeaveTime == 0 || date <= lastSecretChatLeaveTime + dt) {
|
|
|
|
lastMediaCheckTime = Math.max(lastMediaCheckTime, date);
|
|
|
|
send = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (send) {
|
|
|
|
MessagesController.getInstance().sendScreenshotMessage(lastSecretChat, lastSecretChatVisibleMessages);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setLastEncryptedChatParams(long enterTime, long leaveTime, TLRPC.EncryptedChat encryptedChat, ArrayList<Long> visibleMessages) {
|
|
|
|
lastSecretChatEnterTime = enterTime;
|
|
|
|
lastSecretChatLeaveTime = leaveTime;
|
|
|
|
lastSecretChat = encryptedChat;
|
|
|
|
lastSecretChatVisibleMessages = visibleMessages;
|
|
|
|
}
|
|
|
|
|
2014-02-28 22:28:25 +00:00
|
|
|
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();
|
2014-03-31 14:14:49 +00:00
|
|
|
} else if (id == FileLoader.FileUploadProgressChanged) {
|
|
|
|
String location = (String)args[0];
|
|
|
|
listenerInProgress = true;
|
|
|
|
String fileName = (String)args[0];
|
|
|
|
ArrayList<WeakReference<FileDownloadProgressListener>> arrayList = loadingFileObservers.get(fileName);
|
|
|
|
if (arrayList != null) {
|
|
|
|
Float progress = (Float)args[1];
|
|
|
|
Boolean enc = (Boolean)args[2];
|
|
|
|
for (WeakReference<FileDownloadProgressListener> reference : arrayList) {
|
|
|
|
if (reference.get() != null) {
|
|
|
|
reference.get().onProgressUpload(fileName, progress, enc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
listenerInProgress = false;
|
|
|
|
processLaterArrays();
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-22 22:31:55 +00:00
|
|
|
private void checkDecoderQueue() {
|
|
|
|
fileDecodingQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (decodingFinished) {
|
|
|
|
checkPlayerQueue();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
boolean was = false;
|
|
|
|
while (true) {
|
|
|
|
AudioBuffer buffer = null;
|
|
|
|
synchronized (playerSync) {
|
|
|
|
if (!freePlayerBuffers.isEmpty()) {
|
|
|
|
buffer = freePlayerBuffers.get(0);
|
|
|
|
freePlayerBuffers.remove(0);
|
|
|
|
}
|
|
|
|
if (!usedPlayerBuffers.isEmpty()) {
|
|
|
|
was = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (buffer != null) {
|
2014-03-27 14:25:53 +00:00
|
|
|
readOpusFile(buffer.buffer, playerBufferSize, readArgs);
|
|
|
|
buffer.size = readArgs[0];
|
|
|
|
buffer.pcmOffset = readArgs[1];
|
|
|
|
buffer.finished = readArgs[2];
|
2014-03-22 22:31:55 +00:00
|
|
|
if (buffer.finished == 1) {
|
|
|
|
decodingFinished = true;
|
|
|
|
}
|
|
|
|
if (buffer.size != 0) {
|
|
|
|
buffer.buffer.rewind();
|
|
|
|
buffer.buffer.get(buffer.bufferBytes);
|
|
|
|
synchronized (playerSync) {
|
|
|
|
usedPlayerBuffers.add(buffer);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
synchronized (playerSync) {
|
|
|
|
freePlayerBuffers.add(buffer);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
was = true;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (was) {
|
|
|
|
checkPlayerQueue();
|
|
|
|
}
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private void checkPlayerQueue() {
|
|
|
|
playerQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
synchronized (playerObjectSync) {
|
|
|
|
if (audioTrackPlayer == null || audioTrackPlayer.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AudioBuffer buffer = null;
|
|
|
|
synchronized (playerSync) {
|
|
|
|
if (!usedPlayerBuffers.isEmpty()) {
|
|
|
|
buffer = usedPlayerBuffers.get(0);
|
|
|
|
usedPlayerBuffers.remove(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buffer != null) {
|
|
|
|
int count = 0;
|
|
|
|
try {
|
|
|
|
count = audioTrackPlayer.write(buffer.bufferBytes, 0, buffer.size);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count > 0) {
|
|
|
|
final long pcm = buffer.pcmOffset;
|
|
|
|
final int marker = buffer.finished == 1 ? buffer.size : -1;
|
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
lastPlayPcm = pcm;
|
|
|
|
if (marker != -1) {
|
|
|
|
if (audioTrackPlayer != null) {
|
|
|
|
audioTrackPlayer.setNotificationMarkerPosition(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buffer.finished != 1) {
|
|
|
|
checkPlayerQueue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (buffer == null || buffer != null && buffer.finished != 1) {
|
|
|
|
checkDecoderQueue();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buffer != null) {
|
|
|
|
synchronized (playerSync) {
|
|
|
|
freePlayerBuffers.add(buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private void clenupPlayer(boolean notify) {
|
|
|
|
if (audioPlayer != null || audioTrackPlayer != null) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
} else if (audioTrackPlayer != null) {
|
|
|
|
synchronized (playerObjectSync) {
|
|
|
|
try {
|
|
|
|
audioTrackPlayer.pause();
|
|
|
|
audioTrackPlayer.flush();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
audioTrackPlayer.release();
|
|
|
|
audioTrackPlayer = null;
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
|
|
|
lastProgress = 0;
|
|
|
|
isPaused = false;
|
|
|
|
MessageObject lastFile = playingMessageObject;
|
|
|
|
playingMessageObject.audioProgress = 0.0f;
|
|
|
|
playingMessageObject.audioProgressSec = 0;
|
|
|
|
playingMessageObject = null;
|
|
|
|
if (notify) {
|
2014-03-22 22:31:55 +00:00
|
|
|
NotificationCenter.getInstance().postNotificationName(audioDidReset, lastFile.messageOwner.id);
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-22 22:31:55 +00:00
|
|
|
private void seekOpusPlayer(final float progress) {
|
|
|
|
if (currentTotalPcmDuration * progress == currentTotalPcmDuration) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
audioTrackPlayer.pause();
|
|
|
|
audioTrackPlayer.flush();
|
|
|
|
fileDecodingQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
seekOpusFile(progress);
|
|
|
|
synchronized (playerSync) {
|
|
|
|
freePlayerBuffers.addAll(usedPlayerBuffers);
|
|
|
|
usedPlayerBuffers.clear();
|
|
|
|
}
|
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
ignoreFirstProgress = 3;
|
|
|
|
//audioTrackPlayer.setNotificationMarkerPosition((int)(currentTotalPcmDuration * (1 - playingMessageObject.audioProgress)));
|
|
|
|
lastPlayPcm = (long)(currentTotalPcmDuration * progress);
|
|
|
|
if (audioTrackPlayer != null) {
|
|
|
|
audioTrackPlayer.play();
|
|
|
|
}
|
|
|
|
lastProgress = (int)(currentTotalPcmDuration / 48.0f * progress);
|
|
|
|
checkPlayerQueue();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2014-02-28 22:28:25 +00:00
|
|
|
public boolean seekToProgress(MessageObject messageObject, float progress) {
|
2014-03-22 22:31:55 +00:00
|
|
|
if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id) {
|
2014-02-28 22:28:25 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
try {
|
2014-03-22 22:31:55 +00:00
|
|
|
if (audioPlayer != null) {
|
|
|
|
int seekTo = (int) (audioPlayer.getDuration() * progress);
|
|
|
|
audioPlayer.seekTo(seekTo);
|
|
|
|
lastProgress = seekTo;
|
|
|
|
} else if (audioTrackPlayer != null) {
|
|
|
|
seekOpusPlayer(progress);
|
|
|
|
}
|
2014-02-28 22:28:25 +00:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean playAudio(MessageObject messageObject) {
|
|
|
|
if (messageObject == null) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
if ((audioTrackPlayer != null || audioPlayer != null) && playingMessageObject != null && messageObject.messageOwner.id == playingMessageObject.messageOwner.id) {
|
2014-02-28 22:28:25 +00:00
|
|
|
if (isPaused) {
|
|
|
|
resumeAudio(messageObject);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
clenupPlayer(true);
|
2014-03-22 22:31:55 +00:00
|
|
|
final File cacheFile = new File(Utilities.getCacheDir(), messageObject.getFileName());
|
|
|
|
|
|
|
|
if (isOpusFile(cacheFile.getAbsolutePath()) == 1) {
|
|
|
|
synchronized (playerObjectSync) {
|
|
|
|
try {
|
|
|
|
ignoreFirstProgress = 3;
|
|
|
|
final Semaphore semaphore = new Semaphore(0);
|
|
|
|
final Boolean[] result = new Boolean[1];
|
|
|
|
fileDecodingQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
result[0] = openOpusFile(cacheFile.getAbsolutePath()) != 0;
|
|
|
|
semaphore.release();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
semaphore.acquire();
|
|
|
|
|
|
|
|
if (!result[0]) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
currentTotalPcmDuration = getTotalPcmDuration();
|
|
|
|
|
|
|
|
audioTrackPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, playerBufferSize, AudioTrack.MODE_STREAM);
|
|
|
|
//audioTrackPlayer.setNotificationMarkerPosition((int)currentTotalPcmDuration);
|
|
|
|
audioTrackPlayer.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() {
|
|
|
|
@Override
|
|
|
|
public void onMarkerReached(AudioTrack audioTrack) {
|
|
|
|
clenupPlayer(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPeriodicNotification(AudioTrack audioTrack) {
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
audioTrackPlayer.play();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
if (audioTrackPlayer != null) {
|
|
|
|
audioTrackPlayer.release();
|
|
|
|
audioTrackPlayer = null;
|
|
|
|
isPaused = false;
|
|
|
|
playingMessageObject = null;
|
|
|
|
}
|
|
|
|
return false;
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
audioPlayer = new MediaPlayer();
|
|
|
|
audioPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
|
|
|
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;
|
|
|
|
}
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isPaused = false;
|
|
|
|
lastProgress = 0;
|
2014-03-22 22:31:55 +00:00
|
|
|
lastPlayPcm = 0;
|
2014-02-28 22:28:25 +00:00
|
|
|
playingMessageObject = messageObject;
|
|
|
|
|
2014-03-22 22:31:55 +00:00
|
|
|
if (audioPlayer != null) {
|
|
|
|
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);
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
} else if (audioTrackPlayer != null) {
|
|
|
|
if (playingMessageObject.audioProgress == 1) {
|
|
|
|
playingMessageObject.audioProgress = 0;
|
|
|
|
}
|
|
|
|
//audioTrackPlayer.setNotificationMarkerPosition((int)(currentTotalPcmDuration * (1 - playingMessageObject.audioProgress)));
|
|
|
|
fileDecodingQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (playingMessageObject.audioProgress != 0) {
|
|
|
|
lastPlayPcm = (long)(currentTotalPcmDuration * playingMessageObject.audioProgress);
|
|
|
|
seekOpusFile(playingMessageObject.audioProgress);
|
|
|
|
}
|
|
|
|
synchronized (playerSync) {
|
|
|
|
freePlayerBuffers.addAll(usedPlayerBuffers);
|
|
|
|
usedPlayerBuffers.clear();
|
|
|
|
}
|
|
|
|
decodingFinished = false;
|
|
|
|
checkPlayerQueue();
|
|
|
|
}
|
|
|
|
});
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void stopAudio() {
|
2014-03-22 22:31:55 +00:00
|
|
|
if (audioTrackPlayer == null && audioPlayer == null || playingMessageObject == null) {
|
2014-02-28 22:28:25 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
try {
|
2014-03-22 22:31:55 +00:00
|
|
|
if (audioPlayer != null) {
|
|
|
|
audioPlayer.stop();
|
|
|
|
} else if (audioTrackPlayer != null) {
|
|
|
|
audioTrackPlayer.pause();
|
|
|
|
audioTrackPlayer.flush();
|
|
|
|
}
|
2014-02-28 22:28:25 +00:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
try {
|
2014-03-22 22:31:55 +00:00
|
|
|
if (audioPlayer != null) {
|
|
|
|
audioPlayer.release();
|
|
|
|
audioPlayer = null;
|
|
|
|
} else if (audioTrackPlayer != null) {
|
|
|
|
synchronized (playerObjectSync) {
|
|
|
|
audioTrackPlayer.release();
|
|
|
|
audioTrackPlayer = null;
|
|
|
|
}
|
|
|
|
}
|
2014-02-28 22:28:25 +00:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
playingMessageObject = null;
|
|
|
|
isPaused = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean pauseAudio(MessageObject messageObject) {
|
2014-03-22 22:31:55 +00:00
|
|
|
if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id) {
|
2014-02-28 22:28:25 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
try {
|
2014-03-22 22:31:55 +00:00
|
|
|
if (audioPlayer != null) {
|
|
|
|
audioPlayer.pause();
|
|
|
|
} else if (audioTrackPlayer != null) {
|
|
|
|
audioTrackPlayer.pause();
|
|
|
|
}
|
2014-02-28 22:28:25 +00:00
|
|
|
isPaused = true;
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
isPaused = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean resumeAudio(MessageObject messageObject) {
|
2014-03-22 22:31:55 +00:00
|
|
|
if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id) {
|
2014-02-28 22:28:25 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
try {
|
2014-03-22 22:31:55 +00:00
|
|
|
if (audioPlayer != null) {
|
|
|
|
audioPlayer.start();
|
|
|
|
} else if (audioTrackPlayer != null) {
|
|
|
|
audioTrackPlayer.play();
|
|
|
|
checkPlayerQueue();
|
|
|
|
}
|
2014-02-28 22:28:25 +00:00
|
|
|
isPaused = false;
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isPlayingAudio(MessageObject messageObject) {
|
2014-03-22 22:31:55 +00:00
|
|
|
return !(audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id);
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isAudioPaused() {
|
|
|
|
return isPaused;
|
|
|
|
}
|
|
|
|
|
2014-03-23 00:09:24 +00:00
|
|
|
public void startRecording(final long dialog_id) {
|
2014-02-28 22:28:25 +00:00
|
|
|
try {
|
|
|
|
Vibrator v = (Vibrator) ApplicationLoader.applicationContext.getSystemService(Context.VIBRATOR_SERVICE);
|
|
|
|
v.vibrate(20);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
|
2014-03-22 22:31:55 +00:00
|
|
|
recordQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (audioRecorder != null) {
|
2014-03-23 00:09:24 +00:00
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(recordStartError);
|
|
|
|
}
|
|
|
|
});
|
2014-03-22 22:31:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (startRecord(recordingAudioFile.getAbsolutePath()) == 0) {
|
2014-03-23 00:09:24 +00:00
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(recordStartError);
|
|
|
|
}
|
|
|
|
});
|
2014-03-22 22:31:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
audioRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, recordBufferSize * 10);
|
|
|
|
recordStartTime = System.currentTimeMillis();
|
|
|
|
recordTimeCount = 0;
|
|
|
|
recordDialogId = dialog_id;
|
|
|
|
fileBuffer.rewind();
|
|
|
|
|
2014-03-26 20:16:28 +00:00
|
|
|
if (android.os.Build.VERSION.SDK_INT >= 16) {
|
|
|
|
File f = new File("/vendor/lib/libaudioeffect_jni.so");
|
|
|
|
File f2 = new File("/system/lib/libaudioeffect_jni.so");
|
|
|
|
if (f.exists() || f2.exists()) {
|
|
|
|
AutomaticGainControl agc = null;
|
2014-03-22 22:31:55 +00:00
|
|
|
try {
|
2014-03-26 20:16:28 +00:00
|
|
|
if (AutomaticGainControl.isAvailable()) {
|
|
|
|
agc = AutomaticGainControl.create(audioRecorder.getAudioSessionId());
|
|
|
|
agc.setEnabled(true);
|
|
|
|
audioGainObj = agc;
|
2014-03-22 22:31:55 +00:00
|
|
|
}
|
2014-03-26 20:16:28 +00:00
|
|
|
} catch (Exception e) {
|
|
|
|
try {
|
|
|
|
if (agc != null) {
|
|
|
|
agc.release();
|
|
|
|
agc = null;
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
}
|
|
|
|
FileLog.e("tmessages", e);
|
2014-03-22 22:31:55 +00:00
|
|
|
}
|
|
|
|
}
|
2014-03-26 20:16:28 +00:00
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
|
|
|
|
audioRecorder.startRecording();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
recordingAudio = null;
|
|
|
|
stopRecord();
|
2014-02-28 22:28:25 +00:00
|
|
|
recordingAudioFile.delete();
|
2014-03-22 22:31:55 +00:00
|
|
|
recordingAudioFile = null;
|
|
|
|
try {
|
|
|
|
audioRecorder.release();
|
|
|
|
audioRecorder = null;
|
|
|
|
} catch (Exception e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (android.os.Build.VERSION.SDK_INT >= 16 && audioGainObj != null) {
|
|
|
|
AutomaticGainControl agc = (AutomaticGainControl)audioGainObj;
|
|
|
|
try {
|
|
|
|
if (agc != null) {
|
|
|
|
agc.release();
|
|
|
|
agc = null;
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-23 00:09:24 +00:00
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(recordStartError);
|
|
|
|
}
|
|
|
|
});
|
2014-03-22 22:31:55 +00:00
|
|
|
return;
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
|
|
|
|
recordQueue.postRunnable(recordRunnable);
|
2014-03-23 00:09:24 +00:00
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(recordStarted);
|
|
|
|
}
|
|
|
|
});
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
2014-03-23 00:24:19 +00:00
|
|
|
});
|
2014-03-22 22:31:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void stopRecordingInternal(final boolean send) {
|
|
|
|
if (send) {
|
|
|
|
final TLRPC.TL_audio audioToSend = recordingAudio;
|
|
|
|
final File recordingAudioFileToSend = recordingAudioFile;
|
|
|
|
fileEncodingQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
stopRecord();
|
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
audioToSend.date = ConnectionsManager.getInstance().getCurrentTime();
|
|
|
|
audioToSend.size = (int) recordingAudioFileToSend.length();
|
|
|
|
audioToSend.path = recordingAudioFileToSend.getAbsolutePath();
|
|
|
|
long duration = recordTimeCount;
|
|
|
|
audioToSend.duration = (int) (duration / 1000);
|
|
|
|
if (duration > 700) {
|
|
|
|
MessagesController.getInstance().sendMessage(audioToSend, recordDialogId);
|
|
|
|
} else {
|
|
|
|
recordingAudioFileToSend.delete();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (audioRecorder != null) {
|
|
|
|
audioRecorder.release();
|
|
|
|
audioRecorder = null;
|
|
|
|
}
|
2014-03-22 22:31:55 +00:00
|
|
|
if (android.os.Build.VERSION.SDK_INT >= 16 && audioGainObj != null) {
|
|
|
|
AutomaticGainControl agc = (AutomaticGainControl)audioGainObj;
|
|
|
|
try {
|
|
|
|
if (agc != null) {
|
|
|
|
agc.release();
|
|
|
|
agc = null;
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
}
|
|
|
|
}
|
2014-02-28 22:28:25 +00:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
recordingAudio = null;
|
|
|
|
recordingAudioFile = null;
|
2014-03-22 22:31:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void stopRecording(final boolean send) {
|
|
|
|
recordQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (audioRecorder == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//recordTimeCount = System.currentTimeMillis() - recordStartTime;
|
|
|
|
try {
|
|
|
|
sendAfterDone = send;
|
|
|
|
audioRecorder.stop();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
if (recordingAudioFile != null) {
|
|
|
|
recordingAudioFile.delete();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!send) {
|
|
|
|
stopRecordingInternal(false);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
Vibrator v = (Vibrator) ApplicationLoader.applicationContext.getSystemService(Context.VIBRATOR_SERVICE);
|
|
|
|
v.vibrate(20);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
2014-03-23 00:24:19 +00:00
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
NotificationCenter.getInstance().postNotificationName(recordStopped);
|
|
|
|
}
|
|
|
|
});
|
2014-03-22 22:31:55 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2014-04-03 21:18:54 +00:00
|
|
|
public static void saveFile(String path, String fullPath, Context context, final int type, final String name) {
|
|
|
|
if (path == null && fullPath == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
File file = null;
|
|
|
|
if (fullPath != null && fullPath.length() != 0) {
|
|
|
|
file = new File(fullPath);
|
|
|
|
if (!file.exists()) {
|
|
|
|
file = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (file == null) {
|
|
|
|
file = new File(Utilities.getCacheDir(), path);
|
|
|
|
}
|
|
|
|
|
|
|
|
final File sourceFile = file;
|
2014-03-22 22:31:55 +00:00
|
|
|
if (sourceFile.exists()) {
|
|
|
|
ProgressDialog progressDialog = null;
|
|
|
|
if (context != null) {
|
|
|
|
progressDialog = new ProgressDialog(context);
|
|
|
|
progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading));
|
|
|
|
progressDialog.setCanceledOnTouchOutside(false);
|
|
|
|
progressDialog.setCancelable(false);
|
|
|
|
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
|
|
|
progressDialog.setMax(100);
|
|
|
|
progressDialog.show();
|
|
|
|
}
|
|
|
|
|
|
|
|
final ProgressDialog finalProgress = progressDialog;
|
|
|
|
|
|
|
|
Utilities.globalQueue.postRunnable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
File destFile = null;
|
|
|
|
if (type == 0) {
|
|
|
|
destFile = Utilities.generatePicturePath();
|
|
|
|
} else if (type == 1) {
|
|
|
|
destFile = Utilities.generateVideoPath();
|
|
|
|
} else if (type == 2) {
|
|
|
|
File f = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
|
|
|
destFile = new File(f, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!destFile.exists()) {
|
|
|
|
destFile.createNewFile();
|
|
|
|
}
|
|
|
|
FileChannel source = null;
|
|
|
|
FileChannel destination = null;
|
|
|
|
boolean result = true;
|
|
|
|
long lastProgress = System.currentTimeMillis() - 500;
|
|
|
|
try {
|
|
|
|
source = new FileInputStream(sourceFile).getChannel();
|
|
|
|
destination = new FileOutputStream(destFile).getChannel();
|
|
|
|
long size = source.size();
|
|
|
|
for (long a = 0; a < size; a += 1024) {
|
|
|
|
destination.transferFrom(source, a, Math.min(1024, size - a));
|
|
|
|
if (finalProgress != null) {
|
|
|
|
if (lastProgress <= System.currentTimeMillis() - 500) {
|
|
|
|
lastProgress = System.currentTimeMillis();
|
|
|
|
final int progress = (int) ((float) a / (float) size * 100);
|
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
finalProgress.setProgress(progress);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
result = false;
|
|
|
|
} finally {
|
|
|
|
if(source != null) {
|
|
|
|
source.close();
|
|
|
|
}
|
|
|
|
if(destination != null) {
|
|
|
|
destination.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result && (type == 0 || type == 1)) {
|
|
|
|
Utilities.addMediaToGallery(Uri.fromFile(destFile));
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
if (finalProgress != null) {
|
|
|
|
Utilities.RunOnUIThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
finalProgress.dismiss();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|
|
|
|
}
|
2014-03-31 14:14:49 +00:00
|
|
|
|
|
|
|
public GifDrawable getGifDrawable(ChatMediaCell cell, boolean create) {
|
|
|
|
if (cell == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
MessageObject messageObject = cell.getMessageObject();
|
|
|
|
if (messageObject == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2014-04-03 21:18:54 +00:00
|
|
|
if (currentGifDrawable != null && currentGifMessageObject != null && messageObject.messageOwner.id == currentGifMessageObject.messageOwner.id) {
|
2014-03-31 14:14:49 +00:00
|
|
|
currentMediaCell = cell;
|
|
|
|
currentGifDrawable.parentView = new WeakReference<View>(cell);
|
|
|
|
return currentGifDrawable;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (create) {
|
|
|
|
if (currentMediaCell != null) {
|
|
|
|
if (currentGifDrawable != null) {
|
|
|
|
currentGifDrawable.stop();
|
|
|
|
currentGifDrawable.recycle();
|
|
|
|
}
|
|
|
|
currentMediaCell.clearGifImage();
|
|
|
|
}
|
|
|
|
currentGifMessageObject = cell.getMessageObject();
|
|
|
|
currentMediaCell = cell;
|
|
|
|
|
|
|
|
File cacheFile = null;
|
|
|
|
if (currentGifMessageObject.messageOwner.attachPath != null && currentGifMessageObject.messageOwner.attachPath.length() != 0) {
|
|
|
|
File f = new File(currentGifMessageObject.messageOwner.attachPath);
|
|
|
|
if (f.length() > 0) {
|
|
|
|
cacheFile = f;
|
|
|
|
}
|
2014-04-04 17:58:33 +00:00
|
|
|
}
|
|
|
|
if (cacheFile == null) {
|
2014-03-31 14:14:49 +00:00
|
|
|
cacheFile = new File(Utilities.getCacheDir(), messageObject.getFileName());
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
currentGifDrawable = new GifDrawable(cacheFile);
|
|
|
|
currentGifDrawable.parentView = new WeakReference<View>(cell);
|
|
|
|
return currentGifDrawable;
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void clearGifDrawable(ChatMediaCell cell) {
|
|
|
|
if (cell == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MessageObject messageObject = cell.getMessageObject();
|
|
|
|
if (messageObject == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentGifMessageObject != null && messageObject.messageOwner.id == currentGifMessageObject.messageOwner.id) {
|
|
|
|
if (currentGifDrawable != null) {
|
|
|
|
currentGifDrawable.stop();
|
|
|
|
currentGifDrawable.recycle();
|
|
|
|
currentGifDrawable = null;
|
|
|
|
}
|
|
|
|
currentMediaCell = null;
|
|
|
|
currentGifMessageObject = null;
|
|
|
|
}
|
|
|
|
}
|
2014-04-05 17:11:44 +00:00
|
|
|
|
|
|
|
public static boolean isGif(Uri uri) {
|
|
|
|
ParcelFileDescriptor parcelFD = null;
|
|
|
|
FileInputStream input = null;
|
|
|
|
try {
|
|
|
|
parcelFD = ApplicationLoader.applicationContext.getContentResolver().openFileDescriptor(uri, "r");
|
|
|
|
input = new FileInputStream(parcelFD.getFileDescriptor());
|
|
|
|
if (input.getChannel().size() > 3) {
|
|
|
|
byte[] header = new byte[3];
|
|
|
|
input.read(header, 0, 3);
|
|
|
|
String str = new String(header);
|
|
|
|
if (str != null && str.equalsIgnoreCase("gif")) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
} finally {
|
|
|
|
try {
|
|
|
|
if (parcelFD != null) {
|
|
|
|
parcelFD.close();
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (input != null) {
|
|
|
|
input.close();
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String copyDocumentToCache(Uri uri) {
|
|
|
|
ParcelFileDescriptor parcelFD = null;
|
|
|
|
FileInputStream input = null;
|
|
|
|
FileOutputStream output = null;
|
|
|
|
try {
|
|
|
|
int id = UserConfig.lastLocalId;
|
|
|
|
UserConfig.lastLocalId--;
|
|
|
|
parcelFD = ApplicationLoader.applicationContext.getContentResolver().openFileDescriptor(uri, "r");
|
|
|
|
input = new FileInputStream(parcelFD.getFileDescriptor());
|
|
|
|
File f = new File(Utilities.getCacheDir(), String.format(Locale.US, "%d.gif", id));
|
|
|
|
output = new FileOutputStream(f);
|
|
|
|
input.getChannel().transferTo(0, input.getChannel().size(), output.getChannel());
|
|
|
|
UserConfig.saveConfig(false);
|
|
|
|
return f.getAbsolutePath();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e("tmessages", e);
|
|
|
|
} finally {
|
|
|
|
try {
|
|
|
|
if (parcelFD != null) {
|
|
|
|
parcelFD.close();
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (input != null) {
|
|
|
|
input.close();
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (output != null) {
|
|
|
|
output.close();
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
|
|
|
FileLog.e("tmessages", e2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2014-02-28 22:28:25 +00:00
|
|
|
}
|