2014-02-28 23:28:25 +01: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).
|
|
|
|
*
|
2019-01-23 18:03:33 +01:00
|
|
|
* Copyright Nikolai Kudashov, 2013-2018.
|
2014-02-28 23:28:25 +01:00
|
|
|
*/
|
|
|
|
|
2015-09-24 22:52:02 +02:00
|
|
|
package org.telegram.messenger;
|
2014-02-28 23:28:25 +01:00
|
|
|
|
2015-10-29 18:10:07 +01:00
|
|
|
import android.Manifest;
|
2015-05-21 23:27:27 +02:00
|
|
|
import android.annotation.SuppressLint;
|
2014-08-22 16:24:33 +02:00
|
|
|
import android.app.Activity;
|
2016-04-22 15:49:00 +02:00
|
|
|
import android.app.DownloadManager;
|
2018-07-30 04:07:02 +02:00
|
|
|
import android.content.ContentResolver;
|
2014-02-28 23:28:25 +01:00
|
|
|
import android.content.Context;
|
2014-08-22 16:24:33 +02:00
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.SharedPreferences;
|
2015-10-29 18:10:07 +01:00
|
|
|
import android.content.pm.PackageManager;
|
2014-04-04 19:58:33 +02:00
|
|
|
import android.database.ContentObserver;
|
|
|
|
import android.database.Cursor;
|
2014-10-20 20:11:47 +02:00
|
|
|
import android.graphics.BitmapFactory;
|
2020-07-26 10:03:38 +02:00
|
|
|
import android.graphics.Matrix;
|
2014-10-20 20:11:47 +02:00
|
|
|
import android.graphics.Point;
|
2017-07-08 18:32:04 +02:00
|
|
|
import android.graphics.SurfaceTexture;
|
2015-01-02 23:15:07 +01:00
|
|
|
import android.hardware.Sensor;
|
|
|
|
import android.hardware.SensorEvent;
|
|
|
|
import android.hardware.SensorEventListener;
|
|
|
|
import android.hardware.SensorManager;
|
2014-03-22 23:31:55 +01:00
|
|
|
import android.media.AudioFormat;
|
2014-02-28 23:28:25 +01:00
|
|
|
import android.media.AudioManager;
|
2014-03-22 23:31:55 +01:00
|
|
|
import android.media.AudioRecord;
|
2014-09-28 15:37:26 +02:00
|
|
|
import android.media.MediaCodecInfo;
|
|
|
|
import android.media.MediaCodecList;
|
|
|
|
import android.media.MediaExtractor;
|
|
|
|
import android.media.MediaFormat;
|
2019-12-31 14:08:08 +01:00
|
|
|
import android.media.MediaMetadataRetriever;
|
2014-02-28 23:28:25 +01:00
|
|
|
import android.media.MediaRecorder;
|
2014-03-22 23:31:55 +01:00
|
|
|
import android.net.Uri;
|
2014-09-28 15:37:26 +02:00
|
|
|
import android.os.Build;
|
2014-03-22 23:31:55 +01:00
|
|
|
import android.os.Environment;
|
2015-06-29 19:12:11 +02:00
|
|
|
import android.os.PowerManager;
|
2019-12-31 14:08:08 +01:00
|
|
|
import android.os.SystemClock;
|
2014-04-04 19:58:33 +02:00
|
|
|
import android.provider.MediaStore;
|
2016-03-16 13:26:32 +01:00
|
|
|
import android.provider.OpenableColumns;
|
2016-03-06 02:49:31 +01:00
|
|
|
import android.telephony.PhoneStateListener;
|
|
|
|
import android.telephony.TelephonyManager;
|
2017-12-08 18:35:59 +01:00
|
|
|
import android.text.TextUtils;
|
2018-07-30 04:07:02 +02:00
|
|
|
import android.util.SparseArray;
|
|
|
|
import android.view.HapticFeedbackConstants;
|
2017-07-08 18:32:04 +02:00
|
|
|
import android.view.TextureView;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.WindowManager;
|
|
|
|
import android.widget.FrameLayout;
|
2014-02-28 23:28:25 +01:00
|
|
|
|
2018-08-27 10:33:11 +02:00
|
|
|
import com.google.android.exoplayer2.C;
|
|
|
|
import com.google.android.exoplayer2.ExoPlayer;
|
|
|
|
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
|
|
|
|
2015-09-24 22:52:02 +02:00
|
|
|
import org.telegram.messenger.audioinfo.AudioInfo;
|
2019-12-31 14:08:08 +01:00
|
|
|
import org.telegram.messenger.video.MediaCodecVideoConvertor;
|
2017-03-31 01:58:05 +02:00
|
|
|
import org.telegram.messenger.voip.VoIPService;
|
2015-09-24 22:52:02 +02:00
|
|
|
import org.telegram.tgnet.ConnectionsManager;
|
2020-09-30 15:48:47 +02:00
|
|
|
import org.telegram.tgnet.TLObject;
|
2015-09-24 22:52:02 +02:00
|
|
|
import org.telegram.tgnet.TLRPC;
|
2017-03-31 01:58:05 +02:00
|
|
|
import org.telegram.ui.ActionBar.AlertDialog;
|
2018-07-30 04:07:02 +02:00
|
|
|
import org.telegram.ui.ActionBar.BaseFragment;
|
2020-06-04 18:47:15 +02:00
|
|
|
import org.telegram.ui.ActionBar.Theme;
|
2020-09-30 15:48:47 +02:00
|
|
|
import org.telegram.ui.Adapters.FiltersView;
|
2016-03-06 02:49:31 +01:00
|
|
|
import org.telegram.ui.ChatActivity;
|
2017-03-31 01:58:05 +02:00
|
|
|
import org.telegram.ui.Components.EmbedBottomSheet;
|
2017-12-08 18:35:59 +01:00
|
|
|
import org.telegram.ui.Components.PhotoFilterView;
|
2017-07-08 18:32:04 +02:00
|
|
|
import org.telegram.ui.Components.PipRoundVideoView;
|
|
|
|
import org.telegram.ui.Components.VideoPlayer;
|
2016-03-06 02:49:31 +01:00
|
|
|
import org.telegram.ui.PhotoViewer;
|
2014-02-28 23:28:25 +01:00
|
|
|
|
|
|
|
import java.io.File;
|
2020-09-30 15:48:47 +02:00
|
|
|
import java.io.FileDescriptor;
|
2014-03-22 23:31:55 +01:00
|
|
|
import java.io.FileInputStream;
|
|
|
|
import java.io.FileOutputStream;
|
2016-03-16 13:26:32 +01:00
|
|
|
import java.io.InputStream;
|
2020-09-30 15:48:47 +02:00
|
|
|
import java.lang.reflect.Method;
|
2018-07-30 04:07:02 +02:00
|
|
|
import java.net.URLEncoder;
|
2014-03-22 23:31:55 +01:00
|
|
|
import java.nio.ByteBuffer;
|
2015-10-29 18:10:07 +01:00
|
|
|
import java.nio.ByteOrder;
|
2014-03-22 23:31:55 +01:00
|
|
|
import java.nio.channels.FileChannel;
|
2014-02-28 23:28:25 +01:00
|
|
|
import java.util.ArrayList;
|
2017-07-08 18:32:04 +02:00
|
|
|
import java.util.Collections;
|
2014-02-28 23:28:25 +01:00
|
|
|
import java.util.HashMap;
|
2014-04-05 19:11:44 +02:00
|
|
|
import java.util.Locale;
|
2014-02-28 23:28:25 +01:00
|
|
|
import java.util.Timer;
|
|
|
|
import java.util.TimerTask;
|
2020-10-30 11:26:29 +01:00
|
|
|
import java.util.concurrent.CountDownLatch;
|
2014-02-28 23:28:25 +01:00
|
|
|
|
2016-03-06 02:49:31 +01:00
|
|
|
public class MediaController implements AudioManager.OnAudioFocusChangeListener, NotificationCenter.NotificationCenterDelegate, SensorEventListener {
|
2014-02-28 23:28:25 +01:00
|
|
|
|
2020-03-30 14:00:09 +02:00
|
|
|
private native int startRecord(String path, int sampleRate);
|
2014-03-22 23:31:55 +01:00
|
|
|
private native int writeFrame(ByteBuffer frame, int len);
|
|
|
|
private native void stopRecord();
|
2018-07-30 04:07:02 +02:00
|
|
|
public static native int isOpusFile(String path);
|
2016-03-06 02:49:31 +01:00
|
|
|
public native byte[] getWaveform(String path);
|
|
|
|
public native byte[] getWaveform2(short[] array, int length);
|
2014-03-22 23:31:55 +01:00
|
|
|
|
2020-06-04 18:47:15 +02:00
|
|
|
private static class AudioBuffer {
|
2014-03-22 23:31:55 +01:00
|
|
|
public AudioBuffer(int capacity) {
|
|
|
|
buffer = ByteBuffer.allocateDirect(capacity);
|
|
|
|
bufferBytes = new byte[capacity];
|
|
|
|
}
|
|
|
|
|
|
|
|
ByteBuffer buffer;
|
|
|
|
byte[] bufferBytes;
|
|
|
|
int size;
|
|
|
|
int finished;
|
|
|
|
long pcmOffset;
|
|
|
|
}
|
|
|
|
|
2014-06-12 03:13:15 +02:00
|
|
|
private static final String[] projectionPhotos = {
|
|
|
|
MediaStore.Images.Media._ID,
|
|
|
|
MediaStore.Images.Media.BUCKET_ID,
|
|
|
|
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
|
|
|
|
MediaStore.Images.Media.DATA,
|
2019-09-10 12:56:11 +02:00
|
|
|
Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_MODIFIED : MediaStore.Images.Media.DATE_TAKEN,
|
2019-12-31 14:08:08 +01:00
|
|
|
MediaStore.Images.Media.ORIENTATION,
|
|
|
|
MediaStore.Images.Media.WIDTH,
|
|
|
|
MediaStore.Images.Media.HEIGHT,
|
|
|
|
MediaStore.Images.Media.SIZE
|
2014-06-12 03:13:15 +02:00
|
|
|
};
|
|
|
|
|
2015-05-03 13:48:36 +02:00
|
|
|
private static final String[] projectionVideo = {
|
|
|
|
MediaStore.Video.Media._ID,
|
|
|
|
MediaStore.Video.Media.BUCKET_ID,
|
|
|
|
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
|
|
|
|
MediaStore.Video.Media.DATA,
|
2019-09-10 12:56:11 +02:00
|
|
|
Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_MODIFIED : MediaStore.Video.Media.DATE_TAKEN,
|
2019-12-31 14:08:08 +01:00
|
|
|
MediaStore.Video.Media.DURATION,
|
|
|
|
MediaStore.Video.Media.WIDTH,
|
|
|
|
MediaStore.Video.Media.HEIGHT,
|
|
|
|
MediaStore.Video.Media.SIZE
|
2015-05-03 13:48:36 +02:00
|
|
|
};
|
|
|
|
|
2015-07-22 20:56:37 +02:00
|
|
|
public static class AudioEntry {
|
|
|
|
public long id;
|
|
|
|
public String author;
|
|
|
|
public String title;
|
|
|
|
public String genre;
|
|
|
|
public int duration;
|
|
|
|
public String path;
|
|
|
|
public MessageObject messageObject;
|
|
|
|
}
|
|
|
|
|
2014-06-12 03:13:15 +02:00
|
|
|
public static class AlbumEntry {
|
|
|
|
public int bucketId;
|
2019-08-22 01:53:26 +02:00
|
|
|
public boolean videoOnly;
|
2014-06-12 03:13:15 +02:00
|
|
|
public String bucketName;
|
|
|
|
public PhotoEntry coverPhoto;
|
2015-01-02 23:15:07 +01:00
|
|
|
public ArrayList<PhotoEntry> photos = new ArrayList<>();
|
2018-07-30 04:07:02 +02:00
|
|
|
public SparseArray<PhotoEntry> photosByIds = new SparseArray<>();
|
2014-06-12 03:13:15 +02:00
|
|
|
|
2017-07-08 18:32:04 +02:00
|
|
|
public AlbumEntry(int bucketId, String bucketName, PhotoEntry coverPhoto) {
|
2014-06-12 03:13:15 +02:00
|
|
|
this.bucketId = bucketId;
|
|
|
|
this.bucketName = bucketName;
|
|
|
|
this.coverPhoto = coverPhoto;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addPhoto(PhotoEntry photoEntry) {
|
|
|
|
photos.add(photoEntry);
|
2015-02-01 19:51:02 +01:00
|
|
|
photosByIds.put(photoEntry.imageId, photoEntry);
|
2014-06-12 03:13:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-08 18:35:59 +01:00
|
|
|
public static class SavedFilterState {
|
|
|
|
public float enhanceValue;
|
2020-07-26 10:03:38 +02:00
|
|
|
public float softenSkinValue;
|
2017-12-08 18:35:59 +01:00
|
|
|
public float exposureValue;
|
|
|
|
public float contrastValue;
|
|
|
|
public float warmthValue;
|
|
|
|
public float saturationValue;
|
|
|
|
public float fadeValue;
|
|
|
|
public int tintShadowsColor;
|
|
|
|
public int tintHighlightsColor;
|
|
|
|
public float highlightsValue;
|
|
|
|
public float shadowsValue;
|
|
|
|
public float vignetteValue;
|
|
|
|
public float grainValue;
|
|
|
|
public int blurType;
|
|
|
|
public float sharpenValue;
|
|
|
|
public PhotoFilterView.CurvesToolValue curvesToolValue = new PhotoFilterView.CurvesToolValue();
|
|
|
|
public float blurExcludeSize;
|
|
|
|
public org.telegram.ui.Components.Point blurExcludePoint;
|
|
|
|
public float blurExcludeBlurSize;
|
|
|
|
public float blurAngle;
|
|
|
|
}
|
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
public static class CropState {
|
|
|
|
public float cropPx;
|
|
|
|
public float cropPy;
|
|
|
|
public float cropScale = 1;
|
|
|
|
public float cropRotate;
|
|
|
|
public float cropPw = 1;
|
|
|
|
public float cropPh = 1;
|
|
|
|
public int transformWidth;
|
|
|
|
public int transformHeight;
|
|
|
|
public int transformRotation;
|
|
|
|
public boolean mirrored;
|
|
|
|
|
|
|
|
public float stateScale;
|
|
|
|
public float scale;
|
|
|
|
public Matrix matrix;
|
|
|
|
public int width;
|
|
|
|
public int height;
|
|
|
|
public boolean freeform;
|
|
|
|
public float lockedAspectRatio;
|
|
|
|
|
|
|
|
public boolean initied;
|
|
|
|
}
|
|
|
|
|
2020-06-04 18:47:15 +02:00
|
|
|
public static class MediaEditState {
|
|
|
|
|
|
|
|
public CharSequence caption;
|
|
|
|
|
|
|
|
public String thumbPath;
|
|
|
|
public String imagePath;
|
|
|
|
public String filterPath;
|
|
|
|
public String paintPath;
|
2020-07-26 10:03:38 +02:00
|
|
|
public String croppedPaintPath;
|
2020-06-04 18:47:15 +02:00
|
|
|
public String fullPaintPath;
|
|
|
|
|
|
|
|
public ArrayList<TLRPC.MessageEntity> entities;
|
|
|
|
public SavedFilterState savedFilterState;
|
|
|
|
public ArrayList<VideoEditedInfo.MediaEntity> mediaEntities;
|
2020-07-26 10:03:38 +02:00
|
|
|
public ArrayList<VideoEditedInfo.MediaEntity> croppedMediaEntities;
|
2020-06-04 18:47:15 +02:00
|
|
|
public ArrayList<TLRPC.InputDocument> stickers;
|
|
|
|
public VideoEditedInfo editedInfo;
|
|
|
|
public long averageDuration;
|
|
|
|
public boolean isFiltered;
|
|
|
|
public boolean isPainted;
|
|
|
|
public boolean isCropped;
|
|
|
|
public int ttl;
|
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
public CropState cropState;
|
|
|
|
|
2020-06-04 18:47:15 +02:00
|
|
|
public String getPath() {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void reset() {
|
|
|
|
caption = null;
|
|
|
|
thumbPath = null;
|
|
|
|
filterPath = null;
|
|
|
|
imagePath = null;
|
|
|
|
paintPath = null;
|
2020-07-26 10:03:38 +02:00
|
|
|
croppedPaintPath = null;
|
2020-06-04 18:47:15 +02:00
|
|
|
isFiltered = false;
|
|
|
|
isPainted = false;
|
|
|
|
isCropped = false;
|
|
|
|
ttl = 0;
|
|
|
|
mediaEntities = null;
|
|
|
|
editedInfo = null;
|
|
|
|
entities = null;
|
|
|
|
savedFilterState = null;
|
|
|
|
stickers = null;
|
2020-07-26 10:03:38 +02:00
|
|
|
cropState = null;
|
2020-06-04 18:47:15 +02:00
|
|
|
}
|
2020-10-05 00:13:31 +02:00
|
|
|
|
|
|
|
public void copyFrom(MediaEditState state) {
|
|
|
|
caption = state.caption;
|
|
|
|
|
|
|
|
thumbPath = state.thumbPath;
|
|
|
|
imagePath = state.imagePath;
|
|
|
|
filterPath = state.filterPath;
|
|
|
|
paintPath = state.paintPath;
|
|
|
|
croppedPaintPath = state.croppedPaintPath;
|
|
|
|
fullPaintPath = state.fullPaintPath;
|
|
|
|
|
|
|
|
entities = state.entities;
|
|
|
|
savedFilterState = state.savedFilterState;
|
|
|
|
mediaEntities = state.mediaEntities;
|
|
|
|
croppedMediaEntities = state.croppedMediaEntities;
|
|
|
|
stickers = state.stickers;
|
|
|
|
editedInfo = state.editedInfo;
|
|
|
|
averageDuration = state.averageDuration;
|
|
|
|
isFiltered = state.isFiltered;
|
|
|
|
isPainted = state.isPainted;
|
|
|
|
isCropped = state.isCropped;
|
|
|
|
ttl = state.ttl;
|
|
|
|
|
|
|
|
cropState = state.cropState;
|
|
|
|
}
|
2020-06-04 18:47:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public static class PhotoEntry extends MediaEditState {
|
2014-06-12 03:13:15 +02:00
|
|
|
public int bucketId;
|
|
|
|
public int imageId;
|
|
|
|
public long dateTaken;
|
2017-07-08 18:32:04 +02:00
|
|
|
public int duration;
|
2019-12-31 14:08:08 +01:00
|
|
|
public int width;
|
|
|
|
public int height;
|
|
|
|
public long size;
|
2014-06-12 03:13:15 +02:00
|
|
|
public String path;
|
|
|
|
public int orientation;
|
2015-05-03 13:48:36 +02:00
|
|
|
public boolean isVideo;
|
2017-12-08 18:35:59 +01:00
|
|
|
public boolean isMuted;
|
2019-01-23 18:03:33 +01:00
|
|
|
public boolean canDeleteAfter;
|
2014-06-12 03:13:15 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
public PhotoEntry(int bucketId, int imageId, long dateTaken, String path, int orientation, boolean isVideo, int width, int height, long size) {
|
2014-06-12 03:13:15 +02:00
|
|
|
this.bucketId = bucketId;
|
|
|
|
this.imageId = imageId;
|
|
|
|
this.dateTaken = dateTaken;
|
|
|
|
this.path = path;
|
2019-12-31 14:08:08 +01:00
|
|
|
this.width = width;
|
|
|
|
this.height = height;
|
|
|
|
this.size = size;
|
2017-07-08 18:32:04 +02:00
|
|
|
if (isVideo) {
|
|
|
|
this.duration = orientation;
|
|
|
|
} else {
|
|
|
|
this.orientation = orientation;
|
|
|
|
}
|
2015-05-03 13:48:36 +02:00
|
|
|
this.isVideo = isVideo;
|
2014-06-12 03:13:15 +02:00
|
|
|
}
|
2017-07-23 14:56:38 +02:00
|
|
|
|
2020-06-04 18:47:15 +02:00
|
|
|
@Override
|
|
|
|
public String getPath() {
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-07-23 14:56:38 +02:00
|
|
|
public void reset() {
|
2020-06-04 18:47:15 +02:00
|
|
|
if (isVideo) {
|
|
|
|
if (filterPath != null) {
|
|
|
|
new File(filterPath).delete();
|
|
|
|
filterPath = null;
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
2020-06-04 18:47:15 +02:00
|
|
|
super.reset();
|
2017-07-23 14:56:38 +02:00
|
|
|
}
|
2014-06-12 03:13:15 +02:00
|
|
|
}
|
|
|
|
|
2020-06-04 18:47:15 +02:00
|
|
|
public static class SearchImage extends MediaEditState {
|
2015-01-02 23:15:07 +01:00
|
|
|
public String id;
|
|
|
|
public String imageUrl;
|
|
|
|
public String thumbUrl;
|
|
|
|
public int width;
|
|
|
|
public int height;
|
|
|
|
public int size;
|
|
|
|
public int type;
|
|
|
|
public int date;
|
2015-05-03 13:48:36 +02:00
|
|
|
public CharSequence caption;
|
2016-01-11 18:19:48 +01:00
|
|
|
public TLRPC.Document document;
|
2018-07-30 04:07:02 +02:00
|
|
|
public TLRPC.Photo photo;
|
|
|
|
public TLRPC.PhotoSize photoSize;
|
|
|
|
public TLRPC.PhotoSize thumbPhotoSize;
|
2019-09-10 12:56:11 +02:00
|
|
|
public TLRPC.BotInlineResult inlineResult;
|
|
|
|
public HashMap<String, String> params;
|
2017-12-08 18:35:59 +01:00
|
|
|
|
2020-06-04 18:47:15 +02:00
|
|
|
@Override
|
|
|
|
public String getPath() {
|
|
|
|
if (photoSize != null) {
|
|
|
|
return FileLoader.getPathToAttach(photoSize, true).getAbsolutePath();
|
|
|
|
} else if (document != null) {
|
|
|
|
return FileLoader.getPathToAttach(document, true).getAbsolutePath();
|
|
|
|
} else {
|
|
|
|
return ImageLoader.getHttpFilePath(imageUrl, "jpg").getAbsolutePath();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-12-08 18:35:59 +01:00
|
|
|
public void reset() {
|
2020-06-04 18:47:15 +02:00
|
|
|
super.reset();
|
2017-12-08 18:35:59 +01:00
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
|
|
|
|
public String getAttachName() {
|
|
|
|
if (photoSize != null) {
|
|
|
|
return FileLoader.getAttachFileName(photoSize);
|
|
|
|
} else if (document != null) {
|
|
|
|
return FileLoader.getAttachFileName(document);
|
|
|
|
}
|
|
|
|
return Utilities.MD5(imageUrl) + "." + ImageLoader.getHttpUrlExtension(imageUrl, "jpg");
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getPathToAttach() {
|
|
|
|
if (photoSize != null) {
|
|
|
|
return FileLoader.getPathToAttach(photoSize, true).getAbsolutePath();
|
|
|
|
} else if (document != null) {
|
|
|
|
return FileLoader.getPathToAttach(document, true).getAbsolutePath();
|
|
|
|
} else {
|
|
|
|
return imageUrl;
|
|
|
|
}
|
|
|
|
}
|
2015-01-02 23:15:07 +01:00
|
|
|
}
|
|
|
|
|
2020-01-01 19:32:12 +01:00
|
|
|
AudioManager.OnAudioFocusChangeListener audioRecordFocusChangedListener = focusChange -> {
|
|
|
|
if (focusChange != AudioManager.AUDIOFOCUS_GAIN) {
|
|
|
|
hasRecordAudioFocus = false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
public final static int VIDEO_BITRATE_1080 = 6800_000;
|
|
|
|
public final static int VIDEO_BITRATE_720 = 2621_440;
|
|
|
|
public final static int VIDEO_BITRATE_480 = 1000_000;
|
|
|
|
public final static int VIDEO_BITRATE_360 = 750_000;
|
|
|
|
|
|
|
|
public final static String VIDEO_MIME_TYPE = "video/avc";
|
|
|
|
public final static String AUIDO_MIME_TYPE = "audio/mp4a-latm";
|
|
|
|
|
2014-09-28 15:37:26 +02:00
|
|
|
private final Object videoConvertSync = new Object();
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
private SensorManager sensorManager;
|
|
|
|
private boolean ignoreProximity;
|
2015-06-29 19:12:11 +02:00
|
|
|
private PowerManager.WakeLock proximityWakeLock;
|
2016-03-06 02:49:31 +01:00
|
|
|
private Sensor proximitySensor;
|
|
|
|
private Sensor accelerometerSensor;
|
|
|
|
private Sensor linearSensor;
|
|
|
|
private Sensor gravitySensor;
|
|
|
|
private boolean raiseToEarRecord;
|
|
|
|
private ChatActivity raiseChat;
|
|
|
|
private boolean accelerometerVertical;
|
|
|
|
private int raisedToTop;
|
2018-07-30 04:07:02 +02:00
|
|
|
private int raisedToTopSign;
|
2016-03-06 02:49:31 +01:00
|
|
|
private int raisedToBack;
|
|
|
|
private int countLess;
|
|
|
|
private long timeSinceRaise;
|
|
|
|
private long lastTimestamp = 0;
|
|
|
|
private boolean proximityTouched;
|
|
|
|
private boolean proximityHasDifferentValues;
|
|
|
|
private float lastProximityValue = -100;
|
|
|
|
private boolean useFrontSpeaker;
|
|
|
|
private boolean inputFieldHasText;
|
|
|
|
private boolean allowStartRecord;
|
|
|
|
private boolean ignoreOnPause;
|
|
|
|
private boolean sensorsStarted;
|
|
|
|
private float previousAccValue;
|
|
|
|
private float[] gravity = new float[3];
|
|
|
|
private float[] gravityFast = new float[3];
|
|
|
|
private float[] linearAcceleration = new float[3];
|
|
|
|
|
2016-04-22 15:49:00 +02:00
|
|
|
private int hasAudioFocus;
|
2020-01-01 19:32:12 +01:00
|
|
|
private boolean hasRecordAudioFocus;
|
2016-03-06 02:49:31 +01:00
|
|
|
private boolean callInProgress;
|
2016-05-25 23:49:47 +02:00
|
|
|
private int audioFocus = AUDIO_NO_FOCUS_NO_DUCK;
|
|
|
|
private boolean resumeAudioOnFocusGain;
|
|
|
|
|
|
|
|
private static final float VOLUME_DUCK = 0.2f;
|
|
|
|
private static final float VOLUME_NORMAL = 1.0f;
|
|
|
|
private static final int AUDIO_NO_FOCUS_NO_DUCK = 0;
|
|
|
|
private static final int AUDIO_NO_FOCUS_CAN_DUCK = 1;
|
|
|
|
private static final int AUDIO_FOCUSED = 2;
|
2015-01-02 23:15:07 +01:00
|
|
|
|
2020-04-24 11:21:58 +02:00
|
|
|
private static class VideoConvertMessage {
|
2020-01-01 19:32:12 +01:00
|
|
|
public MessageObject messageObject;
|
|
|
|
public VideoEditedInfo videoEditedInfo;
|
|
|
|
public int currentAccount;
|
|
|
|
|
|
|
|
public VideoConvertMessage(MessageObject object, VideoEditedInfo info) {
|
|
|
|
messageObject = object;
|
|
|
|
currentAccount = messageObject.currentAccount;
|
|
|
|
videoEditedInfo = info;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private ArrayList<VideoConvertMessage> videoConvertQueue = new ArrayList<>();
|
2014-09-28 15:37:26 +02:00
|
|
|
private final Object videoQueueSync = new Object();
|
2016-03-06 02:49:31 +01:00
|
|
|
private HashMap<String, MessageObject> generatingWaveform = new HashMap<>();
|
|
|
|
|
|
|
|
private boolean voiceMessagesPlaylistUnread;
|
|
|
|
private ArrayList<MessageObject> voiceMessagesPlaylist;
|
2018-07-30 04:07:02 +02:00
|
|
|
private SparseArray<MessageObject> voiceMessagesPlaylistMap;
|
2014-10-01 00:36:18 +02:00
|
|
|
|
2017-12-08 18:35:59 +01:00
|
|
|
private static Runnable refreshGalleryRunnable;
|
2017-07-08 18:32:04 +02:00
|
|
|
public static AlbumEntry allMediaAlbumEntry;
|
2015-06-29 19:12:11 +02:00
|
|
|
public static AlbumEntry allPhotosAlbumEntry;
|
2019-02-08 03:30:32 +01:00
|
|
|
public static AlbumEntry allVideosAlbumEntry;
|
2019-08-22 01:53:26 +02:00
|
|
|
public static ArrayList<AlbumEntry> allMediaAlbums = new ArrayList<>();
|
|
|
|
public static ArrayList<AlbumEntry> allPhotoAlbums = new ArrayList<>();
|
2016-10-11 13:57:01 +02:00
|
|
|
private static Runnable broadcastPhotosRunnable;
|
2015-06-29 19:12:11 +02:00
|
|
|
|
2014-02-28 23:28:25 +01:00
|
|
|
private boolean isPaused = false;
|
2018-07-30 04:07:02 +02:00
|
|
|
private VideoPlayer audioPlayer = null;
|
2020-10-30 11:26:29 +01:00
|
|
|
private VideoPlayer emojiSoundPlayer = null;
|
|
|
|
private int emojiSoundPlayerNum = 0;
|
2020-07-26 10:03:38 +02:00
|
|
|
private boolean isStreamingCurrentAudio;
|
2019-12-31 14:08:08 +01:00
|
|
|
private int playerNum;
|
|
|
|
private String shouldSavePositionForCurrentAudio;
|
|
|
|
private long lastSaveTime;
|
2018-07-30 04:07:02 +02:00
|
|
|
private float currentPlaybackSpeed = 1.0f;
|
2019-12-31 14:08:08 +01:00
|
|
|
private float currentMusicPlaybackSpeed = 1.0f;
|
2018-07-30 04:07:02 +02:00
|
|
|
private float seekToProgressPending;
|
2017-07-08 18:32:04 +02:00
|
|
|
private long lastProgress = 0;
|
2014-02-28 23:28:25 +01:00
|
|
|
private MessageObject playingMessageObject;
|
2019-03-03 21:40:48 +01:00
|
|
|
private MessageObject goingToShowMessageObject;
|
2014-05-17 01:05:49 +02:00
|
|
|
private Timer progressTimer = null;
|
2014-10-05 23:23:57 +02:00
|
|
|
private final Object progressTimerSync = new Object();
|
2015-07-22 20:56:37 +02:00
|
|
|
private boolean downloadingCurrentMessage;
|
2015-10-29 18:10:07 +01:00
|
|
|
private boolean playMusicAgain;
|
2020-09-30 15:48:47 +02:00
|
|
|
private PlaylistGlobalSearchParams playlistGlobalSearchParams;
|
2015-07-22 20:56:37 +02:00
|
|
|
private AudioInfo audioInfo;
|
2017-07-08 18:32:04 +02:00
|
|
|
private VideoPlayer videoPlayer;
|
2019-03-03 21:40:48 +01:00
|
|
|
private boolean playerWasReady;
|
2017-07-08 18:32:04 +02:00
|
|
|
private TextureView currentTextureView;
|
|
|
|
private PipRoundVideoView pipRoundVideoView;
|
|
|
|
private int pipSwitchingState;
|
|
|
|
private Activity baseActivity;
|
2018-07-30 04:07:02 +02:00
|
|
|
private BaseFragment flagSecureFragment;
|
|
|
|
private View feedbackView;
|
2017-07-08 18:32:04 +02:00
|
|
|
private AspectRatioFrameLayout currentAspectRatioFrameLayout;
|
|
|
|
private boolean isDrawingWasReady;
|
|
|
|
private FrameLayout currentTextureViewContainer;
|
|
|
|
private int currentAspectRatioFrameLayoutRotation;
|
|
|
|
private float currentAspectRatioFrameLayoutRatio;
|
|
|
|
private boolean currentAspectRatioFrameLayoutReady;
|
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
private ArrayList<MessageObject> playlist = new ArrayList<>();
|
|
|
|
private HashMap<Integer, MessageObject> playlistMap = new HashMap<>();
|
|
|
|
private ArrayList<MessageObject> shuffledPlaylist = new ArrayList<>();
|
|
|
|
private int currentPlaylistNum;
|
|
|
|
private boolean forceLoopCurrentPlaylist;
|
|
|
|
private boolean[] playlistEndReached = new boolean[]{false, false};
|
|
|
|
private boolean loadingPlaylist;
|
|
|
|
private long playlistMergeDialogId;
|
|
|
|
private int playlistClassGuid;
|
|
|
|
private int[] playlistMaxId = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE};
|
|
|
|
|
2019-03-03 21:40:48 +01:00
|
|
|
private Runnable setLoadingRunnable = new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (playingMessageObject == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
FileLoader.getInstance(playingMessageObject.currentAccount).setLoadingVideo(playingMessageObject.getDocument(), true, false);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-07-08 18:32:04 +02:00
|
|
|
private AudioRecord audioRecorder;
|
|
|
|
private TLRPC.TL_document recordingAudio;
|
2019-09-10 12:56:11 +02:00
|
|
|
private int recordingGuid = -1;
|
2018-07-30 04:07:02 +02:00
|
|
|
private int recordingCurrentAccount;
|
2017-07-08 18:32:04 +02:00
|
|
|
private File recordingAudioFile;
|
2014-02-28 23:28:25 +01:00
|
|
|
private long recordStartTime;
|
2014-03-22 23:31:55 +01:00
|
|
|
private long recordTimeCount;
|
2014-02-28 23:28:25 +01:00
|
|
|
private long recordDialogId;
|
2020-09-30 15:48:47 +02:00
|
|
|
private MessageObject recordReplyingMsg;
|
|
|
|
private MessageObject recordReplyingTopMsg;
|
2016-03-06 02:49:31 +01:00
|
|
|
private short[] recordSamples = new short[1024];
|
|
|
|
private long samplesCount;
|
2014-02-28 23:28:25 +01:00
|
|
|
|
2014-10-05 23:23:57 +02:00
|
|
|
private final Object sync = new Object();
|
2014-02-28 23:28:25 +01:00
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
private ArrayList<ByteBuffer> recordBuffers = new ArrayList<>();
|
2014-03-22 23:31:55 +01:00
|
|
|
private ByteBuffer fileBuffer;
|
2020-03-30 14:00:09 +02:00
|
|
|
public int recordBufferSize = 1280;
|
|
|
|
public int sampleRate = 16000;
|
2016-03-06 02:49:31 +01:00
|
|
|
private int sendAfterDone;
|
2019-09-10 12:56:11 +02:00
|
|
|
private boolean sendAfterDoneNotify;
|
|
|
|
private int sendAfterDoneScheduleDate;
|
2014-02-28 23:28:25 +01:00
|
|
|
|
2015-07-22 20:56:37 +02:00
|
|
|
private Runnable recordStartRunnable;
|
2014-03-22 23:31:55 +01:00
|
|
|
private DispatchQueue recordQueue;
|
|
|
|
private DispatchQueue fileEncodingQueue;
|
|
|
|
private Runnable recordRunnable = new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
if (audioRecorder != null) {
|
2015-05-21 23:27:27 +02:00
|
|
|
ByteBuffer buffer;
|
2014-03-22 23:31:55 +01:00
|
|
|
if (!recordBuffers.isEmpty()) {
|
|
|
|
buffer = recordBuffers.get(0);
|
|
|
|
recordBuffers.remove(0);
|
|
|
|
} else {
|
|
|
|
buffer = ByteBuffer.allocateDirect(recordBufferSize);
|
2015-10-29 18:10:07 +01:00
|
|
|
buffer.order(ByteOrder.nativeOrder());
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
buffer.rewind();
|
|
|
|
int len = audioRecorder.read(buffer, buffer.capacity());
|
|
|
|
if (len > 0) {
|
2016-03-06 02:49:31 +01:00
|
|
|
buffer.limit(len);
|
2015-10-29 18:10:07 +01:00
|
|
|
double sum = 0;
|
|
|
|
try {
|
2016-03-06 02:49:31 +01:00
|
|
|
long newSamplesCount = samplesCount + len / 2;
|
|
|
|
int currentPart = (int) (((double) samplesCount / (double) newSamplesCount) * recordSamples.length);
|
|
|
|
int newPart = recordSamples.length - currentPart;
|
|
|
|
float sampleStep;
|
|
|
|
if (currentPart != 0) {
|
|
|
|
sampleStep = (float) recordSamples.length / (float) currentPart;
|
|
|
|
float currentNum = 0;
|
|
|
|
for (int a = 0; a < currentPart; a++) {
|
|
|
|
recordSamples[a] = recordSamples[(int) currentNum];
|
|
|
|
currentNum += sampleStep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int currentNum = currentPart;
|
|
|
|
float nextNum = 0;
|
|
|
|
sampleStep = (float) len / 2 / (float) newPart;
|
2015-10-29 18:10:07 +01:00
|
|
|
for (int i = 0; i < len / 2; i++) {
|
|
|
|
short peak = buffer.getShort();
|
2020-03-30 14:00:09 +02:00
|
|
|
if (Build.VERSION.SDK_INT < 21) {
|
|
|
|
if (peak > 2500) {
|
|
|
|
sum += peak * peak;
|
|
|
|
}
|
|
|
|
} else {
|
2016-05-25 23:49:47 +02:00
|
|
|
sum += peak * peak;
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
if (i == (int) nextNum && currentNum < recordSamples.length) {
|
|
|
|
recordSamples[currentNum] = peak;
|
|
|
|
nextNum += sampleStep;
|
|
|
|
currentNum++;
|
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
samplesCount = newSamplesCount;
|
2015-10-29 18:10:07 +01:00
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2015-10-29 18:10:07 +01:00
|
|
|
}
|
|
|
|
buffer.position(0);
|
|
|
|
final double amplitude = Math.sqrt(sum / len / 2);
|
2014-03-22 23:31:55 +01:00
|
|
|
final ByteBuffer finalBuffer = buffer;
|
|
|
|
final boolean flush = len != buffer.capacity();
|
|
|
|
if (len != 0) {
|
2019-01-23 18:03:33 +01:00
|
|
|
fileEncodingQueue.postRunnable(() -> {
|
|
|
|
while (finalBuffer.hasRemaining()) {
|
|
|
|
int oldLimit = -1;
|
|
|
|
if (finalBuffer.remaining() > fileBuffer.remaining()) {
|
|
|
|
oldLimit = finalBuffer.limit();
|
|
|
|
finalBuffer.limit(fileBuffer.remaining() + finalBuffer.position());
|
2014-03-10 10:27:49 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
fileBuffer.put(finalBuffer);
|
|
|
|
if (fileBuffer.position() == fileBuffer.limit() || flush) {
|
|
|
|
if (writeFrame(fileBuffer, !flush ? fileBuffer.limit() : finalBuffer.position()) != 0) {
|
|
|
|
fileBuffer.rewind();
|
2020-03-30 14:00:09 +02:00
|
|
|
recordTimeCount += fileBuffer.limit() / 2 / (sampleRate / 1000);
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
}
|
|
|
|
if (oldLimit != -1) {
|
|
|
|
finalBuffer.limit(oldLimit);
|
|
|
|
}
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
recordQueue.postRunnable(() -> recordBuffers.add(finalBuffer));
|
2014-03-10 10:27:49 +01:00
|
|
|
});
|
|
|
|
}
|
2014-03-22 23:31:55 +01:00
|
|
|
recordQueue.postRunnable(recordRunnable);
|
2020-03-30 14:00:09 +02:00
|
|
|
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordProgressChanged, recordingGuid, amplitude));
|
2014-03-22 23:31:55 +01:00
|
|
|
} else {
|
|
|
|
recordBuffers.add(buffer);
|
2019-09-10 12:56:11 +02:00
|
|
|
if (sendAfterDone != 3) {
|
|
|
|
stopRecordingInternal(sendAfterDone, sendAfterDoneNotify, sendAfterDoneScheduleDate);
|
|
|
|
}
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-04-04 19:58:33 +02: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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-24 11:21:58 +02:00
|
|
|
private static class GalleryObserverInternal extends ContentObserver {
|
2015-06-29 19:12:11 +02:00
|
|
|
public GalleryObserverInternal() {
|
|
|
|
super(null);
|
|
|
|
}
|
|
|
|
|
2016-10-11 13:57:01 +02:00
|
|
|
private void scheduleReloadRunnable() {
|
2019-01-23 18:03:33 +01:00
|
|
|
AndroidUtilities.runOnUIThread(refreshGalleryRunnable = () -> {
|
|
|
|
if (PhotoViewer.getInstance().isVisible()) {
|
|
|
|
scheduleReloadRunnable();
|
|
|
|
return;
|
2015-06-29 19:12:11 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
refreshGalleryRunnable = null;
|
|
|
|
loadGalleryPhotosAlbums(0);
|
2015-06-29 19:12:11 +02:00
|
|
|
}, 2000);
|
|
|
|
}
|
2016-10-11 13:57:01 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onChange(boolean selfChange) {
|
|
|
|
super.onChange(selfChange);
|
|
|
|
if (refreshGalleryRunnable != null) {
|
|
|
|
AndroidUtilities.cancelRunOnUIThread(refreshGalleryRunnable);
|
|
|
|
}
|
|
|
|
scheduleReloadRunnable();
|
|
|
|
}
|
2015-06-29 19:12:11 +02:00
|
|
|
}
|
|
|
|
|
2020-04-24 11:21:58 +02:00
|
|
|
private static class GalleryObserverExternal extends ContentObserver {
|
2015-06-29 19:12:11 +02:00
|
|
|
public GalleryObserverExternal() {
|
|
|
|
super(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onChange(boolean selfChange) {
|
|
|
|
super.onChange(selfChange);
|
2015-07-22 20:56:37 +02:00
|
|
|
if (refreshGalleryRunnable != null) {
|
|
|
|
AndroidUtilities.cancelRunOnUIThread(refreshGalleryRunnable);
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
AndroidUtilities.runOnUIThread(refreshGalleryRunnable = () -> {
|
|
|
|
refreshGalleryRunnable = null;
|
|
|
|
loadGalleryPhotosAlbums(0);
|
2015-06-29 19:12:11 +02:00
|
|
|
}, 2000);
|
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2015-06-29 19:12:11 +02:00
|
|
|
|
2017-12-08 18:35:59 +01:00
|
|
|
public static void checkGallery() {
|
|
|
|
if (Build.VERSION.SDK_INT < 24 || allPhotosAlbumEntry == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
final int prevSize = allPhotosAlbumEntry.photos.size();
|
2019-01-23 18:03:33 +01:00
|
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
|
|
int count = 0;
|
|
|
|
Cursor cursor = null;
|
|
|
|
try {
|
|
|
|
if (ApplicationLoader.applicationContext.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
|
|
|
cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[] {"COUNT(_id)"}, null, null, null);
|
2017-12-08 18:35:59 +01:00
|
|
|
if (cursor != null) {
|
2019-01-23 18:03:33 +01:00
|
|
|
if (cursor.moveToNext()) {
|
|
|
|
count += cursor.getInt(0);
|
2017-12-08 18:35:59 +01:00
|
|
|
}
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
}
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
} finally {
|
|
|
|
if (cursor != null) {
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (ApplicationLoader.applicationContext.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
|
|
|
cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI, new String[] {"COUNT(_id)"}, null, null, null);
|
2017-12-08 18:35:59 +01:00
|
|
|
if (cursor != null) {
|
2019-01-23 18:03:33 +01:00
|
|
|
if (cursor.moveToNext()) {
|
|
|
|
count += cursor.getInt(0);
|
|
|
|
}
|
2017-12-08 18:35:59 +01:00
|
|
|
}
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
} finally {
|
|
|
|
if (cursor != null) {
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (prevSize != count) {
|
|
|
|
if (refreshGalleryRunnable != null) {
|
|
|
|
AndroidUtilities.cancelRunOnUIThread(refreshGalleryRunnable);
|
|
|
|
refreshGalleryRunnable = null;
|
2017-12-08 18:35:59 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
loadGalleryPhotosAlbums(0);
|
2017-12-08 18:35:59 +01:00
|
|
|
}
|
|
|
|
}, 2000);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-07-23 14:56:38 +02:00
|
|
|
private ExternalObserver externalObserver;
|
|
|
|
private InternalObserver internalObserver;
|
|
|
|
private long lastChatEnterTime;
|
2018-07-30 04:07:02 +02:00
|
|
|
private int lastChatAccount;
|
2017-07-23 14:56:38 +02:00
|
|
|
private long lastChatLeaveTime;
|
|
|
|
private long lastMediaCheckTime;
|
|
|
|
private TLRPC.EncryptedChat lastSecretChat;
|
|
|
|
private TLRPC.User lastUser;
|
|
|
|
private int lastMessageId;
|
|
|
|
private ArrayList<Long> lastChatVisibleMessages;
|
|
|
|
private int startObserverToken;
|
|
|
|
private StopMediaObserverRunnable stopMediaObserverRunnable;
|
2015-07-22 20:56:37 +02:00
|
|
|
|
2014-04-04 19:58:33 +02:00
|
|
|
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) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-04-04 19:58:33 +02:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (externalObserver != null) {
|
|
|
|
ApplicationLoader.applicationContext.getContentResolver().unregisterContentObserver(externalObserver);
|
|
|
|
externalObserver = null;
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-04-04 19:58:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
private String[] mediaProjections;
|
2014-04-04 19:58:33 +02:00
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
private static volatile MediaController Instance;
|
2015-07-22 20:56:37 +02:00
|
|
|
|
2014-03-22 23:31:55 +01:00
|
|
|
public static MediaController getInstance() {
|
|
|
|
MediaController localInstance = Instance;
|
|
|
|
if (localInstance == null) {
|
|
|
|
synchronized (MediaController.class) {
|
|
|
|
localInstance = Instance;
|
|
|
|
if (localInstance == null) {
|
|
|
|
Instance = localInstance = new MediaController();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return localInstance;
|
|
|
|
}
|
|
|
|
|
2014-08-22 16:24:33 +02:00
|
|
|
public MediaController() {
|
2014-03-22 23:31:55 +01:00
|
|
|
recordQueue = new DispatchQueue("recordQueue");
|
|
|
|
recordQueue.setPriority(Thread.MAX_PRIORITY);
|
|
|
|
fileEncodingQueue = new DispatchQueue("fileEncodingQueue");
|
|
|
|
fileEncodingQueue.setPriority(Thread.MAX_PRIORITY);
|
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
recordQueue.postRunnable(() -> {
|
|
|
|
try {
|
2020-03-30 14:00:09 +02:00
|
|
|
sampleRate = 16000;
|
|
|
|
int minBuferSize = AudioRecord.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
|
|
|
|
if (minBuferSize <= 0) {
|
|
|
|
minBuferSize = 1280;
|
2019-01-23 18:03:33 +01:00
|
|
|
}
|
2020-03-30 14:00:09 +02:00
|
|
|
recordBufferSize = minBuferSize;
|
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
for (int a = 0; a < 5; a++) {
|
2020-03-30 14:00:09 +02:00
|
|
|
ByteBuffer buffer = ByteBuffer.allocateDirect(recordBufferSize);
|
2019-01-23 18:03:33 +01:00
|
|
|
buffer.order(ByteOrder.nativeOrder());
|
|
|
|
recordBuffers.add(buffer);
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
2015-11-26 22:04:02 +01:00
|
|
|
}
|
|
|
|
});
|
2019-01-23 18:03:33 +01:00
|
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
|
|
try {
|
|
|
|
currentPlaybackSpeed = MessagesController.getGlobalMainSettings().getFloat("playbackSpeed", 1.0f);
|
2019-12-31 14:08:08 +01:00
|
|
|
currentMusicPlaybackSpeed = MessagesController.getGlobalMainSettings().getFloat("musicPlaybackSpeed", 1.0f);
|
2019-01-23 18:03:33 +01:00
|
|
|
sensorManager = (SensorManager) ApplicationLoader.applicationContext.getSystemService(Context.SENSOR_SERVICE);
|
|
|
|
linearSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
|
|
|
|
gravitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
|
|
|
|
if (linearSensor == null || gravitySensor == null) {
|
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
|
|
FileLog.d("gravity or linear sensor not found");
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
|
|
|
linearSensor = null;
|
|
|
|
gravitySensor = null;
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
|
|
|
|
PowerManager powerManager = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
|
|
|
|
proximityWakeLock = powerManager.newWakeLock(0x00000020, "proximity");
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
try {
|
|
|
|
PhoneStateListener phoneStateListener = new PhoneStateListener() {
|
|
|
|
@Override
|
|
|
|
public void onCallStateChanged(final int state, String incomingNumber) {
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
if (state == TelephonyManager.CALL_STATE_RINGING) {
|
|
|
|
if (isPlayingMessage(playingMessageObject) && !isMessagePaused()) {
|
|
|
|
pauseMessage(playingMessageObject);
|
|
|
|
} else if (recordStartRunnable != null || recordingAudio != null) {
|
2019-09-10 12:56:11 +02:00
|
|
|
stopRecording(2, false, 0);
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
EmbedBottomSheet embedBottomSheet = EmbedBottomSheet.getInstance();
|
|
|
|
if (embedBottomSheet != null) {
|
|
|
|
embedBottomSheet.pause();
|
|
|
|
}
|
|
|
|
callInProgress = true;
|
|
|
|
} else if (state == TelephonyManager.CALL_STATE_IDLE) {
|
|
|
|
callInProgress = false;
|
|
|
|
} else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
|
|
|
|
EmbedBottomSheet embedBottomSheet = EmbedBottomSheet.getInstance();
|
|
|
|
if (embedBottomSheet != null) {
|
|
|
|
embedBottomSheet.pause();
|
|
|
|
}
|
|
|
|
callInProgress = true;
|
|
|
|
}
|
|
|
|
});
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
};
|
|
|
|
TelephonyManager mgr = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE);
|
|
|
|
if (mgr != null) {
|
|
|
|
mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
});
|
2014-08-22 16:24:33 +02:00
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
fileBuffer = ByteBuffer.allocateDirect(1920);
|
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) {
|
|
|
|
NotificationCenter.getInstance(a).addObserver(MediaController.this, NotificationCenter.fileDidLoad);
|
|
|
|
NotificationCenter.getInstance(a).addObserver(MediaController.this, NotificationCenter.httpFileDidLoad);
|
|
|
|
NotificationCenter.getInstance(a).addObserver(MediaController.this, NotificationCenter.didReceiveNewMessages);
|
|
|
|
NotificationCenter.getInstance(a).addObserver(MediaController.this, NotificationCenter.messagesDeleted);
|
|
|
|
NotificationCenter.getInstance(a).addObserver(MediaController.this, NotificationCenter.removeAllMessagesFromDialog);
|
|
|
|
NotificationCenter.getInstance(a).addObserver(MediaController.this, NotificationCenter.musicDidLoad);
|
2020-07-26 10:03:38 +02:00
|
|
|
NotificationCenter.getInstance(a).addObserver(MediaController.this, NotificationCenter.mediaDidLoad);
|
2019-01-23 18:03:33 +01:00
|
|
|
NotificationCenter.getGlobalInstance().addObserver(MediaController.this, NotificationCenter.playerDidStartPlaying);
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
|
|
|
});
|
2014-10-20 20:11:47 +02:00
|
|
|
|
2017-07-23 14:56:38 +02:00
|
|
|
mediaProjections = new String[]{
|
|
|
|
MediaStore.Images.ImageColumns.DATA,
|
|
|
|
MediaStore.Images.ImageColumns.DISPLAY_NAME,
|
|
|
|
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
|
2019-09-10 12:56:11 +02:00
|
|
|
Build.VERSION.SDK_INT > 28 ? MediaStore.Images.ImageColumns.DATE_MODIFIED : MediaStore.Images.ImageColumns.DATE_TAKEN,
|
2017-07-23 14:56:38 +02:00
|
|
|
MediaStore.Images.ImageColumns.TITLE,
|
|
|
|
MediaStore.Images.ImageColumns.WIDTH,
|
|
|
|
MediaStore.Images.ImageColumns.HEIGHT
|
|
|
|
};
|
2015-06-29 19:12:11 +02:00
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
ContentResolver contentResolver = ApplicationLoader.applicationContext.getContentResolver();
|
2015-07-22 20:56:37 +02:00
|
|
|
try {
|
2018-07-30 04:07:02 +02:00
|
|
|
contentResolver.registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, new GalleryObserverExternal());
|
2017-12-08 18:35:59 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
try {
|
2018-07-30 04:07:02 +02:00
|
|
|
contentResolver.registerContentObserver(MediaStore.Images.Media.INTERNAL_CONTENT_URI, true, new GalleryObserverInternal());
|
2015-06-29 19:12:11 +02:00
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2015-06-29 19:12:11 +02:00
|
|
|
}
|
|
|
|
try {
|
2018-07-30 04:07:02 +02:00
|
|
|
contentResolver.registerContentObserver(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true, new GalleryObserverExternal());
|
2017-12-08 18:35:59 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
try {
|
2018-07-30 04:07:02 +02:00
|
|
|
contentResolver.registerContentObserver(MediaStore.Video.Media.INTERNAL_CONTENT_URI, true, new GalleryObserverInternal());
|
2016-03-06 02:49:31 +01:00
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
2014-05-17 01:05:49 +02:00
|
|
|
}
|
2014-03-22 23:31:55 +01:00
|
|
|
|
2016-03-06 02:49:31 +01:00
|
|
|
@Override
|
|
|
|
public void onAudioFocusChange(int focusChange) {
|
2020-03-30 14:00:09 +02:00
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
|
|
|
|
if (isPlayingMessage(getPlayingMessageObject()) && !isMessagePaused()) {
|
|
|
|
pauseMessage(playingMessageObject);
|
|
|
|
}
|
|
|
|
hasAudioFocus = 0;
|
|
|
|
audioFocus = AUDIO_NO_FOCUS_NO_DUCK;
|
|
|
|
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
|
|
|
|
audioFocus = AUDIO_FOCUSED;
|
|
|
|
if (resumeAudioOnFocusGain) {
|
|
|
|
resumeAudioOnFocusGain = false;
|
|
|
|
if (isPlayingMessage(getPlayingMessageObject()) && isMessagePaused()) {
|
|
|
|
playMessage(getPlayingMessageObject());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
|
|
|
|
audioFocus = AUDIO_NO_FOCUS_CAN_DUCK;
|
|
|
|
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
|
|
|
|
audioFocus = AUDIO_NO_FOCUS_NO_DUCK;
|
|
|
|
if (isPlayingMessage(getPlayingMessageObject()) && !isMessagePaused()) {
|
|
|
|
pauseMessage(playingMessageObject);
|
|
|
|
resumeAudioOnFocusGain = true;
|
|
|
|
}
|
2016-05-25 23:49:47 +02:00
|
|
|
}
|
2020-03-30 14:00:09 +02:00
|
|
|
setPlayerVolume();
|
|
|
|
});
|
2016-05-25 23:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void setPlayerVolume() {
|
|
|
|
try {
|
|
|
|
float volume;
|
|
|
|
if (audioFocus != AUDIO_NO_FOCUS_CAN_DUCK) {
|
|
|
|
volume = VOLUME_NORMAL;
|
|
|
|
} else {
|
|
|
|
volume = VOLUME_DUCK;
|
|
|
|
}
|
|
|
|
if (audioPlayer != null) {
|
2018-07-30 04:07:02 +02:00
|
|
|
audioPlayer.setVolume(volume);
|
2017-07-08 18:32:04 +02:00
|
|
|
} else if (videoPlayer != null) {
|
|
|
|
videoPlayer.setVolume(volume);
|
2016-05-25 23:49:47 +02:00
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void startProgressTimer(final MessageObject currentPlayingMessageObject) {
|
2014-05-17 01:05:49 +02:00
|
|
|
synchronized (progressTimerSync) {
|
|
|
|
if (progressTimer != null) {
|
|
|
|
try {
|
|
|
|
progressTimer.cancel();
|
|
|
|
progressTimer = null;
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-05-17 01:05:49 +02:00
|
|
|
}
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
final String fileName = currentPlayingMessageObject.getFileName();
|
2014-05-17 01:05:49 +02:00
|
|
|
progressTimer = new Timer();
|
|
|
|
progressTimer.schedule(new TimerTask() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
synchronized (sync) {
|
2019-01-23 18:03:33 +01:00
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
if (currentPlayingMessageObject != null && (audioPlayer != null || videoPlayer != null) && !isPaused) {
|
|
|
|
try {
|
|
|
|
long duration;
|
|
|
|
long progress;
|
|
|
|
float value;
|
|
|
|
float bufferedValue;
|
|
|
|
if (videoPlayer != null) {
|
|
|
|
duration = videoPlayer.getDuration();
|
|
|
|
progress = videoPlayer.getCurrentPosition();
|
2019-09-10 12:56:11 +02:00
|
|
|
if (progress < 0 || duration <= 0) {
|
2019-01-23 18:03:33 +01:00
|
|
|
return;
|
|
|
|
}
|
2019-03-03 21:40:48 +01:00
|
|
|
bufferedValue = videoPlayer.getBufferedPosition() / (float) duration;
|
|
|
|
value = duration >= 0 ? progress / (float) duration : 0.0f;
|
2019-01-23 18:03:33 +01:00
|
|
|
if (value >= 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
duration = audioPlayer.getDuration();
|
|
|
|
progress = audioPlayer.getCurrentPosition();
|
2019-09-10 12:56:11 +02:00
|
|
|
value = duration >= 0 ? (progress / (float) duration) : 0.0f;
|
2019-01-23 18:03:33 +01:00
|
|
|
bufferedValue = audioPlayer.getBufferedPosition() / (float) duration;
|
|
|
|
if (duration == C.TIME_UNSET || progress < 0 || seekToProgressPending != 0) {
|
|
|
|
return;
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
lastProgress = progress;
|
|
|
|
currentPlayingMessageObject.audioPlayerDuration = (int) (duration / 1000);
|
|
|
|
currentPlayingMessageObject.audioProgress = value;
|
|
|
|
currentPlayingMessageObject.audioProgressSec = (int) (lastProgress / 1000);
|
|
|
|
currentPlayingMessageObject.bufferedProgress = bufferedValue;
|
2020-01-23 07:15:40 +01:00
|
|
|
if (value >= 0 && shouldSavePositionForCurrentAudio != null && SystemClock.elapsedRealtime() - lastSaveTime >= 1000) {
|
2019-12-31 14:08:08 +01:00
|
|
|
String saveFor = shouldSavePositionForCurrentAudio;
|
2020-01-23 07:15:40 +01:00
|
|
|
lastSaveTime = SystemClock.elapsedRealtime();
|
2019-12-31 14:08:08 +01:00
|
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
|
|
SharedPreferences.Editor editor = ApplicationLoader.applicationContext.getSharedPreferences("media_saved_pos", Activity.MODE_PRIVATE).edit();
|
|
|
|
editor.putFloat(shouldSavePositionForCurrentAudio, value).commit();
|
|
|
|
});
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
NotificationCenter.getInstance(currentPlayingMessageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingProgressDidChanged, currentPlayingMessageObject.getId(), value);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
}
|
2014-05-17 01:05:49 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, 0, 17);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void stopProgressTimer() {
|
|
|
|
synchronized (progressTimerSync) {
|
|
|
|
if (progressTimer != null) {
|
|
|
|
try {
|
|
|
|
progressTimer.cancel();
|
|
|
|
progressTimer = null;
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
}
|
2014-05-17 01:05:49 +02:00
|
|
|
}
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void cleanup() {
|
2020-07-26 10:03:38 +02:00
|
|
|
cleanupPlayer(true, true);
|
2015-07-22 20:56:37 +02:00
|
|
|
audioInfo = null;
|
2015-10-29 18:10:07 +01:00
|
|
|
playMusicAgain = false;
|
2018-07-30 04:07:02 +02:00
|
|
|
for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) {
|
|
|
|
DownloadController.getInstance(a).cleanup();
|
|
|
|
}
|
2014-09-30 00:48:11 +02:00
|
|
|
videoConvertQueue.clear();
|
2016-03-06 02:49:31 +01:00
|
|
|
generatingWaveform.clear();
|
|
|
|
voiceMessagesPlaylist = null;
|
|
|
|
voiceMessagesPlaylistMap = null;
|
2020-07-26 10:03:38 +02:00
|
|
|
clearPlaylist();
|
2014-09-30 00:48:11 +02:00
|
|
|
cancelVideoConvert(null);
|
2014-08-22 16:24:33 +02:00
|
|
|
}
|
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
private void clearPlaylist() {
|
|
|
|
playlist.clear();
|
|
|
|
playlistMap.clear();
|
|
|
|
shuffledPlaylist.clear();
|
|
|
|
playlistClassGuid = 0;
|
|
|
|
playlistEndReached[0] = playlistEndReached[1] = false;
|
|
|
|
playlistMergeDialogId = 0;
|
|
|
|
playlistMaxId[0] = playlistMaxId[1] = Integer.MAX_VALUE;
|
|
|
|
loadingPlaylist = false;
|
2020-09-30 15:48:47 +02:00
|
|
|
playlistGlobalSearchParams = null;
|
2020-07-26 10:03:38 +02:00
|
|
|
}
|
|
|
|
|
2014-04-04 19:58:33 +02:00
|
|
|
public void startMediaObserver() {
|
|
|
|
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) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-04-04 19:58:33 +02:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (externalObserver == null) {
|
|
|
|
ApplicationLoader.applicationContext.getContentResolver().registerContentObserver(MediaStore.Images.Media.INTERNAL_CONTENT_URI, false, internalObserver = new InternalObserver());
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-04-04 19:58:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void stopMediaObserver() {
|
|
|
|
if (stopMediaObserverRunnable == null) {
|
|
|
|
stopMediaObserverRunnable = new StopMediaObserverRunnable();
|
|
|
|
}
|
|
|
|
stopMediaObserverRunnable.currentObserverToken = startObserverToken;
|
|
|
|
ApplicationLoader.applicationHandler.postDelayed(stopMediaObserverRunnable, 5000);
|
|
|
|
}
|
|
|
|
|
2017-07-23 14:56:38 +02:00
|
|
|
private void processMediaObserver(Uri uri) {
|
2018-07-30 04:07:02 +02:00
|
|
|
Cursor cursor = null;
|
2014-04-04 19:58:33 +02:00
|
|
|
try {
|
2014-11-07 11:23:17 +01:00
|
|
|
Point size = AndroidUtilities.getRealScreenSize();
|
2014-10-20 20:11:47 +02:00
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
cursor = ApplicationLoader.applicationContext.getContentResolver().query(uri, mediaProjections, null, null, "date_added DESC LIMIT 1");
|
2015-01-02 23:15:07 +01:00
|
|
|
final ArrayList<Long> screenshotDates = new ArrayList<>();
|
2014-04-04 19:58:33 +02:00
|
|
|
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);
|
|
|
|
long date = cursor.getLong(3);
|
2014-10-20 20:11:47 +02:00
|
|
|
String title = cursor.getString(4);
|
2017-07-23 14:56:38 +02:00
|
|
|
int photoW = cursor.getInt(5);
|
|
|
|
int photoH = cursor.getInt(6);
|
2014-04-04 19:58:33 +02:00
|
|
|
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")) {
|
|
|
|
try {
|
2014-10-20 20:11:47 +02:00
|
|
|
if (photoW == 0 || photoH == 0) {
|
|
|
|
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
|
|
|
|
bmOptions.inJustDecodeBounds = true;
|
|
|
|
BitmapFactory.decodeFile(data, bmOptions);
|
|
|
|
photoW = bmOptions.outWidth;
|
|
|
|
photoH = bmOptions.outHeight;
|
2014-04-04 19:58:33 +02:00
|
|
|
}
|
2014-11-07 11:23:17 +01:00
|
|
|
if (photoW <= 0 || photoH <= 0 || (photoW == size.x && photoH == size.y || photoH == size.x && photoW == size.y)) {
|
2014-04-04 19:58:33 +02:00
|
|
|
screenshotDates.add(date);
|
|
|
|
}
|
2014-10-20 20:11:47 +02:00
|
|
|
} catch (Exception e) {
|
|
|
|
screenshotDates.add(date);
|
|
|
|
}
|
2014-04-04 19:58:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
if (!screenshotDates.isEmpty()) {
|
2019-01-23 18:03:33 +01:00
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
NotificationCenter.getInstance(lastChatAccount).postNotificationName(NotificationCenter.screenshotTook);
|
|
|
|
checkScreenshots(screenshotDates);
|
2014-04-04 19:58:33 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2018-07-30 04:07:02 +02:00
|
|
|
} finally {
|
|
|
|
try {
|
|
|
|
if (cursor != null) {
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
} catch (Exception ignore) {
|
|
|
|
|
|
|
|
}
|
2014-04-04 19:58:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void checkScreenshots(ArrayList<Long> dates) {
|
2017-07-23 14:56:38 +02:00
|
|
|
if (dates == null || dates.isEmpty() || lastChatEnterTime == 0 || (lastUser == null && !(lastSecretChat instanceof TLRPC.TL_encryptedChat))) {
|
2014-04-04 19:58:33 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
long dt = 2000;
|
|
|
|
boolean send = false;
|
2017-07-23 14:56:38 +02:00
|
|
|
for (int a = 0; a < dates.size(); a++) {
|
|
|
|
Long date = dates.get(a);
|
2014-04-04 19:58:33 +02:00
|
|
|
if (lastMediaCheckTime != 0 && date <= lastMediaCheckTime) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-07-23 14:56:38 +02:00
|
|
|
if (date >= lastChatEnterTime) {
|
|
|
|
if (lastChatLeaveTime == 0 || date <= lastChatLeaveTime + dt) {
|
2014-04-04 19:58:33 +02:00
|
|
|
lastMediaCheckTime = Math.max(lastMediaCheckTime, date);
|
|
|
|
send = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (send) {
|
2017-07-23 14:56:38 +02:00
|
|
|
if (lastSecretChat != null) {
|
2018-07-30 04:07:02 +02:00
|
|
|
SecretChatHelper.getInstance(lastChatAccount).sendScreenshotMessage(lastSecretChat, lastChatVisibleMessages, null);
|
2017-07-23 14:56:38 +02:00
|
|
|
} else {
|
2018-07-30 04:07:02 +02:00
|
|
|
SendMessagesHelper.getInstance(lastChatAccount).sendScreenshotMessage(lastUser, lastMessageId, null);
|
2017-07-23 14:56:38 +02:00
|
|
|
}
|
2014-04-04 19:58:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
public void setLastVisibleMessageIds(int account, long enterTime, long leaveTime, TLRPC.User user, TLRPC.EncryptedChat encryptedChat, ArrayList<Long> visibleMessages, int visibleMessage) {
|
2017-07-23 14:56:38 +02:00
|
|
|
lastChatEnterTime = enterTime;
|
|
|
|
lastChatLeaveTime = leaveTime;
|
2018-07-30 04:07:02 +02:00
|
|
|
lastChatAccount = account;
|
2014-04-04 19:58:33 +02:00
|
|
|
lastSecretChat = encryptedChat;
|
2017-07-23 14:56:38 +02:00
|
|
|
lastUser = user;
|
|
|
|
lastMessageId = visibleMessage;
|
|
|
|
lastChatVisibleMessages = visibleMessages;
|
2014-04-04 19:58:33 +02:00
|
|
|
}
|
|
|
|
|
2014-10-21 22:35:16 +02:00
|
|
|
@SuppressWarnings("unchecked")
|
2014-02-28 23:28:25 +01:00
|
|
|
@Override
|
2018-07-30 04:07:02 +02:00
|
|
|
public void didReceivedNotification(int id, int account, Object... args) {
|
2019-01-23 18:03:33 +01:00
|
|
|
if (id == NotificationCenter.fileDidLoad || id == NotificationCenter.httpFileDidLoad) {
|
2015-07-22 20:56:37 +02:00
|
|
|
String fileName = (String) args[0];
|
2020-07-26 10:03:38 +02:00
|
|
|
if (playingMessageObject != null && playingMessageObject.currentAccount == account) {
|
2016-04-22 15:49:00 +02:00
|
|
|
String file = FileLoader.getAttachFileName(playingMessageObject.getDocument());
|
2015-07-22 20:56:37 +02:00
|
|
|
if (file.equals(fileName)) {
|
2020-07-26 10:03:38 +02:00
|
|
|
if (downloadingCurrentMessage) {
|
|
|
|
playMusicAgain = true;
|
|
|
|
playMessage(playingMessageObject);
|
|
|
|
} else if (audioInfo == null) {
|
|
|
|
try {
|
|
|
|
File cacheFile = FileLoader.getPathToMessage(playingMessageObject.messageOwner);
|
|
|
|
audioInfo = AudioInfo.getAudioInfo(cacheFile);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
|
|
|
}
|
2014-10-21 22:35:16 +02:00
|
|
|
} else if (id == NotificationCenter.messagesDeleted) {
|
2019-09-10 12:56:11 +02:00
|
|
|
boolean scheduled = (Boolean) args[2];
|
|
|
|
if (scheduled) {
|
|
|
|
return;
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
int channelId = (Integer) args[1];
|
|
|
|
ArrayList<Integer> markAsDeletedMessages = (ArrayList<Integer>) args[0];
|
2014-10-21 22:35:16 +02:00
|
|
|
if (playingMessageObject != null) {
|
2020-09-30 15:48:47 +02:00
|
|
|
if (channelId == playingMessageObject.messageOwner.peer_id.channel_id) {
|
2016-03-06 02:49:31 +01:00
|
|
|
if (markAsDeletedMessages.contains(playingMessageObject.getId())) {
|
|
|
|
cleanupPlayer(true, true);
|
|
|
|
}
|
2015-09-24 22:52:02 +02:00
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
|
|
|
if (voiceMessagesPlaylist != null && !voiceMessagesPlaylist.isEmpty()) {
|
|
|
|
MessageObject messageObject = voiceMessagesPlaylist.get(0);
|
2020-09-30 15:48:47 +02:00
|
|
|
if (channelId == messageObject.messageOwner.peer_id.channel_id) {
|
2016-03-06 02:49:31 +01:00
|
|
|
for (int a = 0; a < markAsDeletedMessages.size(); a++) {
|
2018-07-30 04:07:02 +02:00
|
|
|
Integer key = markAsDeletedMessages.get(a);
|
|
|
|
messageObject = voiceMessagesPlaylistMap.get(key);
|
|
|
|
voiceMessagesPlaylistMap.remove(key);
|
2016-03-06 02:49:31 +01:00
|
|
|
if (messageObject != null) {
|
|
|
|
voiceMessagesPlaylist.remove(messageObject);
|
|
|
|
}
|
|
|
|
}
|
2014-10-21 22:35:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (id == NotificationCenter.removeAllMessagesFromDialog) {
|
2015-07-22 20:56:37 +02:00
|
|
|
long did = (Long) args[0];
|
2014-10-21 22:35:16 +02:00
|
|
|
if (playingMessageObject != null && playingMessageObject.getDialogId() == did) {
|
2015-10-29 18:10:07 +01:00
|
|
|
cleanupPlayer(false, true);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
} else if (id == NotificationCenter.musicDidLoad) {
|
2015-07-22 20:56:37 +02:00
|
|
|
long did = (Long) args[0];
|
2019-09-10 12:56:11 +02:00
|
|
|
if (playingMessageObject != null && playingMessageObject.isMusic() && playingMessageObject.getDialogId() == did && !playingMessageObject.scheduled) {
|
2020-07-26 10:03:38 +02:00
|
|
|
ArrayList<MessageObject> arrayListBegin = (ArrayList<MessageObject>) args[1];
|
|
|
|
ArrayList<MessageObject> arrayListEnd = (ArrayList<MessageObject>) args[2];
|
|
|
|
playlist.addAll(0, arrayListBegin);
|
|
|
|
playlist.addAll(arrayListEnd);
|
|
|
|
for (int a = 0, N = playlist.size(); a < N; a++) {
|
|
|
|
MessageObject object = playlist.get(a);
|
|
|
|
playlistMap.put(object.getId(), object);
|
|
|
|
playlistMaxId[0] = Math.min(playlistMaxId[0], object.getId());
|
|
|
|
}
|
|
|
|
playlistClassGuid = ConnectionsManager.generateClassGuid();
|
2018-07-30 04:07:02 +02:00
|
|
|
if (SharedConfig.shuffleMusic) {
|
2015-07-22 20:56:37 +02:00
|
|
|
buildShuffledPlayList();
|
|
|
|
currentPlaylistNum = 0;
|
|
|
|
} else {
|
2020-07-26 10:03:38 +02:00
|
|
|
currentPlaylistNum += arrayListBegin.size();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (id == NotificationCenter.mediaDidLoad) {
|
|
|
|
int guid = (Integer) args[3];
|
2020-07-26 23:11:01 +02:00
|
|
|
if (guid == playlistClassGuid && playingMessageObject != null) {
|
2020-07-26 10:03:38 +02:00
|
|
|
long did = (Long) args[0];
|
|
|
|
int type = (Integer) args[4];
|
|
|
|
|
|
|
|
ArrayList<MessageObject> arr = (ArrayList<MessageObject>) args[2];
|
|
|
|
boolean enc = ((int) did) == 0;
|
|
|
|
int loadIndex = did == playlistMergeDialogId ? 1 : 0;
|
|
|
|
if (!arr.isEmpty()) {
|
|
|
|
playlistEndReached[loadIndex] = (Boolean) args[5];
|
|
|
|
}
|
|
|
|
int addedCount = 0;
|
|
|
|
for (int a = 0; a < arr.size(); a++) {
|
|
|
|
MessageObject message = arr.get(a);
|
|
|
|
if (playlistMap.containsKey(message.getId())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
addedCount++;
|
|
|
|
playlist.add(0, message);
|
|
|
|
playlistMap.put(message.getId(), message);
|
|
|
|
playlistMaxId[loadIndex] = Math.min(playlistMaxId[loadIndex], message.getId());
|
|
|
|
}
|
|
|
|
loadingPlaylist = false;
|
|
|
|
if (SharedConfig.shuffleMusic) {
|
|
|
|
buildShuffledPlayList();
|
|
|
|
}
|
|
|
|
if (addedCount != 0) {
|
|
|
|
NotificationCenter.getInstance(playingMessageObject.currentAccount).postNotificationName(NotificationCenter.moreMusicDidLoad, addedCount);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2014-10-21 22:35:16 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
} else if (id == NotificationCenter.didReceiveNewMessages) {
|
2019-09-10 12:56:11 +02:00
|
|
|
boolean scheduled = (Boolean) args[2];
|
|
|
|
if (scheduled) {
|
|
|
|
return;
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
if (voiceMessagesPlaylist != null && !voiceMessagesPlaylist.isEmpty()) {
|
|
|
|
MessageObject messageObject = voiceMessagesPlaylist.get(0);
|
|
|
|
long did = (Long) args[0];
|
|
|
|
if (did == messageObject.getDialogId()) {
|
|
|
|
ArrayList<MessageObject> arr = (ArrayList<MessageObject>) args[1];
|
|
|
|
for (int a = 0; a < arr.size(); a++) {
|
|
|
|
messageObject = arr.get(a);
|
2017-07-08 18:32:04 +02:00
|
|
|
if ((messageObject.isVoice() || messageObject.isRoundVideo()) && (!voiceMessagesPlaylistUnread || messageObject.isContentUnread() && !messageObject.isOut())) {
|
2016-03-06 02:49:31 +01:00
|
|
|
voiceMessagesPlaylist.add(messageObject);
|
|
|
|
voiceMessagesPlaylistMap.put(messageObject.getId(), messageObject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
} else if (id == NotificationCenter.playerDidStartPlaying) {
|
|
|
|
VideoPlayer p = (VideoPlayer) args[0];
|
|
|
|
if (!MediaController.getInstance().isCurrentPlayer(p)) {
|
|
|
|
MediaController.getInstance().pauseMessage(MediaController.getInstance().getPlayingMessageObject());
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
|
2016-03-06 02:49:31 +01:00
|
|
|
protected boolean isRecordingAudio() {
|
|
|
|
return recordStartRunnable != null || recordingAudio != null;
|
|
|
|
}
|
|
|
|
|
2015-05-21 23:27:27 +02:00
|
|
|
private boolean isNearToSensor(float value) {
|
|
|
|
return value < 5.0f && value != proximitySensor.getMaximumRange();
|
|
|
|
}
|
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
public boolean isRecordingOrListeningByProximity() {
|
|
|
|
return proximityTouched && (isRecordingAudio() || playingMessageObject != null && (playingMessageObject.isVoice() || playingMessageObject.isRoundVideo()));
|
|
|
|
}
|
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
@Override
|
|
|
|
public void onSensorChanged(SensorEvent event) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (!sensorsStarted || VoIPService.getSharedInstance() != null) {
|
2015-01-02 23:15:07 +01:00
|
|
|
return;
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
if (event.sensor == proximitySensor) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
2019-05-14 14:08:05 +02:00
|
|
|
FileLog.d("proximity changed to " + event.values[0] + " max value = " + proximitySensor.getMaximumRange());
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
if (lastProximityValue == -100) {
|
|
|
|
lastProximityValue = event.values[0];
|
|
|
|
} else if (lastProximityValue != event.values[0]) {
|
|
|
|
proximityHasDifferentValues = true;
|
|
|
|
}
|
|
|
|
if (proximityHasDifferentValues) {
|
|
|
|
proximityTouched = isNearToSensor(event.values[0]);
|
|
|
|
}
|
|
|
|
} else if (event.sensor == accelerometerSensor) {
|
|
|
|
final double alpha = lastTimestamp == 0 ? 0.98f : 1.0 / (1.0 + (event.timestamp - lastTimestamp) / 1000000000.0);
|
|
|
|
final float alphaFast = 0.8f;
|
|
|
|
lastTimestamp = event.timestamp;
|
|
|
|
gravity[0] = (float) (alpha * gravity[0] + (1.0 - alpha) * event.values[0]);
|
|
|
|
gravity[1] = (float) (alpha * gravity[1] + (1.0 - alpha) * event.values[1]);
|
|
|
|
gravity[2] = (float) (alpha * gravity[2] + (1.0 - alpha) * event.values[2]);
|
|
|
|
gravityFast[0] = (alphaFast * gravity[0] + (1.0f - alphaFast) * event.values[0]);
|
|
|
|
gravityFast[1] = (alphaFast * gravity[1] + (1.0f - alphaFast) * event.values[1]);
|
|
|
|
gravityFast[2] = (alphaFast * gravity[2] + (1.0f - alphaFast) * event.values[2]);
|
|
|
|
|
|
|
|
linearAcceleration[0] = event.values[0] - gravity[0];
|
|
|
|
linearAcceleration[1] = event.values[1] - gravity[1];
|
|
|
|
linearAcceleration[2] = event.values[2] - gravity[2];
|
|
|
|
} else if (event.sensor == linearSensor) {
|
|
|
|
linearAcceleration[0] = event.values[0];
|
|
|
|
linearAcceleration[1] = event.values[1];
|
|
|
|
linearAcceleration[2] = event.values[2];
|
|
|
|
} else if (event.sensor == gravitySensor) {
|
|
|
|
gravityFast[0] = gravity[0] = event.values[0];
|
|
|
|
gravityFast[1] = gravity[1] = event.values[1];
|
|
|
|
gravityFast[2] = gravity[2] = event.values[2];
|
|
|
|
}
|
|
|
|
final float minDist = 15.0f;
|
|
|
|
final int minCount = 6;
|
|
|
|
final int countLessMax = 10;
|
|
|
|
if (event.sensor == linearSensor || event.sensor == gravitySensor || event.sensor == accelerometerSensor) {
|
|
|
|
float val = gravity[0] * linearAcceleration[0] + gravity[1] * linearAcceleration[1] + gravity[2] * linearAcceleration[2];
|
|
|
|
if (raisedToBack != minCount) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (val > 0 && previousAccValue > 0 || val < 0 && previousAccValue < 0) {
|
|
|
|
boolean goodValue;
|
|
|
|
int sign;
|
|
|
|
if (val > 0) {
|
|
|
|
goodValue = val > minDist;
|
|
|
|
sign = 1;
|
|
|
|
} else {
|
|
|
|
goodValue = val < -minDist;
|
|
|
|
sign = 2;
|
|
|
|
}
|
|
|
|
if (raisedToTopSign != 0 && raisedToTopSign != sign) {
|
|
|
|
if (raisedToTop == minCount && goodValue) {
|
|
|
|
if (raisedToBack < minCount) {
|
|
|
|
raisedToBack++;
|
|
|
|
if (raisedToBack == minCount) {
|
|
|
|
raisedToTop = 0;
|
|
|
|
raisedToTopSign = 0;
|
|
|
|
countLess = 0;
|
|
|
|
timeSinceRaise = System.currentTimeMillis();
|
|
|
|
if (BuildVars.LOGS_ENABLED && BuildVars.DEBUG_PRIVATE_VERSION) {
|
|
|
|
FileLog.d("motion detected");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!goodValue) {
|
|
|
|
countLess++;
|
|
|
|
}
|
|
|
|
if (countLess == countLessMax || raisedToTop != minCount || raisedToBack != 0) {
|
|
|
|
raisedToTop = 0;
|
|
|
|
raisedToTopSign = 0;
|
|
|
|
raisedToBack = 0;
|
|
|
|
countLess = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (goodValue && raisedToBack == 0 && (raisedToTopSign == 0 || raisedToTopSign == sign)) {
|
|
|
|
if (raisedToTop < minCount && !proximityTouched) {
|
|
|
|
raisedToTopSign = sign;
|
|
|
|
raisedToTop++;
|
|
|
|
if (raisedToTop == minCount) {
|
|
|
|
countLess = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!goodValue) {
|
|
|
|
countLess++;
|
|
|
|
}
|
|
|
|
if (raisedToTopSign != sign || countLess == countLessMax || raisedToTop != minCount || raisedToBack != 0) {
|
|
|
|
raisedToBack = 0;
|
|
|
|
raisedToTop = 0;
|
|
|
|
raisedToTopSign = 0;
|
|
|
|
countLess = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*if (val > 0 && previousAccValue > 0) {
|
2016-03-06 02:49:31 +01:00
|
|
|
if (val > minDist && raisedToBack == 0) {
|
|
|
|
if (raisedToTop < minCount && !proximityTouched) {
|
|
|
|
raisedToTop++;
|
|
|
|
if (raisedToTop == minCount) {
|
|
|
|
countLess = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (val < minDist) {
|
|
|
|
countLess++;
|
|
|
|
}
|
|
|
|
if (countLess == countLessMax || raisedToTop != minCount || raisedToBack != 0) {
|
|
|
|
raisedToBack = 0;
|
|
|
|
raisedToTop = 0;
|
|
|
|
countLess = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (val < 0 && previousAccValue < 0) {
|
|
|
|
if (raisedToTop == minCount && val < -minDist) {
|
|
|
|
if (raisedToBack < minCount) {
|
|
|
|
raisedToBack++;
|
|
|
|
if (raisedToBack == minCount) {
|
|
|
|
raisedToTop = 0;
|
|
|
|
countLess = 0;
|
|
|
|
timeSinceRaise = System.currentTimeMillis();
|
2018-07-30 04:07:02 +02:00
|
|
|
if (BuildVars.LOGS_ENABLED && BuildVars.DEBUG_PRIVATE_VERSION) {
|
|
|
|
FileLog.e("motion detected");
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (val > -minDist) {
|
|
|
|
countLess++;
|
|
|
|
}
|
|
|
|
if (countLess == countLessMax || raisedToTop != minCount || raisedToBack != 0) {
|
|
|
|
raisedToTop = 0;
|
|
|
|
raisedToBack = 0;
|
|
|
|
countLess = 0;
|
|
|
|
}
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
}*/
|
|
|
|
/*if (BuildVars.LOGS_ENABLED && BuildVars.DEBUG_PRIVATE_VERSION) {
|
|
|
|
FileLog.e("raise2 to top = " + raisedToTop + " to back = " + raisedToBack + " val = " + val + " countLess = " + countLess);
|
|
|
|
}*/
|
2015-04-09 20:00:14 +02:00
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
previousAccValue = val;
|
2018-07-30 04:07:02 +02:00
|
|
|
accelerometerVertical = gravityFast[1] > 2.5f && Math.abs(gravityFast[2]) < 4.0f && Math.abs(gravityFast[0]) > 1.5f;
|
|
|
|
/*if (BuildVars.LOGS_ENABLED && BuildVars.DEBUG_PRIVATE_VERSION) {
|
|
|
|
FileLog.d(accelerometerVertical + " val = " + val + " acc (" + linearAcceleration[0] + ", " + linearAcceleration[1] + ", " + linearAcceleration[2] + ") grav (" + gravityFast[0] + ", " + gravityFast[1] + ", " + gravityFast[2] + ")");
|
|
|
|
}*/
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
if (raisedToBack == minCount && accelerometerVertical && proximityTouched && !NotificationsController.audioManager.isWiredHeadsetOn()) {
|
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
|
|
FileLog.d("sensor values reached");
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
if (playingMessageObject == null && recordStartRunnable == null && recordingAudio == null && !PhotoViewer.getInstance().isVisible() && ApplicationLoader.isScreenOn && !inputFieldHasText && allowStartRecord && raiseChat != null && !callInProgress) {
|
|
|
|
if (!raiseToEarRecord) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
|
|
FileLog.d("start record");
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
useFrontSpeaker = true;
|
|
|
|
if (!raiseChat.playFirstUnreadVoiceMessage()) {
|
|
|
|
raiseToEarRecord = true;
|
|
|
|
useFrontSpeaker = false;
|
2020-09-30 15:48:47 +02:00
|
|
|
startRecording(raiseChat.getCurrentAccount(), raiseChat.getDialogId(), null, raiseChat.getThreadMessage(), raiseChat.getClassGuid());
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
if (useFrontSpeaker) {
|
|
|
|
setUseFrontSpeaker(true);
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
ignoreOnPause = true;
|
2016-04-22 15:49:00 +02:00
|
|
|
if (proximityHasDifferentValues && proximityWakeLock != null && !proximityWakeLock.isHeld()) {
|
2016-03-06 02:49:31 +01:00
|
|
|
proximityWakeLock.acquire();
|
|
|
|
}
|
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
} else if (playingMessageObject != null && (playingMessageObject.isVoice() || playingMessageObject.isRoundVideo())) {
|
2016-03-06 02:49:31 +01:00
|
|
|
if (!useFrontSpeaker) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
|
|
FileLog.d("start listen");
|
|
|
|
}
|
2016-04-22 15:49:00 +02:00
|
|
|
if (proximityHasDifferentValues && proximityWakeLock != null && !proximityWakeLock.isHeld()) {
|
2016-03-06 02:49:31 +01:00
|
|
|
proximityWakeLock.acquire();
|
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
setUseFrontSpeaker(true);
|
2016-03-06 02:49:31 +01:00
|
|
|
startAudioAgain(false);
|
|
|
|
ignoreOnPause = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
raisedToBack = 0;
|
|
|
|
raisedToTop = 0;
|
2018-07-30 04:07:02 +02:00
|
|
|
raisedToTopSign = 0;
|
2016-03-06 02:49:31 +01:00
|
|
|
countLess = 0;
|
|
|
|
} else if (proximityTouched) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (playingMessageObject != null && !ApplicationLoader.mainInterfacePaused && (playingMessageObject.isVoice() || playingMessageObject.isRoundVideo())) {
|
2019-12-31 20:46:59 +01:00
|
|
|
if (!useFrontSpeaker && !NotificationsController.audioManager.isWiredHeadsetOn()) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
|
|
FileLog.d("start listen by proximity only");
|
|
|
|
}
|
2016-04-22 15:49:00 +02:00
|
|
|
if (proximityHasDifferentValues && proximityWakeLock != null && !proximityWakeLock.isHeld()) {
|
2016-03-06 02:49:31 +01:00
|
|
|
proximityWakeLock.acquire();
|
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
setUseFrontSpeaker(true);
|
2016-03-06 02:49:31 +01:00
|
|
|
startAudioAgain(false);
|
|
|
|
ignoreOnPause = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (!proximityTouched) {
|
|
|
|
if (raiseToEarRecord) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
|
|
FileLog.d("stop record");
|
|
|
|
}
|
2019-09-10 12:56:11 +02:00
|
|
|
stopRecording(2, false, 0);
|
2016-03-06 02:49:31 +01:00
|
|
|
raiseToEarRecord = false;
|
|
|
|
ignoreOnPause = false;
|
2016-04-22 15:49:00 +02:00
|
|
|
if (proximityHasDifferentValues && proximityWakeLock != null && proximityWakeLock.isHeld()) {
|
2016-03-06 02:49:31 +01:00
|
|
|
proximityWakeLock.release();
|
|
|
|
}
|
|
|
|
} else if (useFrontSpeaker) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
|
|
FileLog.d("stop listen");
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
useFrontSpeaker = false;
|
|
|
|
startAudioAgain(true);
|
|
|
|
ignoreOnPause = false;
|
2016-04-22 15:49:00 +02:00
|
|
|
if (proximityHasDifferentValues && proximityWakeLock != null && proximityWakeLock.isHeld()) {
|
2016-03-06 02:49:31 +01:00
|
|
|
proximityWakeLock.release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (timeSinceRaise != 0 && raisedToBack == minCount && Math.abs(System.currentTimeMillis() - timeSinceRaise) > 1000) {
|
|
|
|
raisedToBack = 0;
|
|
|
|
raisedToTop = 0;
|
2018-07-30 04:07:02 +02:00
|
|
|
raisedToTopSign = 0;
|
2016-03-06 02:49:31 +01:00
|
|
|
countLess = 0;
|
|
|
|
timeSinceRaise = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-08 18:32:04 +02:00
|
|
|
private void setUseFrontSpeaker(boolean value) {
|
|
|
|
useFrontSpeaker = value;
|
2018-07-30 04:07:02 +02:00
|
|
|
AudioManager audioManager = NotificationsController.audioManager;
|
2017-07-08 18:32:04 +02:00
|
|
|
if (useFrontSpeaker) {
|
|
|
|
audioManager.setBluetoothScoOn(false);
|
|
|
|
audioManager.setSpeakerphoneOn(false);
|
|
|
|
} else {
|
|
|
|
audioManager.setSpeakerphoneOn(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-06 02:49:31 +01:00
|
|
|
public void startRecordingIfFromSpeaker() {
|
2019-12-31 14:08:08 +01:00
|
|
|
if (!useFrontSpeaker || raiseChat == null || !allowStartRecord || !SharedConfig.raiseToSpeak) {
|
2016-03-06 02:49:31 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
raiseToEarRecord = true;
|
2020-09-30 15:48:47 +02:00
|
|
|
startRecording(raiseChat.getCurrentAccount(), raiseChat.getDialogId(), null, raiseChat.getThreadMessage(), raiseChat.getClassGuid());
|
2016-03-06 02:49:31 +01:00
|
|
|
ignoreOnPause = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void startAudioAgain(boolean paused) {
|
|
|
|
if (playingMessageObject == null) {
|
|
|
|
return;
|
2015-04-09 20:00:14 +02:00
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
NotificationCenter.getInstance(playingMessageObject.currentAccount).postNotificationName(NotificationCenter.audioRouteChanged, useFrontSpeaker);
|
2017-07-08 18:32:04 +02:00
|
|
|
if (videoPlayer != null) {
|
|
|
|
videoPlayer.setStreamType(useFrontSpeaker ? AudioManager.STREAM_VOICE_CALL : AudioManager.STREAM_MUSIC);
|
|
|
|
if (!paused) {
|
2019-12-31 14:08:08 +01:00
|
|
|
if (videoPlayer.getCurrentPosition() < 1000) {
|
|
|
|
videoPlayer.seekTo(0);
|
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
videoPlayer.play();
|
2016-03-16 13:26:32 +01:00
|
|
|
} else {
|
2019-03-03 21:40:48 +01:00
|
|
|
pauseMessage(playingMessageObject);
|
2017-07-08 18:32:04 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
boolean post = audioPlayer != null;
|
|
|
|
final MessageObject currentMessageObject = playingMessageObject;
|
|
|
|
float progress = playingMessageObject.audioProgress;
|
2019-12-31 14:08:08 +01:00
|
|
|
int duration = playingMessageObject.audioPlayerDuration;
|
|
|
|
if (paused || audioPlayer == null || !audioPlayer.isPlaying() || duration * progress > 1f) {
|
|
|
|
currentMessageObject.audioProgress = progress;
|
|
|
|
} else {
|
|
|
|
currentMessageObject.audioProgress = 0;
|
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
cleanupPlayer(false, true);
|
|
|
|
playMessage(currentMessageObject);
|
|
|
|
if (paused) {
|
|
|
|
if (post) {
|
2019-01-23 18:03:33 +01:00
|
|
|
AndroidUtilities.runOnUIThread(() -> pauseMessage(currentMessageObject), 100);
|
2017-07-08 18:32:04 +02:00
|
|
|
} else {
|
|
|
|
pauseMessage(currentMessageObject);
|
|
|
|
}
|
2016-03-16 13:26:32 +01:00
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
2015-01-02 23:15:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-03-06 02:49:31 +01:00
|
|
|
public void setInputFieldHasText(boolean value) {
|
|
|
|
inputFieldHasText = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setAllowStartRecord(boolean value) {
|
|
|
|
allowStartRecord = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void startRaiseToEarSensors(ChatActivity chatActivity) {
|
|
|
|
if (chatActivity == null || accelerometerSensor == null && (gravitySensor == null || linearAcceleration == null) || proximitySensor == null) {
|
2015-01-02 23:15:07 +01:00
|
|
|
return;
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
raiseChat = chatActivity;
|
2018-07-30 04:07:02 +02:00
|
|
|
if (!SharedConfig.raiseToSpeak && (playingMessageObject == null || !playingMessageObject.isVoice() && !playingMessageObject.isRoundVideo())) {
|
2016-03-06 02:49:31 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!sensorsStarted) {
|
|
|
|
gravity[0] = gravity[1] = gravity[2] = 0;
|
|
|
|
linearAcceleration[0] = linearAcceleration[1] = linearAcceleration[2] = 0;
|
|
|
|
gravityFast[0] = gravityFast[1] = gravityFast[2] = 0;
|
|
|
|
lastTimestamp = 0;
|
|
|
|
previousAccValue = 0;
|
|
|
|
raisedToTop = 0;
|
2018-07-30 04:07:02 +02:00
|
|
|
raisedToTopSign = 0;
|
2016-03-06 02:49:31 +01:00
|
|
|
countLess = 0;
|
|
|
|
raisedToBack = 0;
|
2019-01-23 18:03:33 +01:00
|
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
|
|
if (gravitySensor != null) {
|
|
|
|
sensorManager.registerListener(MediaController.this, gravitySensor, 30000);
|
|
|
|
}
|
|
|
|
if (linearSensor != null) {
|
|
|
|
sensorManager.registerListener(MediaController.this, linearSensor, 30000);
|
|
|
|
}
|
|
|
|
if (accelerometerSensor != null) {
|
|
|
|
sensorManager.registerListener(MediaController.this, accelerometerSensor, 30000);
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
sensorManager.registerListener(MediaController.this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
|
2016-03-06 02:49:31 +01:00
|
|
|
});
|
|
|
|
sensorsStarted = true;
|
2015-01-02 23:15:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
public void stopRaiseToEarSensors(ChatActivity chatActivity, boolean fromChat) {
|
2016-03-06 02:49:31 +01:00
|
|
|
if (ignoreOnPause) {
|
|
|
|
ignoreOnPause = false;
|
2015-01-02 23:15:07 +01:00
|
|
|
return;
|
|
|
|
}
|
2019-09-10 12:56:11 +02:00
|
|
|
stopRecording(fromChat ? 2 : 0, false, 0);
|
2016-03-06 02:49:31 +01:00
|
|
|
if (!sensorsStarted || ignoreOnPause || accelerometerSensor == null && (gravitySensor == null || linearAcceleration == null) || proximitySensor == null || raiseChat != chatActivity) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
raiseChat = null;
|
|
|
|
sensorsStarted = false;
|
|
|
|
accelerometerVertical = false;
|
|
|
|
proximityTouched = false;
|
|
|
|
raiseToEarRecord = false;
|
|
|
|
useFrontSpeaker = false;
|
2019-01-23 18:03:33 +01:00
|
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
|
|
if (linearSensor != null) {
|
|
|
|
sensorManager.unregisterListener(MediaController.this, linearSensor);
|
|
|
|
}
|
|
|
|
if (gravitySensor != null) {
|
|
|
|
sensorManager.unregisterListener(MediaController.this, gravitySensor);
|
2015-06-29 19:12:11 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
if (accelerometerSensor != null) {
|
|
|
|
sensorManager.unregisterListener(MediaController.this, accelerometerSensor);
|
|
|
|
}
|
|
|
|
sensorManager.unregisterListener(MediaController.this, proximitySensor);
|
2016-03-06 02:49:31 +01:00
|
|
|
});
|
2016-04-22 15:49:00 +02:00
|
|
|
if (proximityHasDifferentValues && proximityWakeLock != null && proximityWakeLock.isHeld()) {
|
2016-03-06 02:49:31 +01:00
|
|
|
proximityWakeLock.release();
|
2015-01-02 23:15:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-29 18:10:07 +01:00
|
|
|
public void cleanupPlayer(boolean notify, boolean stopService) {
|
2019-03-03 21:40:48 +01:00
|
|
|
cleanupPlayer(notify, stopService, false, false);
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
|
|
|
|
2019-03-03 21:40:48 +01:00
|
|
|
public void cleanupPlayer(boolean notify, boolean stopService, boolean byVoiceEnd, boolean transferPlayerToPhotoViewer) {
|
2015-10-29 18:10:07 +01:00
|
|
|
if (audioPlayer != null) {
|
|
|
|
try {
|
2019-03-03 21:40:48 +01:00
|
|
|
audioPlayer.releasePlayer(true);
|
2015-10-29 18:10:07 +01:00
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2015-10-29 18:10:07 +01:00
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
audioPlayer = null;
|
2020-06-04 18:47:15 +02:00
|
|
|
Theme.unrefAudioVisualizeDrawable(playingMessageObject);
|
2017-07-08 18:32:04 +02:00
|
|
|
} else if (videoPlayer != null) {
|
|
|
|
currentAspectRatioFrameLayout = null;
|
|
|
|
currentTextureViewContainer = null;
|
|
|
|
currentAspectRatioFrameLayoutReady = false;
|
2019-03-03 21:40:48 +01:00
|
|
|
isDrawingWasReady = false;
|
2017-07-08 18:32:04 +02:00
|
|
|
currentTextureView = null;
|
2019-03-03 21:40:48 +01:00
|
|
|
goingToShowMessageObject = null;
|
|
|
|
if (transferPlayerToPhotoViewer) {
|
|
|
|
PhotoViewer.getInstance().injectVideoPlayer(videoPlayer);
|
|
|
|
goingToShowMessageObject = playingMessageObject;
|
|
|
|
NotificationCenter.getInstance(playingMessageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingGoingToStop, playingMessageObject, true);
|
|
|
|
} else {
|
|
|
|
long position = videoPlayer.getCurrentPosition();
|
|
|
|
if (playingMessageObject != null && playingMessageObject.isVideo() && position > 0 && position != C.TIME_UNSET) {
|
|
|
|
playingMessageObject.audioProgressMs = (int) position;
|
|
|
|
NotificationCenter.getInstance(playingMessageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingGoingToStop, playingMessageObject, false);
|
|
|
|
}
|
|
|
|
videoPlayer.releasePlayer(true);
|
|
|
|
videoPlayer = null;
|
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
try {
|
|
|
|
baseActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
2019-03-03 21:40:48 +01:00
|
|
|
if (playingMessageObject != null && !transferPlayerToPhotoViewer) {
|
|
|
|
AndroidUtilities.cancelRunOnUIThread(setLoadingRunnable);
|
|
|
|
FileLoader.getInstance(playingMessageObject.currentAccount).removeLoadingVideo(playingMessageObject.getDocument(), true, false);
|
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
}
|
|
|
|
stopProgressTimer();
|
|
|
|
lastProgress = 0;
|
|
|
|
isPaused = false;
|
2018-07-30 04:07:02 +02:00
|
|
|
if (!useFrontSpeaker && !SharedConfig.raiseToSpeak) {
|
|
|
|
ChatActivity chat = raiseChat;
|
|
|
|
stopRaiseToEarSensors(raiseChat, false);
|
|
|
|
raiseChat = chat;
|
|
|
|
}
|
2019-12-31 14:08:08 +01:00
|
|
|
if (proximityWakeLock != null && proximityWakeLock.isHeld() && !proximityTouched) {
|
|
|
|
proximityWakeLock.release();
|
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
if (playingMessageObject != null) {
|
2015-07-22 20:56:37 +02:00
|
|
|
if (downloadingCurrentMessage) {
|
2018-07-30 04:07:02 +02:00
|
|
|
FileLoader.getInstance(playingMessageObject.currentAccount).cancelLoadFile(playingMessageObject.getDocument());
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2014-02-28 23:28:25 +01:00
|
|
|
MessageObject lastFile = playingMessageObject;
|
2018-07-30 04:07:02 +02:00
|
|
|
if (notify) {
|
|
|
|
playingMessageObject.resetPlayingProgress();
|
|
|
|
NotificationCenter.getInstance(lastFile.currentAccount).postNotificationName(NotificationCenter.messagePlayingProgressDidChanged, playingMessageObject.getId(), 0);
|
|
|
|
}
|
2014-02-28 23:28:25 +01:00
|
|
|
playingMessageObject = null;
|
2015-07-22 20:56:37 +02:00
|
|
|
downloadingCurrentMessage = false;
|
2014-02-28 23:28:25 +01:00
|
|
|
if (notify) {
|
2018-07-30 04:07:02 +02:00
|
|
|
NotificationsController.audioManager.abandonAudioFocus(this);
|
2016-04-22 15:49:00 +02:00
|
|
|
hasAudioFocus = 0;
|
2018-07-30 04:07:02 +02:00
|
|
|
int index = -1;
|
2016-03-06 02:49:31 +01:00
|
|
|
if (voiceMessagesPlaylist != null) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (byVoiceEnd && (index = voiceMessagesPlaylist.indexOf(lastFile)) >= 0) {
|
|
|
|
voiceMessagesPlaylist.remove(index);
|
2016-03-06 02:49:31 +01:00
|
|
|
voiceMessagesPlaylistMap.remove(lastFile.getId());
|
|
|
|
if (voiceMessagesPlaylist.isEmpty()) {
|
|
|
|
voiceMessagesPlaylist = null;
|
|
|
|
voiceMessagesPlaylistMap = null;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
voiceMessagesPlaylist = null;
|
|
|
|
voiceMessagesPlaylistMap = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
boolean next = false;
|
2018-07-30 04:07:02 +02:00
|
|
|
if (voiceMessagesPlaylist != null && index < voiceMessagesPlaylist.size()) {
|
|
|
|
MessageObject nextVoiceMessage = voiceMessagesPlaylist.get(index);
|
2017-07-08 18:32:04 +02:00
|
|
|
playMessage(nextVoiceMessage);
|
|
|
|
if (!nextVoiceMessage.isRoundVideo() && pipRoundVideoView != null) {
|
|
|
|
pipRoundVideoView.close(true);
|
|
|
|
pipRoundVideoView = null;
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
} else {
|
2017-07-08 18:32:04 +02:00
|
|
|
if ((lastFile.isVoice() || lastFile.isRoundVideo()) && lastFile.getId() != 0) {
|
2016-03-06 02:49:31 +01:00
|
|
|
startRecordingIfFromSpeaker();
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
NotificationCenter.getInstance(lastFile.currentAccount).postNotificationName(NotificationCenter.messagePlayingDidReset, lastFile.getId(), stopService);
|
2017-07-08 18:32:04 +02:00
|
|
|
pipSwitchingState = 0;
|
|
|
|
if (pipRoundVideoView != null) {
|
|
|
|
pipRoundVideoView.close(true);
|
|
|
|
pipRoundVideoView = null;
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
if (stopService) {
|
|
|
|
Intent intent = new Intent(ApplicationLoader.applicationContext, MusicPlayerService.class);
|
|
|
|
ApplicationLoader.applicationContext.stopService(intent);
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-03 21:40:48 +01:00
|
|
|
public boolean isGoingToShowMessageObject(MessageObject messageObject) {
|
|
|
|
return goingToShowMessageObject == messageObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void resetGoingToShowMessageObject() {
|
|
|
|
goingToShowMessageObject = null;
|
|
|
|
}
|
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
private boolean isSamePlayingMessage(MessageObject messageObject) {
|
|
|
|
return playingMessageObject != null && playingMessageObject.getDialogId() == messageObject.getDialogId() && playingMessageObject.getId() == messageObject.getId() && ((playingMessageObject.eventId == 0) == (messageObject.eventId == 0));
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
|
2014-02-28 23:28:25 +01:00
|
|
|
public boolean seekToProgress(MessageObject messageObject, float progress) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (audioPlayer == null && videoPlayer == null || messageObject == null || playingMessageObject == null || !isSamePlayingMessage(messageObject)) {
|
2014-02-28 23:28:25 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
try {
|
2014-03-22 23:31:55 +01:00
|
|
|
if (audioPlayer != null) {
|
2018-07-30 04:07:02 +02:00
|
|
|
long duration = audioPlayer.getDuration();
|
|
|
|
if (duration == C.TIME_UNSET) {
|
|
|
|
seekToProgressPending = progress;
|
|
|
|
} else {
|
2019-12-31 14:08:08 +01:00
|
|
|
playingMessageObject.audioProgress = progress;
|
2018-07-30 04:07:02 +02:00
|
|
|
int seekTo = (int) (duration * progress);
|
|
|
|
audioPlayer.seekTo(seekTo);
|
|
|
|
lastProgress = seekTo;
|
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
} else if (videoPlayer != null) {
|
|
|
|
videoPlayer.seekTo((long) (videoPlayer.getDuration() * progress));
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2014-02-28 23:28:25 +01:00
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-02-28 23:28:25 +01:00
|
|
|
return false;
|
|
|
|
}
|
2018-08-27 10:33:11 +02:00
|
|
|
NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingDidSeek, playingMessageObject.getId(), progress);
|
2014-02-28 23:28:25 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-07-22 20:56:37 +02:00
|
|
|
public MessageObject getPlayingMessageObject() {
|
|
|
|
return playingMessageObject;
|
|
|
|
}
|
|
|
|
|
2016-05-25 23:49:47 +02:00
|
|
|
public int getPlayingMessageObjectNum() {
|
|
|
|
return currentPlaylistNum;
|
|
|
|
}
|
|
|
|
|
2015-07-22 20:56:37 +02:00
|
|
|
private void buildShuffledPlayList() {
|
2015-08-13 11:23:31 +02:00
|
|
|
if (playlist.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
ArrayList<MessageObject> all = new ArrayList<>(playlist);
|
|
|
|
shuffledPlaylist.clear();
|
|
|
|
|
|
|
|
MessageObject messageObject = playlist.get(currentPlaylistNum);
|
|
|
|
all.remove(currentPlaylistNum);
|
|
|
|
shuffledPlaylist.add(messageObject);
|
|
|
|
|
|
|
|
int count = all.size();
|
|
|
|
for (int a = 0; a < count; a++) {
|
|
|
|
int index = Utilities.random.nextInt(all.size());
|
|
|
|
shuffledPlaylist.add(all.get(index));
|
|
|
|
all.remove(index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
public void loadMoreMusic() {
|
|
|
|
if (loadingPlaylist || playingMessageObject == null || playingMessageObject.scheduled || (int) playingMessageObject.getDialogId() == 0 || playlistClassGuid == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2020-09-30 15:48:47 +02:00
|
|
|
if (playlistGlobalSearchParams != null) {
|
|
|
|
int finalPlaylistGuid = playlistClassGuid;
|
|
|
|
if (!playlistGlobalSearchParams.endReached && !playlist.isEmpty()) {
|
|
|
|
int currentAccount = playlist.get(0).currentAccount;
|
|
|
|
TLObject request;
|
|
|
|
if (playlistGlobalSearchParams.dialogId != 0) {
|
|
|
|
final TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
|
|
|
|
req.q = playlistGlobalSearchParams.query;
|
|
|
|
req.limit = 20;
|
|
|
|
req.filter = playlistGlobalSearchParams.filter == null ? new TLRPC.TL_inputMessagesFilterEmpty() : playlistGlobalSearchParams.filter.filter;
|
|
|
|
req.peer = AccountInstance.getInstance(currentAccount).getMessagesController().getInputPeer(playlistGlobalSearchParams.dialogId);
|
|
|
|
MessageObject lastMessage = playlist.get(playlist.size() - 1);
|
|
|
|
req.offset_id = lastMessage.getId();
|
|
|
|
if (playlistGlobalSearchParams.minDate > 0) {
|
|
|
|
req.min_date = (int) (playlistGlobalSearchParams.minDate / 1000);
|
|
|
|
}
|
|
|
|
if (playlistGlobalSearchParams.maxDate > 0) {
|
|
|
|
req.min_date = (int) (playlistGlobalSearchParams.maxDate / 1000);
|
|
|
|
}
|
|
|
|
request = req;
|
|
|
|
} else {
|
|
|
|
final TLRPC.TL_messages_searchGlobal req = new TLRPC.TL_messages_searchGlobal();
|
|
|
|
req.limit = 20;
|
|
|
|
req.q = playlistGlobalSearchParams.query;
|
|
|
|
req.filter = playlistGlobalSearchParams.filter.filter;
|
|
|
|
MessageObject lastMessage = playlist.get(playlist.size() - 1);
|
|
|
|
req.offset_id = lastMessage.getId();
|
|
|
|
req.offset_rate = playlistGlobalSearchParams.nextSearchRate;
|
|
|
|
req.flags |= 1;
|
|
|
|
req.folder_id = playlistGlobalSearchParams.folderId;
|
|
|
|
int id;
|
|
|
|
if (lastMessage.messageOwner.peer_id.channel_id != 0) {
|
|
|
|
id = -lastMessage.messageOwner.peer_id.channel_id;
|
|
|
|
} else if (lastMessage.messageOwner.peer_id.chat_id != 0) {
|
|
|
|
id = -lastMessage.messageOwner.peer_id.chat_id;
|
|
|
|
} else {
|
|
|
|
id = lastMessage.messageOwner.peer_id.user_id;
|
|
|
|
}
|
|
|
|
req.offset_peer = MessagesController.getInstance(currentAccount).getInputPeer(id);
|
|
|
|
if (playlistGlobalSearchParams.minDate > 0) {
|
|
|
|
req.min_date = (int) (playlistGlobalSearchParams.minDate / 1000);
|
|
|
|
}
|
|
|
|
if (playlistGlobalSearchParams.maxDate > 0) {
|
|
|
|
req.min_date = (int) (playlistGlobalSearchParams.maxDate / 1000);
|
|
|
|
}
|
|
|
|
request = req;
|
|
|
|
}
|
|
|
|
loadingPlaylist = true;
|
|
|
|
ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> {
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
2020-09-30 18:55:35 +02:00
|
|
|
if (playlistClassGuid != finalPlaylistGuid || playlistGlobalSearchParams == null || playingMessageObject == null) {
|
2020-09-30 15:48:47 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (error != null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
loadingPlaylist = false;
|
|
|
|
|
|
|
|
TLRPC.messages_Messages res = (TLRPC.messages_Messages) response;
|
|
|
|
playlistGlobalSearchParams.nextSearchRate = res.next_rate;
|
|
|
|
MessagesStorage.getInstance(currentAccount).putUsersAndChats(res.users, res.chats, true, true);
|
|
|
|
MessagesController.getInstance(currentAccount).putUsers(res.users, false);
|
|
|
|
MessagesController.getInstance(currentAccount).putChats(res.chats, false);
|
|
|
|
int n = res.messages.size();
|
|
|
|
int addedCount = 0;
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
MessageObject messageObject = new MessageObject(currentAccount, res.messages.get(i), false, true);
|
|
|
|
if (playlistMap.containsKey(messageObject.getId())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
playlist.add(0, messageObject);
|
|
|
|
playlistMap.put(messageObject.getId(), messageObject);
|
|
|
|
addedCount++;
|
|
|
|
}
|
|
|
|
loadingPlaylist = false;
|
|
|
|
playlistGlobalSearchParams.endReached = playlist.size() == playlistGlobalSearchParams.totalCount;
|
|
|
|
if (SharedConfig.shuffleMusic) {
|
|
|
|
buildShuffledPlayList();
|
|
|
|
}
|
|
|
|
if (addedCount != 0) {
|
|
|
|
NotificationCenter.getInstance(playingMessageObject.currentAccount).postNotificationName(NotificationCenter.moreMusicDidLoad, addedCount);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2020-07-26 10:03:38 +02:00
|
|
|
if (!playlistEndReached[0]) {
|
|
|
|
loadingPlaylist = true;
|
|
|
|
AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playingMessageObject.getDialogId(), 50, playlistMaxId[0], MediaDataController.MEDIA_MUSIC, 1, playlistClassGuid);
|
|
|
|
} else if (playlistMergeDialogId != 0 && !playlistEndReached[1]) {
|
|
|
|
loadingPlaylist = true;
|
|
|
|
AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playlistMergeDialogId, 50, playlistMaxId[0], MediaDataController.MEDIA_MUSIC, 1, playlistClassGuid);
|
|
|
|
}
|
2016-05-25 23:49:47 +02:00
|
|
|
}
|
|
|
|
|
2020-09-30 15:48:47 +02:00
|
|
|
public boolean setPlaylist(ArrayList<MessageObject> messageObjects, MessageObject current, long mergeDialogId, PlaylistGlobalSearchParams globalSearchParams) {
|
|
|
|
return setPlaylist(messageObjects, current, mergeDialogId, true, globalSearchParams);
|
|
|
|
}
|
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
public boolean setPlaylist(ArrayList<MessageObject> messageObjects, MessageObject current, long mergeDialogId) {
|
2020-09-30 15:48:47 +02:00
|
|
|
return setPlaylist(messageObjects, current, mergeDialogId, true, null);
|
2020-07-26 10:03:38 +02:00
|
|
|
}
|
|
|
|
|
2020-09-30 15:48:47 +02:00
|
|
|
public boolean setPlaylist(ArrayList<MessageObject> messageObjects, MessageObject current, long mergeDialogId, boolean loadMusic, PlaylistGlobalSearchParams params) {
|
2015-07-22 20:56:37 +02:00
|
|
|
if (playingMessageObject == current) {
|
2017-07-08 18:32:04 +02:00
|
|
|
return playMessage(current);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2016-05-25 23:49:47 +02:00
|
|
|
forceLoopCurrentPlaylist = !loadMusic;
|
2020-07-26 10:03:38 +02:00
|
|
|
playlistMergeDialogId = mergeDialogId;
|
2015-10-29 18:10:07 +01:00
|
|
|
playMusicAgain = !playlist.isEmpty();
|
2020-07-26 10:03:38 +02:00
|
|
|
clearPlaylist();
|
2020-09-30 15:48:47 +02:00
|
|
|
playlistGlobalSearchParams = params;
|
2015-07-22 20:56:37 +02:00
|
|
|
for (int a = messageObjects.size() - 1; a >= 0; a--) {
|
|
|
|
MessageObject messageObject = messageObjects.get(a);
|
|
|
|
if (messageObject.isMusic()) {
|
|
|
|
playlist.add(messageObject);
|
2020-07-26 10:03:38 +02:00
|
|
|
playlistMap.put(messageObject.getId(), messageObject);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
currentPlaylistNum = playlist.indexOf(current);
|
|
|
|
if (currentPlaylistNum == -1) {
|
2020-07-26 10:03:38 +02:00
|
|
|
clearPlaylist();
|
2016-06-24 12:27:15 +02:00
|
|
|
currentPlaylistNum = playlist.size();
|
2016-04-22 15:49:00 +02:00
|
|
|
playlist.add(current);
|
2020-07-26 10:03:38 +02:00
|
|
|
playlistMap.put(current.getId(), current);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2019-09-10 12:56:11 +02:00
|
|
|
if (current.isMusic() && !current.scheduled) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (SharedConfig.shuffleMusic) {
|
2016-03-06 02:49:31 +01:00
|
|
|
buildShuffledPlayList();
|
|
|
|
currentPlaylistNum = 0;
|
|
|
|
}
|
2016-05-25 23:49:47 +02:00
|
|
|
if (loadMusic) {
|
2020-09-30 15:48:47 +02:00
|
|
|
if (playlistGlobalSearchParams == null) {
|
|
|
|
MediaDataController.getInstance(current.currentAccount).loadMusic(current.getDialogId(), playlist.get(0).getIdWithChannel(), playlist.get(playlist.size() - 1).getIdWithChannel());
|
|
|
|
} else {
|
|
|
|
playlistClassGuid = ConnectionsManager.generateClassGuid();
|
|
|
|
}
|
2016-05-25 23:49:47 +02:00
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
return playMessage(current);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void playNextMessage() {
|
2017-12-08 18:35:59 +01:00
|
|
|
playNextMessageWithoutOrder(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean findMessageInPlaylistAndPlay(MessageObject messageObject) {
|
|
|
|
int index = playlist.indexOf(messageObject);
|
|
|
|
if (index == -1) {
|
|
|
|
return playMessage(messageObject);
|
|
|
|
} else {
|
|
|
|
playMessageAtIndex(index);
|
|
|
|
}
|
|
|
|
return true;
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
|
|
|
|
2016-05-25 23:49:47 +02:00
|
|
|
public void playMessageAtIndex(int index) {
|
|
|
|
if (currentPlaylistNum < 0 || currentPlaylistNum >= playlist.size()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
currentPlaylistNum = index;
|
|
|
|
playMusicAgain = true;
|
2020-10-30 11:26:29 +01:00
|
|
|
MessageObject messageObject = playlist.get(currentPlaylistNum);
|
|
|
|
if (playingMessageObject != null && !isSamePlayingMessage(messageObject)) {
|
2018-07-30 04:07:02 +02:00
|
|
|
playingMessageObject.resetPlayingProgress();
|
|
|
|
}
|
2020-10-30 11:26:29 +01:00
|
|
|
playMessage(messageObject);
|
2016-05-25 23:49:47 +02:00
|
|
|
}
|
|
|
|
|
2017-12-08 18:35:59 +01:00
|
|
|
private void playNextMessageWithoutOrder(boolean byStop) {
|
2018-07-30 04:07:02 +02:00
|
|
|
ArrayList<MessageObject> currentPlayList = SharedConfig.shuffleMusic ? shuffledPlaylist : playlist;
|
2015-07-22 20:56:37 +02:00
|
|
|
|
2019-08-22 01:53:26 +02:00
|
|
|
if (byStop && (SharedConfig.repeatMode == 2 || SharedConfig.repeatMode == 1 && currentPlayList.size() == 1) && !forceLoopCurrentPlaylist) {
|
2015-10-29 18:10:07 +01:00
|
|
|
cleanupPlayer(false, false);
|
2018-07-30 04:07:02 +02:00
|
|
|
MessageObject messageObject = currentPlayList.get(currentPlaylistNum);
|
|
|
|
messageObject.audioProgress = 0;
|
|
|
|
messageObject.audioProgressSec = 0;
|
|
|
|
playMessage(messageObject);
|
2015-07-22 20:56:37 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-12-08 18:35:59 +01:00
|
|
|
|
|
|
|
boolean last = false;
|
2018-07-30 04:07:02 +02:00
|
|
|
if (SharedConfig.playOrderReversed) {
|
2017-12-08 18:35:59 +01:00
|
|
|
currentPlaylistNum++;
|
|
|
|
if (currentPlaylistNum >= currentPlayList.size()) {
|
|
|
|
currentPlaylistNum = 0;
|
|
|
|
last = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
currentPlaylistNum--;
|
|
|
|
if (currentPlaylistNum < 0) {
|
|
|
|
currentPlaylistNum = currentPlayList.size() - 1;
|
|
|
|
last = true;
|
|
|
|
}
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
if (last && byStop && SharedConfig.repeatMode == 0 && !forceLoopCurrentPlaylist) {
|
|
|
|
if (audioPlayer != null || videoPlayer != null) {
|
2017-12-08 18:35:59 +01:00
|
|
|
if (audioPlayer != null) {
|
|
|
|
try {
|
2019-03-03 21:40:48 +01:00
|
|
|
audioPlayer.releasePlayer(true);
|
2017-12-08 18:35:59 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
audioPlayer = null;
|
2020-06-04 18:47:15 +02:00
|
|
|
Theme.unrefAudioVisualizeDrawable(playingMessageObject);
|
2017-12-08 18:35:59 +01:00
|
|
|
} else if (videoPlayer != null) {
|
|
|
|
currentAspectRatioFrameLayout = null;
|
|
|
|
currentTextureViewContainer = null;
|
|
|
|
currentAspectRatioFrameLayoutReady = false;
|
|
|
|
currentTextureView = null;
|
2019-03-03 21:40:48 +01:00
|
|
|
videoPlayer.releasePlayer(true);
|
2017-12-08 18:35:59 +01:00
|
|
|
videoPlayer = null;
|
|
|
|
try {
|
|
|
|
baseActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2019-03-03 21:40:48 +01:00
|
|
|
AndroidUtilities.cancelRunOnUIThread(setLoadingRunnable);
|
|
|
|
FileLoader.getInstance(playingMessageObject.currentAccount).removeLoadingVideo(playingMessageObject.getDocument(), true, false);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2017-12-08 18:35:59 +01:00
|
|
|
stopProgressTimer();
|
|
|
|
lastProgress = 0;
|
|
|
|
isPaused = true;
|
|
|
|
playingMessageObject.audioProgress = 0.0f;
|
|
|
|
playingMessageObject.audioProgressSec = 0;
|
2018-07-30 04:07:02 +02:00
|
|
|
NotificationCenter.getInstance(playingMessageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingProgressDidChanged, playingMessageObject.getId(), 0);
|
|
|
|
NotificationCenter.getInstance(playingMessageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingPlayStateChanged, playingMessageObject.getId());
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2017-12-08 18:35:59 +01:00
|
|
|
return;
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
|
|
|
if (currentPlaylistNum < 0 || currentPlaylistNum >= currentPlayList.size()) {
|
|
|
|
return;
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
if (playingMessageObject != null) {
|
|
|
|
playingMessageObject.resetPlayingProgress();
|
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
playMusicAgain = true;
|
2017-07-08 18:32:04 +02:00
|
|
|
playMessage(currentPlayList.get(currentPlaylistNum));
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void playPreviousMessage() {
|
2018-07-30 04:07:02 +02:00
|
|
|
ArrayList<MessageObject> currentPlayList = SharedConfig.shuffleMusic ? shuffledPlaylist : playlist;
|
|
|
|
if (currentPlayList.isEmpty() || currentPlaylistNum < 0 || currentPlaylistNum >= currentPlayList.size()) {
|
2017-03-31 01:58:05 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
MessageObject currentSong = currentPlayList.get(currentPlaylistNum);
|
|
|
|
if (currentSong.audioProgressSec > 10) {
|
2018-07-30 04:07:02 +02:00
|
|
|
seekToProgress(currentSong, 0);
|
2017-03-31 01:58:05 +02:00
|
|
|
return;
|
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
if (SharedConfig.playOrderReversed) {
|
2017-12-08 18:35:59 +01:00
|
|
|
currentPlaylistNum--;
|
|
|
|
if (currentPlaylistNum < 0) {
|
|
|
|
currentPlaylistNum = currentPlayList.size() - 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
currentPlaylistNum++;
|
|
|
|
if (currentPlaylistNum >= currentPlayList.size()) {
|
|
|
|
currentPlaylistNum = 0;
|
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
|
|
|
if (currentPlaylistNum < 0 || currentPlaylistNum >= currentPlayList.size()) {
|
|
|
|
return;
|
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
playMusicAgain = true;
|
2017-07-08 18:32:04 +02:00
|
|
|
playMessage(currentPlayList.get(currentPlaylistNum));
|
|
|
|
}
|
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
protected void checkIsNextMediaFileDownloaded() {
|
|
|
|
if (playingMessageObject == null || !playingMessageObject.isMusic()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
checkIsNextMusicFileDownloaded(playingMessageObject.currentAccount);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void checkIsNextVoiceFileDownloaded(int currentAccount) {
|
2017-07-08 18:32:04 +02:00
|
|
|
if (voiceMessagesPlaylist == null || voiceMessagesPlaylist.size() < 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
MessageObject nextAudio = voiceMessagesPlaylist.get(1);
|
|
|
|
File file = null;
|
|
|
|
if (nextAudio.messageOwner.attachPath != null && nextAudio.messageOwner.attachPath.length() > 0) {
|
|
|
|
file = new File(nextAudio.messageOwner.attachPath);
|
|
|
|
if (!file.exists()) {
|
|
|
|
file = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
final File cacheFile = file != null ? file : FileLoader.getPathToMessage(nextAudio.messageOwner);
|
|
|
|
boolean exist = cacheFile != null && cacheFile.exists();
|
|
|
|
if (cacheFile != null && cacheFile != file && !cacheFile.exists()) {
|
2019-01-23 18:03:33 +01:00
|
|
|
FileLoader.getInstance(currentAccount).loadFile(nextAudio.getDocument(), nextAudio, 0, 0);
|
2017-07-08 18:32:04 +02:00
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
private void checkIsNextMusicFileDownloaded(int currentAccount) {
|
2019-03-03 21:40:48 +01:00
|
|
|
if (!DownloadController.getInstance(currentAccount).canDownloadNextTrack()) {
|
2016-01-11 18:19:48 +01:00
|
|
|
return;
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
ArrayList<MessageObject> currentPlayList = SharedConfig.shuffleMusic ? shuffledPlaylist : playlist;
|
2015-07-22 20:56:37 +02:00
|
|
|
if (currentPlayList == null || currentPlayList.size() < 2) {
|
|
|
|
return;
|
|
|
|
}
|
2017-12-08 18:35:59 +01:00
|
|
|
int nextIndex;
|
2018-07-30 04:07:02 +02:00
|
|
|
if (SharedConfig.playOrderReversed) {
|
2017-12-08 18:35:59 +01:00
|
|
|
nextIndex = currentPlaylistNum + 1;
|
|
|
|
if (nextIndex >= currentPlayList.size()) {
|
|
|
|
nextIndex = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
nextIndex = currentPlaylistNum - 1;
|
|
|
|
if (nextIndex < 0) {
|
|
|
|
nextIndex = currentPlayList.size() - 1;
|
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
if (nextIndex < 0 || nextIndex >= currentPlayList.size()) {
|
|
|
|
return;
|
|
|
|
}
|
2017-12-08 18:35:59 +01:00
|
|
|
|
2015-07-22 20:56:37 +02:00
|
|
|
MessageObject nextAudio = currentPlayList.get(nextIndex);
|
|
|
|
File file = null;
|
2017-12-08 18:35:59 +01:00
|
|
|
if (!TextUtils.isEmpty(nextAudio.messageOwner.attachPath)) {
|
2015-07-22 20:56:37 +02:00
|
|
|
file = new File(nextAudio.messageOwner.attachPath);
|
|
|
|
if (!file.exists()) {
|
|
|
|
file = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
final File cacheFile = file != null ? file : FileLoader.getPathToMessage(nextAudio.messageOwner);
|
|
|
|
boolean exist = cacheFile != null && cacheFile.exists();
|
|
|
|
if (cacheFile != null && cacheFile != file && !cacheFile.exists() && nextAudio.isMusic()) {
|
2019-01-23 18:03:33 +01:00
|
|
|
FileLoader.getInstance(currentAccount).loadFile(nextAudio.getDocument(), nextAudio, 0, 0);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-06 02:49:31 +01:00
|
|
|
public void setVoiceMessagesPlaylist(ArrayList<MessageObject> playlist, boolean unread) {
|
|
|
|
voiceMessagesPlaylist = playlist;
|
|
|
|
if (voiceMessagesPlaylist != null) {
|
|
|
|
voiceMessagesPlaylistUnread = unread;
|
2018-07-30 04:07:02 +02:00
|
|
|
voiceMessagesPlaylistMap = new SparseArray<>();
|
2016-03-06 02:49:31 +01:00
|
|
|
for (int a = 0; a < voiceMessagesPlaylist.size(); a++) {
|
|
|
|
MessageObject messageObject = voiceMessagesPlaylist.get(a);
|
|
|
|
voiceMessagesPlaylistMap.put(messageObject.getId(), messageObject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-22 15:49:00 +02:00
|
|
|
private void checkAudioFocus(MessageObject messageObject) {
|
|
|
|
int neededAudioFocus;
|
2017-07-08 18:32:04 +02:00
|
|
|
if (messageObject.isVoice() || messageObject.isRoundVideo()) {
|
2016-04-22 15:49:00 +02:00
|
|
|
if (useFrontSpeaker) {
|
|
|
|
neededAudioFocus = 3;
|
|
|
|
} else {
|
|
|
|
neededAudioFocus = 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
neededAudioFocus = 1;
|
|
|
|
}
|
|
|
|
if (hasAudioFocus != neededAudioFocus) {
|
|
|
|
hasAudioFocus = neededAudioFocus;
|
2016-05-25 23:49:47 +02:00
|
|
|
int result;
|
2016-04-22 15:49:00 +02:00
|
|
|
if (neededAudioFocus == 3) {
|
2018-07-30 04:07:02 +02:00
|
|
|
result = NotificationsController.audioManager.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN);
|
2016-04-22 15:49:00 +02:00
|
|
|
} else {
|
2018-07-30 04:07:02 +02:00
|
|
|
result = NotificationsController.audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, neededAudioFocus == 2 ? AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK : AudioManager.AUDIOFOCUS_GAIN);
|
2016-05-25 23:49:47 +02:00
|
|
|
}
|
|
|
|
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
|
|
|
audioFocus = AUDIO_FOCUSED;
|
2016-04-22 15:49:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-03 21:40:48 +01:00
|
|
|
public void setCurrentVideoVisible(boolean visible) {
|
2017-07-08 18:32:04 +02:00
|
|
|
if (currentAspectRatioFrameLayout == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (visible) {
|
|
|
|
if (pipRoundVideoView != null) {
|
|
|
|
pipSwitchingState = 2;
|
|
|
|
pipRoundVideoView.close(true);
|
|
|
|
pipRoundVideoView = null;
|
|
|
|
} else if (currentAspectRatioFrameLayout != null) {
|
|
|
|
if (currentAspectRatioFrameLayout.getParent() == null) {
|
|
|
|
currentTextureViewContainer.addView(currentAspectRatioFrameLayout);
|
|
|
|
}
|
|
|
|
videoPlayer.setTextureView(currentTextureView);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (currentAspectRatioFrameLayout.getParent() != null) {
|
|
|
|
pipSwitchingState = 1;
|
|
|
|
currentTextureViewContainer.removeView(currentAspectRatioFrameLayout);
|
|
|
|
} else {
|
|
|
|
if (pipRoundVideoView == null) {
|
|
|
|
try {
|
|
|
|
pipRoundVideoView = new PipRoundVideoView();
|
2019-01-23 18:03:33 +01:00
|
|
|
pipRoundVideoView.show(baseActivity, () -> cleanupPlayer(true, true));
|
2017-07-08 18:32:04 +02:00
|
|
|
} catch (Exception e) {
|
|
|
|
pipRoundVideoView = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pipRoundVideoView != null) {
|
|
|
|
videoPlayer.setTextureView(pipRoundVideoView.getTextureView());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTextureView(TextureView textureView, AspectRatioFrameLayout aspectRatioFrameLayout, FrameLayout container, boolean set) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (textureView == null) {
|
|
|
|
return;
|
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
if (!set && currentTextureView == textureView) {
|
|
|
|
pipSwitchingState = 1;
|
|
|
|
currentTextureView = null;
|
|
|
|
currentAspectRatioFrameLayout = null;
|
|
|
|
currentTextureViewContainer = null;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (videoPlayer == null || textureView == currentTextureView) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
isDrawingWasReady = aspectRatioFrameLayout != null && aspectRatioFrameLayout.isDrawingReady();
|
|
|
|
currentTextureView = textureView;
|
|
|
|
if (pipRoundVideoView != null) {
|
|
|
|
videoPlayer.setTextureView(pipRoundVideoView.getTextureView());
|
|
|
|
} else {
|
|
|
|
videoPlayer.setTextureView(currentTextureView);
|
|
|
|
}
|
|
|
|
currentAspectRatioFrameLayout = aspectRatioFrameLayout;
|
|
|
|
currentTextureViewContainer = container;
|
|
|
|
if (currentAspectRatioFrameLayoutReady && currentAspectRatioFrameLayout != null) {
|
|
|
|
if (currentAspectRatioFrameLayout != null) {
|
|
|
|
currentAspectRatioFrameLayout.setAspectRatio(currentAspectRatioFrameLayoutRatio, currentAspectRatioFrameLayoutRotation);
|
|
|
|
}
|
2019-03-03 21:40:48 +01:00
|
|
|
//if (currentTextureViewContainer.getVisibility() != View.VISIBLE) {
|
|
|
|
// currentTextureViewContainer.setVisibility(View.VISIBLE);
|
|
|
|
//}
|
2017-07-08 18:32:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setBaseActivity(Activity activity, boolean set) {
|
|
|
|
if (set) {
|
|
|
|
baseActivity = activity;
|
|
|
|
} else if (baseActivity == activity) {
|
|
|
|
baseActivity = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
public void setFeedbackView(View view, boolean set) {
|
|
|
|
if (set) {
|
|
|
|
feedbackView = view;
|
|
|
|
} else if (feedbackView == view) {
|
|
|
|
feedbackView = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
public void setPlaybackSpeed(boolean music, float speed) {
|
|
|
|
if (music) {
|
|
|
|
currentMusicPlaybackSpeed = speed;
|
|
|
|
} else {
|
|
|
|
currentPlaybackSpeed = speed;
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
if (audioPlayer != null) {
|
2019-12-31 14:08:08 +01:00
|
|
|
audioPlayer.setPlaybackSpeed(speed);
|
2018-07-30 04:07:02 +02:00
|
|
|
} else if (videoPlayer != null) {
|
2019-12-31 14:08:08 +01:00
|
|
|
videoPlayer.setPlaybackSpeed(speed);
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
2019-12-31 14:08:08 +01:00
|
|
|
MessagesController.getGlobalMainSettings().edit().putFloat(music ? "musicPlaybackSpeed" : "playbackSpeed", speed).commit();
|
|
|
|
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.messagePlayingSpeedChanged);
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
public float getPlaybackSpeed(boolean music) {
|
|
|
|
return music ? currentMusicPlaybackSpeed : currentPlaybackSpeed;
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
|
|
|
|
2019-08-22 01:53:26 +02:00
|
|
|
private void updateVideoState(MessageObject messageObject, int[] playCount, boolean destroyAtEnd, boolean playWhenReady, int playbackState) {
|
2019-05-14 14:08:05 +02:00
|
|
|
if (videoPlayer == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (playbackState != ExoPlayer.STATE_ENDED && playbackState != ExoPlayer.STATE_IDLE) {
|
|
|
|
try {
|
|
|
|
baseActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
baseActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (playbackState == ExoPlayer.STATE_READY) {
|
|
|
|
playerWasReady = true;
|
|
|
|
if (playingMessageObject != null && (playingMessageObject.isVideo() || playingMessageObject.isRoundVideo())) {
|
|
|
|
AndroidUtilities.cancelRunOnUIThread(setLoadingRunnable);
|
|
|
|
FileLoader.getInstance(messageObject.currentAccount).removeLoadingVideo(playingMessageObject.getDocument(), true, false);
|
|
|
|
}
|
|
|
|
currentAspectRatioFrameLayoutReady = true;
|
|
|
|
} else if (playbackState == ExoPlayer.STATE_BUFFERING) {
|
|
|
|
if (playWhenReady && playingMessageObject != null && (playingMessageObject.isVideo() || playingMessageObject.isRoundVideo())) {
|
|
|
|
if (playerWasReady) {
|
|
|
|
setLoadingRunnable.run();
|
|
|
|
} else {
|
|
|
|
AndroidUtilities.runOnUIThread(setLoadingRunnable, 1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (videoPlayer.isPlaying() && playbackState == ExoPlayer.STATE_ENDED) {
|
|
|
|
if (playingMessageObject.isVideo() && !destroyAtEnd && (playCount == null || playCount[0] < 4)) {
|
|
|
|
videoPlayer.seekTo(0);
|
|
|
|
if (playCount != null) {
|
|
|
|
playCount[0]++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cleanupPlayer(true, true, true, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void injectVideoPlayer(VideoPlayer player, MessageObject messageObject) {
|
|
|
|
if (player == null || messageObject == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
FileLoader.getInstance(messageObject.currentAccount).setLoadingVideoForPlayer(messageObject.getDocument(), true);
|
|
|
|
playerWasReady = false;
|
|
|
|
boolean destroyAtEnd = true;
|
|
|
|
int[] playCount = null;
|
2020-07-26 10:03:38 +02:00
|
|
|
clearPlaylist();
|
2019-05-14 14:08:05 +02:00
|
|
|
videoPlayer = player;
|
|
|
|
playingMessageObject = messageObject;
|
2019-12-31 14:08:08 +01:00
|
|
|
int tag = ++playerNum;
|
2019-05-14 14:08:05 +02:00
|
|
|
videoPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() {
|
|
|
|
@Override
|
|
|
|
public void onStateChanged(boolean playWhenReady, int playbackState) {
|
2019-12-31 14:08:08 +01:00
|
|
|
if (tag != playerNum) {
|
|
|
|
return;
|
|
|
|
}
|
2019-05-14 14:08:05 +02:00
|
|
|
updateVideoState(messageObject, playCount, destroyAtEnd, playWhenReady, playbackState);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-06-04 18:47:15 +02:00
|
|
|
public void onError(VideoPlayer player, Exception e) {
|
2019-05-14 14:08:05 +02:00
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
|
|
|
|
currentAspectRatioFrameLayoutRotation = unappliedRotationDegrees;
|
|
|
|
if (unappliedRotationDegrees == 90 || unappliedRotationDegrees == 270) {
|
|
|
|
int temp = width;
|
|
|
|
width = height;
|
|
|
|
height = temp;
|
|
|
|
}
|
|
|
|
currentAspectRatioFrameLayoutRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height;
|
|
|
|
|
|
|
|
if (currentAspectRatioFrameLayout != null) {
|
|
|
|
currentAspectRatioFrameLayout.setAspectRatio(currentAspectRatioFrameLayoutRatio, currentAspectRatioFrameLayoutRotation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onRenderedFirstFrame() {
|
|
|
|
if (currentAspectRatioFrameLayout != null && !currentAspectRatioFrameLayout.isDrawingReady()) {
|
|
|
|
isDrawingWasReady = true;
|
|
|
|
currentAspectRatioFrameLayout.setDrawingReady(true);
|
|
|
|
currentTextureViewContainer.setTag(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onSurfaceDestroyed(SurfaceTexture surfaceTexture) {
|
|
|
|
if (videoPlayer == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (pipSwitchingState == 2) {
|
|
|
|
if (currentAspectRatioFrameLayout != null) {
|
|
|
|
if (isDrawingWasReady) {
|
|
|
|
currentAspectRatioFrameLayout.setDrawingReady(true);
|
|
|
|
}
|
|
|
|
if (currentAspectRatioFrameLayout.getParent() == null) {
|
|
|
|
currentTextureViewContainer.addView(currentAspectRatioFrameLayout);
|
|
|
|
}
|
|
|
|
if (currentTextureView.getSurfaceTexture() != surfaceTexture) {
|
|
|
|
currentTextureView.setSurfaceTexture(surfaceTexture);
|
|
|
|
}
|
|
|
|
videoPlayer.setTextureView(currentTextureView);
|
|
|
|
}
|
|
|
|
pipSwitchingState = 0;
|
|
|
|
return true;
|
|
|
|
} else if (pipSwitchingState == 1) {
|
|
|
|
if (baseActivity != null) {
|
|
|
|
if (pipRoundVideoView == null) {
|
|
|
|
try {
|
|
|
|
pipRoundVideoView = new PipRoundVideoView();
|
|
|
|
pipRoundVideoView.show(baseActivity, () -> cleanupPlayer(true, true));
|
|
|
|
} catch (Exception e) {
|
|
|
|
pipRoundVideoView = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pipRoundVideoView != null) {
|
|
|
|
if (pipRoundVideoView.getTextureView().getSurfaceTexture() != surfaceTexture) {
|
|
|
|
pipRoundVideoView.getTextureView().setSurfaceTexture(surfaceTexture);
|
|
|
|
}
|
|
|
|
videoPlayer.setTextureView(pipRoundVideoView.getTextureView());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pipSwitchingState = 0;
|
|
|
|
return true;
|
|
|
|
} else if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isInjectingVideoPlayer()) {
|
|
|
|
PhotoViewer.getInstance().injectVideoPlayerSurface(surfaceTexture);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
currentAspectRatioFrameLayoutReady = false;
|
|
|
|
if (currentTextureView != null) {
|
|
|
|
videoPlayer.setTextureView(currentTextureView);
|
|
|
|
}
|
|
|
|
|
|
|
|
checkAudioFocus(messageObject);
|
|
|
|
setPlayerVolume();
|
|
|
|
|
|
|
|
isPaused = false;
|
|
|
|
lastProgress = 0;
|
|
|
|
playingMessageObject = messageObject;
|
|
|
|
if (!SharedConfig.raiseToSpeak) {
|
|
|
|
startRaiseToEarSensors(raiseChat);
|
|
|
|
}
|
|
|
|
startProgressTimer(playingMessageObject);
|
|
|
|
NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingDidStart, messageObject);
|
|
|
|
|
|
|
|
/*try {
|
|
|
|
if (playingMessageObject.audioProgress != 0) {
|
|
|
|
long duration = videoPlayer.getDuration();
|
|
|
|
if (duration == C.TIME_UNSET) {
|
|
|
|
duration = (long) playingMessageObject.getDuration() * 1000;
|
|
|
|
}
|
|
|
|
int seekTo = (int) (duration * playingMessageObject.audioProgress);
|
|
|
|
if (playingMessageObject.audioProgressMs != 0) {
|
|
|
|
seekTo = playingMessageObject.audioProgressMs;
|
|
|
|
playingMessageObject.audioProgressMs = 0;
|
|
|
|
}
|
|
|
|
videoPlayer.seekTo(seekTo);
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
|
|
|
playingMessageObject.audioProgress = 0;
|
|
|
|
playingMessageObject.audioProgressSec = 0;
|
|
|
|
NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingProgressDidChanged, playingMessageObject.getId(), 0);
|
|
|
|
FileLog.e(e2);
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
|
2020-10-30 11:26:29 +01:00
|
|
|
public void playEmojiSound(AccountInstance accountInstance, String emoji, MessagesController.EmojiSound sound, boolean loadOnly) {
|
|
|
|
if (sound == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Utilities.stageQueue.postRunnable(() -> {
|
|
|
|
TLRPC.Document document = new TLRPC.TL_document();
|
|
|
|
document.access_hash = sound.accessHash;
|
|
|
|
document.id = sound.id;
|
|
|
|
document.mime_type = "sound/ogg";
|
|
|
|
document.file_reference = sound.fileReference;
|
|
|
|
document.dc_id = accountInstance.getConnectionsManager().getCurrentDatacenterId();
|
|
|
|
File file = FileLoader.getPathToAttach(document, true);
|
|
|
|
if (file.exists()) {
|
|
|
|
if (loadOnly) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
try {
|
|
|
|
int tag = ++emojiSoundPlayerNum;
|
|
|
|
if (emojiSoundPlayer != null) {
|
|
|
|
emojiSoundPlayer.releasePlayer(true);
|
|
|
|
}
|
|
|
|
emojiSoundPlayer = new VideoPlayer(false);
|
|
|
|
emojiSoundPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() {
|
|
|
|
@Override
|
|
|
|
public void onStateChanged(boolean playWhenReady, int playbackState) {
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
if (tag != emojiSoundPlayerNum) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (playbackState == ExoPlayer.STATE_ENDED) {
|
|
|
|
if (emojiSoundPlayer != null) {
|
|
|
|
try {
|
|
|
|
emojiSoundPlayer.releasePlayer(true);
|
|
|
|
emojiSoundPlayer = null;
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onError(VideoPlayer player, Exception e) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onRenderedFirstFrame() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onSurfaceDestroyed(SurfaceTexture surfaceTexture) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
emojiSoundPlayer.preparePlayer(Uri.fromFile(file), "other");
|
|
|
|
emojiSoundPlayer.setStreamType(AudioManager.STREAM_MUSIC);
|
|
|
|
emojiSoundPlayer.play();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
if (emojiSoundPlayer != null) {
|
|
|
|
emojiSoundPlayer.releasePlayer(true);
|
|
|
|
emojiSoundPlayer = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
AndroidUtilities.runOnUIThread(() -> accountInstance.getFileLoader().loadFile(document, null, 1, 1));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-07-08 18:32:04 +02:00
|
|
|
public boolean playMessage(final MessageObject messageObject) {
|
2014-02-28 23:28:25 +01:00
|
|
|
if (messageObject == null) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
if ((audioPlayer != null || videoPlayer != null) && isSamePlayingMessage(messageObject)) {
|
2014-02-28 23:28:25 +01:00
|
|
|
if (isPaused) {
|
|
|
|
resumeAudio(messageObject);
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
if (!SharedConfig.raiseToSpeak) {
|
2016-03-06 02:49:31 +01:00
|
|
|
startRaiseToEarSensors(raiseChat);
|
|
|
|
}
|
2014-02-28 23:28:25 +01:00
|
|
|
return true;
|
|
|
|
}
|
2017-12-08 18:35:59 +01:00
|
|
|
if (!messageObject.isOut() && messageObject.isContentUnread()) {
|
2018-07-30 04:07:02 +02:00
|
|
|
MessagesController.getInstance(messageObject.currentAccount).markMessageContentAsRead(messageObject);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
boolean notify = !playMusicAgain;
|
|
|
|
if (playingMessageObject != null) {
|
|
|
|
notify = false;
|
2018-07-30 04:07:02 +02:00
|
|
|
if (!playMusicAgain) {
|
|
|
|
playingMessageObject.resetPlayingProgress();
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
|
|
|
cleanupPlayer(notify, false);
|
2019-12-31 14:08:08 +01:00
|
|
|
shouldSavePositionForCurrentAudio = null;
|
|
|
|
lastSaveTime = 0;
|
2015-10-29 18:10:07 +01:00
|
|
|
playMusicAgain = false;
|
2018-07-30 04:07:02 +02:00
|
|
|
seekToProgressPending = 0;
|
2015-06-29 19:12:11 +02:00
|
|
|
File file = null;
|
2018-07-30 04:07:02 +02:00
|
|
|
boolean exists = false;
|
2015-06-29 19:12:11 +02:00
|
|
|
if (messageObject.messageOwner.attachPath != null && messageObject.messageOwner.attachPath.length() > 0) {
|
|
|
|
file = new File(messageObject.messageOwner.attachPath);
|
2018-07-30 04:07:02 +02:00
|
|
|
exists = file.exists();
|
|
|
|
if (!exists) {
|
2015-06-29 19:12:11 +02:00
|
|
|
file = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
final File cacheFile = file != null ? file : FileLoader.getPathToMessage(messageObject.messageOwner);
|
2019-05-14 14:08:05 +02:00
|
|
|
boolean canStream = SharedConfig.streamMedia && (messageObject.isMusic() || messageObject.isRoundVideo() || messageObject.isVideo() && messageObject.canStreamVideo()) && (int) messageObject.getDialogId() != 0;
|
2018-07-30 04:07:02 +02:00
|
|
|
if (cacheFile != null && cacheFile != file && !(exists = cacheFile.exists()) && !canStream) {
|
2019-01-23 18:03:33 +01:00
|
|
|
FileLoader.getInstance(messageObject.currentAccount).loadFile(messageObject.getDocument(), messageObject, 0, 0);
|
2015-07-22 20:56:37 +02:00
|
|
|
downloadingCurrentMessage = true;
|
|
|
|
isPaused = false;
|
|
|
|
lastProgress = 0;
|
|
|
|
audioInfo = null;
|
|
|
|
playingMessageObject = messageObject;
|
2018-07-30 04:07:02 +02:00
|
|
|
if (playingMessageObject.isMusic()) {
|
2015-07-22 20:56:37 +02:00
|
|
|
Intent intent = new Intent(ApplicationLoader.applicationContext, MusicPlayerService.class);
|
2018-07-30 04:07:02 +02:00
|
|
|
try {
|
|
|
|
/*if (Build.VERSION.SDK_INT >= 26) {
|
|
|
|
ApplicationLoader.applicationContext.startForegroundService(intent);
|
|
|
|
} else {*/
|
|
|
|
ApplicationLoader.applicationContext.startService(intent);
|
|
|
|
//}
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
} else {
|
|
|
|
Intent intent = new Intent(ApplicationLoader.applicationContext, MusicPlayerService.class);
|
|
|
|
ApplicationLoader.applicationContext.stopService(intent);
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
NotificationCenter.getInstance(playingMessageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingPlayStateChanged, playingMessageObject.getId());
|
2015-07-22 20:56:37 +02:00
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
downloadingCurrentMessage = false;
|
|
|
|
}
|
|
|
|
if (messageObject.isMusic()) {
|
2018-07-30 04:07:02 +02:00
|
|
|
checkIsNextMusicFileDownloaded(messageObject.currentAccount);
|
2017-07-08 18:32:04 +02:00
|
|
|
} else {
|
2018-07-30 04:07:02 +02:00
|
|
|
checkIsNextVoiceFileDownloaded(messageObject.currentAccount);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
if (currentAspectRatioFrameLayout != null) {
|
|
|
|
isDrawingWasReady = false;
|
|
|
|
currentAspectRatioFrameLayout.setDrawingReady(false);
|
|
|
|
}
|
2019-03-03 21:40:48 +01:00
|
|
|
boolean isVideo = messageObject.isVideo();
|
|
|
|
if (messageObject.isRoundVideo() || isVideo) {
|
2019-05-14 14:08:05 +02:00
|
|
|
FileLoader.getInstance(messageObject.currentAccount).setLoadingVideoForPlayer(messageObject.getDocument(), true);
|
2019-03-03 21:40:48 +01:00
|
|
|
playerWasReady = false;
|
2020-09-30 15:48:47 +02:00
|
|
|
boolean destroyAtEnd = !isVideo || messageObject.messageOwner.peer_id.channel_id == 0 && messageObject.audioProgress <= 0.1f;
|
2019-03-03 21:40:48 +01:00
|
|
|
int[] playCount = isVideo && messageObject.getDuration() <= 30 ? new int[]{1} : null;
|
2020-07-26 10:03:38 +02:00
|
|
|
clearPlaylist();
|
2017-07-08 18:32:04 +02:00
|
|
|
videoPlayer = new VideoPlayer();
|
2019-12-31 14:08:08 +01:00
|
|
|
int tag = ++playerNum;
|
2017-07-08 18:32:04 +02:00
|
|
|
videoPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() {
|
|
|
|
@Override
|
|
|
|
public void onStateChanged(boolean playWhenReady, int playbackState) {
|
2019-12-31 14:08:08 +01:00
|
|
|
if (tag != playerNum) {
|
|
|
|
return;
|
|
|
|
}
|
2019-05-14 14:08:05 +02:00
|
|
|
updateVideoState(messageObject, playCount, destroyAtEnd, playWhenReady, playbackState);
|
2017-07-08 18:32:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-06-04 18:47:15 +02:00
|
|
|
public void onError(VideoPlayer player, Exception e) {
|
2017-07-08 18:32:04 +02:00
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
|
|
|
|
currentAspectRatioFrameLayoutRotation = unappliedRotationDegrees;
|
|
|
|
if (unappliedRotationDegrees == 90 || unappliedRotationDegrees == 270) {
|
|
|
|
int temp = width;
|
|
|
|
width = height;
|
|
|
|
height = temp;
|
|
|
|
}
|
|
|
|
currentAspectRatioFrameLayoutRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height;
|
|
|
|
|
|
|
|
if (currentAspectRatioFrameLayout != null) {
|
|
|
|
currentAspectRatioFrameLayout.setAspectRatio(currentAspectRatioFrameLayoutRatio, currentAspectRatioFrameLayoutRotation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onRenderedFirstFrame() {
|
|
|
|
if (currentAspectRatioFrameLayout != null && !currentAspectRatioFrameLayout.isDrawingReady()) {
|
|
|
|
isDrawingWasReady = true;
|
|
|
|
currentAspectRatioFrameLayout.setDrawingReady(true);
|
2019-03-03 21:40:48 +01:00
|
|
|
currentTextureViewContainer.setTag(1);
|
|
|
|
//if (currentTextureViewContainer != null && currentTextureViewContainer.getVisibility() != View.VISIBLE) {
|
|
|
|
// currentTextureViewContainer.setVisibility(View.VISIBLE);
|
|
|
|
//}
|
2017-07-08 18:32:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onSurfaceDestroyed(SurfaceTexture surfaceTexture) {
|
|
|
|
if (videoPlayer == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (pipSwitchingState == 2) {
|
|
|
|
if (currentAspectRatioFrameLayout != null) {
|
|
|
|
if (isDrawingWasReady) {
|
|
|
|
currentAspectRatioFrameLayout.setDrawingReady(true);
|
|
|
|
}
|
|
|
|
if (currentAspectRatioFrameLayout.getParent() == null) {
|
|
|
|
currentTextureViewContainer.addView(currentAspectRatioFrameLayout);
|
|
|
|
}
|
|
|
|
if (currentTextureView.getSurfaceTexture() != surfaceTexture) {
|
|
|
|
currentTextureView.setSurfaceTexture(surfaceTexture);
|
|
|
|
}
|
|
|
|
videoPlayer.setTextureView(currentTextureView);
|
|
|
|
}
|
|
|
|
pipSwitchingState = 0;
|
|
|
|
return true;
|
|
|
|
} else if (pipSwitchingState == 1) {
|
|
|
|
if (baseActivity != null) {
|
|
|
|
if (pipRoundVideoView == null) {
|
|
|
|
try {
|
|
|
|
pipRoundVideoView = new PipRoundVideoView();
|
2019-01-23 18:03:33 +01:00
|
|
|
pipRoundVideoView.show(baseActivity, () -> cleanupPlayer(true, true));
|
2017-07-08 18:32:04 +02:00
|
|
|
} catch (Exception e) {
|
|
|
|
pipRoundVideoView = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pipRoundVideoView != null) {
|
|
|
|
if (pipRoundVideoView.getTextureView().getSurfaceTexture() != surfaceTexture) {
|
|
|
|
pipRoundVideoView.getTextureView().setSurfaceTexture(surfaceTexture);
|
|
|
|
}
|
|
|
|
videoPlayer.setTextureView(pipRoundVideoView.getTextureView());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pipSwitchingState = 0;
|
|
|
|
return true;
|
2019-03-03 21:40:48 +01:00
|
|
|
} else if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isInjectingVideoPlayer()) {
|
|
|
|
PhotoViewer.getInstance().injectVideoPlayerSurface(surfaceTexture);
|
|
|
|
return true;
|
2017-07-08 18:32:04 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
currentAspectRatioFrameLayoutReady = false;
|
2019-09-10 12:56:11 +02:00
|
|
|
if (pipRoundVideoView != null || !MessagesController.getInstance(messageObject.currentAccount).isDialogVisible(messageObject.getDialogId(), messageObject.scheduled)) {
|
2017-07-08 18:32:04 +02:00
|
|
|
if (pipRoundVideoView == null) {
|
|
|
|
try {
|
|
|
|
pipRoundVideoView = new PipRoundVideoView();
|
2019-01-23 18:03:33 +01:00
|
|
|
pipRoundVideoView.show(baseActivity, () -> cleanupPlayer(true, true));
|
2017-07-08 18:32:04 +02:00
|
|
|
} catch (Exception e) {
|
|
|
|
pipRoundVideoView = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pipRoundVideoView != null) {
|
|
|
|
videoPlayer.setTextureView(pipRoundVideoView.getTextureView());
|
|
|
|
}
|
|
|
|
} else if (currentTextureView != null) {
|
|
|
|
videoPlayer.setTextureView(currentTextureView);
|
|
|
|
}
|
2019-03-03 21:40:48 +01:00
|
|
|
|
|
|
|
if (exists) {
|
|
|
|
if (!messageObject.mediaExists && cacheFile != file) {
|
2019-09-10 12:56:11 +02:00
|
|
|
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.fileDidLoad, FileLoader.getAttachFileName(messageObject.getDocument()), cacheFile));
|
2019-03-03 21:40:48 +01:00
|
|
|
}
|
|
|
|
videoPlayer.preparePlayer(Uri.fromFile(cacheFile), "other");
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
int reference = FileLoader.getInstance(messageObject.currentAccount).getFileReference(messageObject);
|
|
|
|
TLRPC.Document document = messageObject.getDocument();
|
|
|
|
String params = "?account=" + messageObject.currentAccount +
|
|
|
|
"&id=" + document.id +
|
|
|
|
"&hash=" + document.access_hash +
|
|
|
|
"&dc=" + document.dc_id +
|
|
|
|
"&size=" + document.size +
|
|
|
|
"&mime=" + URLEncoder.encode(document.mime_type, "UTF-8") +
|
|
|
|
"&rid=" + reference +
|
|
|
|
"&name=" + URLEncoder.encode(FileLoader.getDocumentFileName(document), "UTF-8") +
|
|
|
|
"&reference=" + Utilities.bytesToHex(document.file_reference != null ? document.file_reference : new byte[0]);
|
|
|
|
Uri uri = Uri.parse("tg://" + messageObject.getFileName() + params);
|
|
|
|
videoPlayer.preparePlayer(uri, "other");
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (messageObject.isRoundVideo()) {
|
|
|
|
videoPlayer.setStreamType(useFrontSpeaker ? AudioManager.STREAM_VOICE_CALL : AudioManager.STREAM_MUSIC);
|
|
|
|
if (currentPlaybackSpeed > 1.0f) {
|
|
|
|
videoPlayer.setPlaybackSpeed(currentPlaybackSpeed);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
videoPlayer.setStreamType(AudioManager.STREAM_MUSIC);
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (pipRoundVideoView != null) {
|
|
|
|
pipRoundVideoView.close(true);
|
|
|
|
pipRoundVideoView = null;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
audioPlayer = new VideoPlayer();
|
2019-12-31 14:08:08 +01:00
|
|
|
int tag = ++playerNum;
|
2018-07-30 04:07:02 +02:00
|
|
|
audioPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() {
|
|
|
|
@Override
|
|
|
|
public void onStateChanged(boolean playWhenReady, int playbackState) {
|
2019-12-31 14:08:08 +01:00
|
|
|
if (tag != playerNum) {
|
|
|
|
return;
|
|
|
|
}
|
2019-05-14 14:08:05 +02:00
|
|
|
if (playbackState == ExoPlayer.STATE_ENDED || (playbackState == ExoPlayer.STATE_IDLE || playbackState == ExoPlayer.STATE_BUFFERING) && playWhenReady && messageObject.audioProgress >= 0.999f) {
|
2019-08-22 01:53:26 +02:00
|
|
|
if (!playlist.isEmpty() && (playlist.size() > 1 || !messageObject.isVoice())) {
|
2018-07-30 04:07:02 +02:00
|
|
|
playNextMessageWithoutOrder(true);
|
|
|
|
} else {
|
2019-03-03 21:40:48 +01:00
|
|
|
cleanupPlayer(true, true, messageObject != null && messageObject.isVoice(), false);
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
|
|
|
} else if (seekToProgressPending != 0 && (playbackState == ExoPlayer.STATE_READY || playbackState == ExoPlayer.STATE_IDLE)) {
|
|
|
|
int seekTo = (int) (audioPlayer.getDuration() * seekToProgressPending);
|
|
|
|
audioPlayer.seekTo(seekTo);
|
|
|
|
lastProgress = seekTo;
|
|
|
|
seekToProgressPending = 0;
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-06-04 18:47:15 +02:00
|
|
|
public void onError(VideoPlayer player, Exception e) {
|
2014-03-22 23:31:55 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
@Override
|
|
|
|
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
|
2014-03-22 23:31:55 +01:00
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onRenderedFirstFrame() {
|
2014-03-22 23:31:55 +01:00
|
|
|
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
|
2014-03-22 23:31:55 +01:00
|
|
|
@Override
|
2018-07-30 04:07:02 +02:00
|
|
|
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onSurfaceDestroyed(SurfaceTexture surfaceTexture) {
|
|
|
|
return false;
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
});
|
2020-06-04 18:47:15 +02:00
|
|
|
audioPlayer.setAudioVisualizerDelegate(new VideoPlayer.AudioVisualizerDelegate() {
|
|
|
|
@Override
|
|
|
|
public void onVisualizerUpdate(boolean playing, boolean animate, float[] values) {
|
|
|
|
Theme.getCurrentAudiVisualizerDrawable().setWaveform(playing, animate, values);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean needUpdate() {
|
|
|
|
return Theme.getCurrentAudiVisualizerDrawable().getParentView() != null;
|
|
|
|
}
|
|
|
|
});
|
2018-07-30 04:07:02 +02:00
|
|
|
if (exists) {
|
|
|
|
if (!messageObject.mediaExists && cacheFile != file) {
|
2019-09-10 12:56:11 +02:00
|
|
|
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.fileDidLoad, FileLoader.getAttachFileName(messageObject.getDocument()), cacheFile));
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
|
|
|
audioPlayer.preparePlayer(Uri.fromFile(cacheFile), "other");
|
2020-07-26 10:03:38 +02:00
|
|
|
isStreamingCurrentAudio = false;
|
2018-07-30 04:07:02 +02:00
|
|
|
} else {
|
2019-01-23 18:03:33 +01:00
|
|
|
int reference = FileLoader.getInstance(messageObject.currentAccount).getFileReference(messageObject);
|
2018-07-30 04:07:02 +02:00
|
|
|
TLRPC.Document document = messageObject.getDocument();
|
2019-01-23 18:03:33 +01:00
|
|
|
String params = "?account=" + messageObject.currentAccount +
|
|
|
|
"&id=" + document.id +
|
|
|
|
"&hash=" + document.access_hash +
|
|
|
|
"&dc=" + document.dc_id +
|
|
|
|
"&size=" + document.size +
|
|
|
|
"&mime=" + URLEncoder.encode(document.mime_type, "UTF-8") +
|
|
|
|
"&rid=" + reference +
|
|
|
|
"&name=" + URLEncoder.encode(FileLoader.getDocumentFileName(document), "UTF-8") +
|
|
|
|
"&reference=" + Utilities.bytesToHex(document.file_reference != null ? document.file_reference : new byte[0]);
|
2018-07-30 04:07:02 +02:00
|
|
|
Uri uri = Uri.parse("tg://" + messageObject.getFileName() + params);
|
|
|
|
audioPlayer.preparePlayer(uri, "other");
|
2020-07-26 10:03:38 +02:00
|
|
|
isStreamingCurrentAudio = true;
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
if (messageObject.isVoice()) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (currentPlaybackSpeed > 1.0f) {
|
|
|
|
audioPlayer.setPlaybackSpeed(currentPlaybackSpeed);
|
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
audioInfo = null;
|
2020-07-26 10:03:38 +02:00
|
|
|
clearPlaylist();
|
2015-07-22 20:56:37 +02:00
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
audioInfo = AudioInfo.getAudioInfo(cacheFile);
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2019-12-31 14:08:08 +01:00
|
|
|
String name = messageObject.getFileName();
|
|
|
|
if (!TextUtils.isEmpty(name) && messageObject.getDuration() >= 20 * 60) {
|
|
|
|
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("media_saved_pos", Activity.MODE_PRIVATE);
|
|
|
|
float pos = preferences.getFloat(name, -1);
|
|
|
|
if (pos > 0 && pos < 0.999f) {
|
|
|
|
messageObject.audioProgress = seekToProgressPending = pos;
|
|
|
|
}
|
|
|
|
shouldSavePositionForCurrentAudio = name;
|
|
|
|
if (currentMusicPlaybackSpeed > 1.0f) {
|
|
|
|
audioPlayer.setPlaybackSpeed(currentMusicPlaybackSpeed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (messageObject.forceSeekTo >= 0) {
|
|
|
|
messageObject.audioProgress = seekToProgressPending = messageObject.forceSeekTo;
|
|
|
|
messageObject.forceSeekTo = -1;
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
audioPlayer.setStreamType(useFrontSpeaker ? AudioManager.STREAM_VOICE_CALL : AudioManager.STREAM_MUSIC);
|
|
|
|
audioPlayer.play();
|
2014-03-22 23:31:55 +01:00
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2018-07-30 04:07:02 +02:00
|
|
|
NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingPlayStateChanged, playingMessageObject != null ? playingMessageObject.getId() : 0);
|
2014-03-22 23:31:55 +01:00
|
|
|
if (audioPlayer != null) {
|
2019-03-03 21:40:48 +01:00
|
|
|
audioPlayer.releasePlayer(true);
|
2014-03-22 23:31:55 +01:00
|
|
|
audioPlayer = null;
|
2020-06-04 18:47:15 +02:00
|
|
|
Theme.unrefAudioVisualizeDrawable(playingMessageObject);
|
2014-03-22 23:31:55 +01:00
|
|
|
isPaused = false;
|
|
|
|
playingMessageObject = null;
|
2015-07-22 20:56:37 +02:00
|
|
|
downloadingCurrentMessage = false;
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
2016-04-22 15:49:00 +02:00
|
|
|
checkAudioFocus(messageObject);
|
2016-05-25 23:49:47 +02:00
|
|
|
setPlayerVolume();
|
2014-02-28 23:28:25 +01:00
|
|
|
|
|
|
|
isPaused = false;
|
|
|
|
lastProgress = 0;
|
|
|
|
playingMessageObject = messageObject;
|
2018-07-30 04:07:02 +02:00
|
|
|
if (!SharedConfig.raiseToSpeak) {
|
2016-03-06 02:49:31 +01:00
|
|
|
startRaiseToEarSensors(raiseChat);
|
|
|
|
}
|
2020-01-23 07:15:40 +01:00
|
|
|
if (!ApplicationLoader.mainInterfacePaused && proximityWakeLock != null && !proximityWakeLock.isHeld() && (playingMessageObject.isVoice() || playingMessageObject.isRoundVideo())) {
|
2019-12-31 14:08:08 +01:00
|
|
|
proximityWakeLock.acquire();
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
startProgressTimer(playingMessageObject);
|
2019-01-23 18:03:33 +01:00
|
|
|
NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingDidStart, messageObject);
|
2014-02-28 23:28:25 +01:00
|
|
|
|
2017-07-08 18:32:04 +02:00
|
|
|
if (videoPlayer != null) {
|
|
|
|
try {
|
|
|
|
if (playingMessageObject.audioProgress != 0) {
|
2019-03-03 21:40:48 +01:00
|
|
|
long duration = videoPlayer.getDuration();
|
2018-07-30 04:07:02 +02:00
|
|
|
if (duration == C.TIME_UNSET) {
|
|
|
|
duration = (long) playingMessageObject.getDuration() * 1000;
|
|
|
|
}
|
|
|
|
int seekTo = (int) (duration * playingMessageObject.audioProgress);
|
2019-03-03 21:40:48 +01:00
|
|
|
if (playingMessageObject.audioProgressMs != 0) {
|
|
|
|
seekTo = playingMessageObject.audioProgressMs;
|
|
|
|
playingMessageObject.audioProgressMs = 0;
|
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
videoPlayer.seekTo(seekTo);
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
|
|
|
playingMessageObject.audioProgress = 0;
|
|
|
|
playingMessageObject.audioProgressSec = 0;
|
2018-07-30 04:07:02 +02:00
|
|
|
NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingProgressDidChanged, playingMessageObject.getId(), 0);
|
2017-07-08 18:32:04 +02:00
|
|
|
FileLog.e(e2);
|
|
|
|
}
|
2019-03-03 21:40:48 +01:00
|
|
|
videoPlayer.play();
|
2017-07-08 18:32:04 +02:00
|
|
|
} else if (audioPlayer != null) {
|
2014-03-22 23:31:55 +01:00
|
|
|
try {
|
|
|
|
if (playingMessageObject.audioProgress != 0) {
|
2018-07-30 04:07:02 +02:00
|
|
|
long duration = audioPlayer.getDuration();
|
|
|
|
if (duration == C.TIME_UNSET) {
|
|
|
|
duration = (long) playingMessageObject.getDuration() * 1000;
|
|
|
|
}
|
|
|
|
int seekTo = (int) (duration * playingMessageObject.audioProgress);
|
2014-03-22 23:31:55 +01:00
|
|
|
audioPlayer.seekTo(seekTo);
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
2018-07-30 04:07:02 +02:00
|
|
|
playingMessageObject.resetPlayingProgress();
|
|
|
|
NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingProgressDidChanged, playingMessageObject.getId(), 0);
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e2);
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-03 21:40:48 +01:00
|
|
|
if (playingMessageObject != null && playingMessageObject.isMusic()) {
|
2015-07-22 20:56:37 +02:00
|
|
|
Intent intent = new Intent(ApplicationLoader.applicationContext, MusicPlayerService.class);
|
2018-07-30 04:07:02 +02:00
|
|
|
try {
|
|
|
|
/*if (Build.VERSION.SDK_INT >= 26) {
|
|
|
|
ApplicationLoader.applicationContext.startForegroundService(intent);
|
|
|
|
} else {*/
|
|
|
|
ApplicationLoader.applicationContext.startService(intent);
|
|
|
|
//}
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
} else {
|
|
|
|
Intent intent = new Intent(ApplicationLoader.applicationContext, MusicPlayerService.class);
|
|
|
|
ApplicationLoader.applicationContext.stopService(intent);
|
|
|
|
}
|
|
|
|
|
2014-02-28 23:28:25 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-07-22 20:56:37 +02:00
|
|
|
public AudioInfo getAudioInfo() {
|
|
|
|
return audioInfo;
|
|
|
|
}
|
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
public void setPlaybackOrderType(int type) {
|
2018-07-30 04:07:02 +02:00
|
|
|
boolean oldShuffle = SharedConfig.shuffleMusic;
|
2020-07-26 10:03:38 +02:00
|
|
|
SharedConfig.setPlaybackOrderType(type);
|
2018-07-30 04:07:02 +02:00
|
|
|
if (oldShuffle != SharedConfig.shuffleMusic) {
|
|
|
|
if (SharedConfig.shuffleMusic) {
|
2017-12-08 18:35:59 +01:00
|
|
|
buildShuffledPlayList();
|
|
|
|
currentPlaylistNum = 0;
|
|
|
|
} else {
|
|
|
|
if (playingMessageObject != null) {
|
|
|
|
currentPlaylistNum = playlist.indexOf(playingMessageObject);
|
|
|
|
if (currentPlaylistNum == -1) {
|
2020-07-26 10:03:38 +02:00
|
|
|
clearPlaylist();
|
2017-12-08 18:35:59 +01:00
|
|
|
cleanupPlayer(true, true);
|
|
|
|
}
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
public boolean isStreamingCurrentAudio() {
|
|
|
|
return isStreamingCurrentAudio;
|
|
|
|
}
|
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
public boolean isCurrentPlayer(VideoPlayer player) {
|
|
|
|
return videoPlayer == player || audioPlayer == player;
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
|
|
|
|
2017-07-08 18:32:04 +02:00
|
|
|
public boolean pauseMessage(MessageObject messageObject) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (audioPlayer == null && videoPlayer == null || messageObject == null || playingMessageObject == null || !isSamePlayingMessage(messageObject)) {
|
2014-02-28 23:28:25 +01:00
|
|
|
return false;
|
|
|
|
}
|
2015-05-21 23:27:27 +02:00
|
|
|
stopProgressTimer();
|
2014-02-28 23:28:25 +01:00
|
|
|
try {
|
2014-03-22 23:31:55 +01:00
|
|
|
if (audioPlayer != null) {
|
|
|
|
audioPlayer.pause();
|
2017-07-08 18:32:04 +02:00
|
|
|
} else if (videoPlayer != null) {
|
|
|
|
videoPlayer.pause();
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2014-02-28 23:28:25 +01:00
|
|
|
isPaused = true;
|
2018-07-30 04:07:02 +02:00
|
|
|
NotificationCenter.getInstance(playingMessageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingPlayStateChanged, playingMessageObject.getId());
|
2014-02-28 23:28:25 +01:00
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-02-28 23:28:25 +01:00
|
|
|
isPaused = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-01-05 12:50:11 +01:00
|
|
|
private boolean resumeAudio(MessageObject messageObject) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (audioPlayer == null && videoPlayer == null || messageObject == null || playingMessageObject == null || !isSamePlayingMessage(messageObject)) {
|
2014-02-28 23:28:25 +01:00
|
|
|
return false;
|
|
|
|
}
|
2016-03-06 02:49:31 +01:00
|
|
|
|
2014-02-28 23:28:25 +01:00
|
|
|
try {
|
2017-07-08 18:32:04 +02:00
|
|
|
startProgressTimer(playingMessageObject);
|
2014-03-22 23:31:55 +01:00
|
|
|
if (audioPlayer != null) {
|
2018-07-30 04:07:02 +02:00
|
|
|
audioPlayer.play();
|
2017-07-08 18:32:04 +02:00
|
|
|
} else if (videoPlayer != null) {
|
|
|
|
videoPlayer.play();
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2016-04-22 15:49:00 +02:00
|
|
|
checkAudioFocus(messageObject);
|
2014-02-28 23:28:25 +01:00
|
|
|
isPaused = false;
|
2018-07-30 04:07:02 +02:00
|
|
|
NotificationCenter.getInstance(playingMessageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingPlayStateChanged, playingMessageObject.getId());
|
2014-02-28 23:28:25 +01:00
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-02-28 23:28:25 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-03-03 21:40:48 +01:00
|
|
|
public boolean isVideoDrawingReady() {
|
2017-07-08 18:32:04 +02:00
|
|
|
return currentAspectRatioFrameLayout != null && currentAspectRatioFrameLayout.isDrawingReady();
|
|
|
|
}
|
|
|
|
|
2017-12-08 18:35:59 +01:00
|
|
|
public ArrayList<MessageObject> getPlaylist() {
|
|
|
|
return playlist;
|
|
|
|
}
|
|
|
|
|
2017-07-08 18:32:04 +02:00
|
|
|
public boolean isPlayingMessage(MessageObject messageObject) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (audioPlayer == null && videoPlayer == null || messageObject == null || playingMessageObject == null) {
|
2017-12-08 18:35:59 +01:00
|
|
|
return false;
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
if (playingMessageObject.eventId != 0 && playingMessageObject.eventId == messageObject.eventId) {
|
2017-12-08 18:35:59 +01:00
|
|
|
return !downloadingCurrentMessage;
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
if (isSamePlayingMessage(messageObject)) {
|
2017-12-08 18:35:59 +01:00
|
|
|
return !downloadingCurrentMessage;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
return false;
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
|
|
|
|
2019-03-03 21:40:48 +01:00
|
|
|
public boolean isPlayingMessageAndReadyToDraw(MessageObject messageObject) {
|
|
|
|
return isDrawingWasReady && isPlayingMessage(messageObject);
|
|
|
|
}
|
|
|
|
|
2017-07-08 18:32:04 +02:00
|
|
|
public boolean isMessagePaused() {
|
2015-07-22 20:56:37 +02:00
|
|
|
return isPaused || downloadingCurrentMessage;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isDownloadingCurrentMessage() {
|
|
|
|
return downloadingCurrentMessage;
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
|
|
|
|
2020-09-30 15:48:47 +02:00
|
|
|
public void setReplyingMessage(MessageObject replyToMsg, MessageObject replyToTopMsg) {
|
|
|
|
recordReplyingMsg = replyToMsg;
|
|
|
|
recordReplyingTopMsg = replyToTopMsg;
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
|
|
|
|
2020-01-03 16:45:22 +01:00
|
|
|
public void requestAudioFocus(boolean request) {
|
|
|
|
if (request) {
|
2020-02-13 19:26:53 +01:00
|
|
|
if (!hasRecordAudioFocus && SharedConfig.pauseMusicOnRecord) {
|
2020-01-03 16:45:22 +01:00
|
|
|
int result = NotificationsController.audioManager.requestAudioFocus(audioRecordFocusChangedListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
|
|
|
|
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
|
|
|
hasRecordAudioFocus = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (hasRecordAudioFocus) {
|
|
|
|
NotificationsController.audioManager.abandonAudioFocus(audioRecordFocusChangedListener);
|
|
|
|
hasRecordAudioFocus = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-30 15:48:47 +02:00
|
|
|
public void startRecording(int currentAccount, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, int guid) {
|
2015-07-22 20:56:37 +02:00
|
|
|
boolean paused = false;
|
2017-07-08 18:32:04 +02:00
|
|
|
if (playingMessageObject != null && isPlayingMessage(playingMessageObject) && !isMessagePaused()) {
|
2015-07-22 20:56:37 +02:00
|
|
|
paused = true;
|
2020-01-01 19:32:12 +01:00
|
|
|
}
|
|
|
|
|
2020-01-03 16:45:22 +01:00
|
|
|
requestAudioFocus(true);
|
2014-09-14 01:40:36 +02:00
|
|
|
|
2014-02-28 23:28:25 +01:00
|
|
|
try {
|
2018-07-30 04:07:02 +02:00
|
|
|
feedbackView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
|
|
|
|
} catch (Exception ignore) {
|
|
|
|
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
recordQueue.postRunnable(recordStartRunnable = () -> {
|
|
|
|
if (audioRecorder != null) {
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
recordStartRunnable = null;
|
2019-09-10 12:56:11 +02:00
|
|
|
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStartError, guid);
|
2019-01-23 18:03:33 +01:00
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-09-10 12:56:11 +02:00
|
|
|
sendAfterDone = 0;
|
2019-01-23 18:03:33 +01:00
|
|
|
recordingAudio = new TLRPC.TL_document();
|
2019-09-10 12:56:11 +02:00
|
|
|
recordingGuid = guid;
|
2019-01-23 18:03:33 +01:00
|
|
|
recordingAudio.file_reference = new byte[0];
|
|
|
|
recordingAudio.dc_id = Integer.MIN_VALUE;
|
|
|
|
recordingAudio.id = SharedConfig.getLastLocalId();
|
|
|
|
recordingAudio.user_id = UserConfig.getInstance(currentAccount).getClientUserId();
|
|
|
|
recordingAudio.mime_type = "audio/ogg";
|
|
|
|
recordingAudio.file_reference = new byte[0];
|
|
|
|
SharedConfig.saveConfig();
|
|
|
|
|
|
|
|
recordingAudioFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), FileLoader.getAttachFileName(recordingAudio));
|
|
|
|
|
|
|
|
try {
|
2020-03-30 14:00:09 +02:00
|
|
|
if (startRecord(recordingAudioFile.getAbsolutePath(), 16000) == 0) {
|
2019-01-23 18:03:33 +01:00
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
recordStartRunnable = null;
|
2019-09-10 12:56:11 +02:00
|
|
|
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStartError, guid);
|
2014-03-23 01:09:24 +01:00
|
|
|
});
|
2014-03-22 23:31:55 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-03-30 14:00:09 +02:00
|
|
|
audioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, recordBufferSize);
|
2019-01-23 18:03:33 +01:00
|
|
|
recordStartTime = System.currentTimeMillis();
|
|
|
|
recordTimeCount = 0;
|
|
|
|
samplesCount = 0;
|
2020-09-30 15:48:47 +02:00
|
|
|
recordDialogId = dialogId;
|
2019-01-23 18:03:33 +01:00
|
|
|
recordingCurrentAccount = currentAccount;
|
2020-09-30 15:48:47 +02:00
|
|
|
recordReplyingMsg = replyToMsg;
|
|
|
|
recordReplyingTopMsg = replyToTopMsg;
|
2019-01-23 18:03:33 +01:00
|
|
|
fileBuffer.rewind();
|
2014-03-22 23:31:55 +01:00
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
audioRecorder.startRecording();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
recordingAudio = null;
|
|
|
|
stopRecord();
|
|
|
|
recordingAudioFile.delete();
|
|
|
|
recordingAudioFile = null;
|
2014-03-22 23:31:55 +01:00
|
|
|
try {
|
2019-01-23 18:03:33 +01:00
|
|
|
audioRecorder.release();
|
|
|
|
audioRecorder = null;
|
|
|
|
} catch (Exception e2) {
|
|
|
|
FileLog.e(e2);
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
2014-03-22 23:31:55 +01:00
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
recordStartRunnable = null;
|
2019-09-10 12:56:11 +02:00
|
|
|
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStartError, guid);
|
2014-03-23 01:09:24 +01:00
|
|
|
});
|
2019-01-23 18:03:33 +01:00
|
|
|
return;
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
|
|
|
|
recordQueue.postRunnable(recordRunnable);
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
recordStartRunnable = null;
|
2020-03-30 14:00:09 +02:00
|
|
|
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStarted, guid, true);
|
2019-01-23 18:03:33 +01:00
|
|
|
});
|
2016-03-06 02:49:31 +01:00
|
|
|
}, paused ? 500 : 50);
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
|
2016-03-06 02:49:31 +01:00
|
|
|
public void generateWaveform(MessageObject messageObject) {
|
|
|
|
final String id = messageObject.getId() + "_" + messageObject.getDialogId();
|
|
|
|
final String path = FileLoader.getPathToMessage(messageObject.messageOwner).getAbsolutePath();
|
|
|
|
if (generatingWaveform.containsKey(id)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
generatingWaveform.put(id, messageObject);
|
2019-01-23 18:03:33 +01:00
|
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
|
|
final byte[] waveform = getWaveform(path);
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
MessageObject messageObject1 = generatingWaveform.remove(id);
|
|
|
|
if (messageObject1 == null) {
|
|
|
|
return;
|
|
|
|
}
|
2020-10-02 23:48:16 +02:00
|
|
|
if (waveform != null && messageObject1.getDocument() != null) {
|
2019-01-23 18:03:33 +01:00
|
|
|
for (int a = 0; a < messageObject1.getDocument().attributes.size(); a++) {
|
|
|
|
TLRPC.DocumentAttribute attribute = messageObject1.getDocument().attributes.get(a);
|
|
|
|
if (attribute instanceof TLRPC.TL_documentAttributeAudio) {
|
|
|
|
attribute.waveform = waveform;
|
|
|
|
attribute.flags |= 4;
|
|
|
|
break;
|
2016-03-06 02:49:31 +01:00
|
|
|
}
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages();
|
|
|
|
messagesRes.messages.add(messageObject1.messageOwner);
|
2019-09-10 12:56:11 +02:00
|
|
|
MessagesStorage.getInstance(messageObject1.currentAccount).putMessages(messagesRes, messageObject1.getDialogId(), -1, 0, false, messageObject.scheduled);
|
2019-01-23 18:03:33 +01:00
|
|
|
ArrayList<MessageObject> arrayList = new ArrayList<>();
|
|
|
|
arrayList.add(messageObject1);
|
|
|
|
NotificationCenter.getInstance(messageObject1.currentAccount).postNotificationName(NotificationCenter.replaceMessagesObjects, messageObject1.getDialogId(), arrayList);
|
|
|
|
}
|
|
|
|
});
|
2016-03-06 02:49:31 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-09-10 12:56:11 +02:00
|
|
|
private void stopRecordingInternal(final int send, boolean notify, int scheduleDate) {
|
2016-03-06 02:49:31 +01:00
|
|
|
if (send != 0) {
|
|
|
|
final TLRPC.TL_document audioToSend = recordingAudio;
|
2014-03-22 23:31:55 +01:00
|
|
|
final File recordingAudioFileToSend = recordingAudioFile;
|
2019-01-23 18:03:33 +01:00
|
|
|
fileEncodingQueue.postRunnable(() -> {
|
|
|
|
stopRecord();
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
audioToSend.date = ConnectionsManager.getInstance(recordingCurrentAccount).getCurrentTime();
|
|
|
|
audioToSend.size = (int) recordingAudioFileToSend.length();
|
|
|
|
TLRPC.TL_documentAttributeAudio attributeAudio = new TLRPC.TL_documentAttributeAudio();
|
|
|
|
attributeAudio.voice = true;
|
|
|
|
attributeAudio.waveform = getWaveform2(recordSamples, recordSamples.length);
|
|
|
|
if (attributeAudio.waveform != null) {
|
|
|
|
attributeAudio.flags |= 4;
|
|
|
|
}
|
|
|
|
long duration = recordTimeCount;
|
|
|
|
attributeAudio.duration = (int) (recordTimeCount / 1000);
|
|
|
|
audioToSend.attributes.add(attributeAudio);
|
|
|
|
if (duration > 700) {
|
|
|
|
if (send == 1) {
|
2020-09-30 15:48:47 +02:00
|
|
|
SendMessagesHelper.getInstance(recordingCurrentAccount).sendMessage(audioToSend, null, recordingAudioFileToSend.getAbsolutePath(), recordDialogId, recordReplyingMsg, recordReplyingTopMsg, null, null, null, null, notify, scheduleDate, 0, null);
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2019-09-10 12:56:11 +02:00
|
|
|
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.audioDidSent, recordingGuid, send == 2 ? audioToSend : null, send == 2 ? recordingAudioFileToSend.getAbsolutePath() : null);
|
2019-01-23 18:03:33 +01:00
|
|
|
} else {
|
2020-03-30 14:00:09 +02:00
|
|
|
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.audioRecordTooShort, recordingGuid, false, (int) duration);
|
2019-01-23 18:03:33 +01:00
|
|
|
recordingAudioFileToSend.delete();
|
|
|
|
}
|
2020-01-03 16:45:22 +01:00
|
|
|
requestAudioFocus(false);
|
2019-01-23 18:03:33 +01:00
|
|
|
});
|
2014-03-22 23:31:55 +01:00
|
|
|
});
|
2019-09-10 12:56:11 +02:00
|
|
|
} else {
|
|
|
|
if (recordingAudioFile != null) {
|
|
|
|
recordingAudioFile.delete();
|
|
|
|
}
|
2020-01-03 16:45:22 +01:00
|
|
|
requestAudioFocus(false);
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (audioRecorder != null) {
|
|
|
|
audioRecorder.release();
|
|
|
|
audioRecorder = null;
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
|
|
|
recordingAudio = null;
|
|
|
|
recordingAudioFile = null;
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
|
2019-09-10 12:56:11 +02:00
|
|
|
public void stopRecording(final int send, boolean notify, int scheduleDate) {
|
2015-07-22 20:56:37 +02:00
|
|
|
if (recordStartRunnable != null) {
|
|
|
|
recordQueue.cancelRunnable(recordStartRunnable);
|
2016-03-06 02:49:31 +01:00
|
|
|
recordStartRunnable = null;
|
2015-07-22 20:56:37 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
recordQueue.postRunnable(() -> {
|
2019-09-10 12:56:11 +02:00
|
|
|
if (sendAfterDone == 3) {
|
|
|
|
sendAfterDone = 0;
|
|
|
|
stopRecordingInternal(send, notify, scheduleDate);
|
|
|
|
return;
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
if (audioRecorder == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
sendAfterDone = send;
|
2019-09-10 12:56:11 +02:00
|
|
|
sendAfterDoneNotify = notify;
|
|
|
|
sendAfterDoneScheduleDate = scheduleDate;
|
2019-01-23 18:03:33 +01:00
|
|
|
audioRecorder.stop();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
if (recordingAudioFile != null) {
|
|
|
|
recordingAudioFile.delete();
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
}
|
|
|
|
if (send == 0) {
|
2019-09-10 12:56:11 +02:00
|
|
|
stopRecordingInternal(0, false, 0);
|
2019-01-23 18:03:33 +01:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
feedbackView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
|
|
|
|
} catch (Exception ignore) {
|
2018-07-30 04:07:02 +02:00
|
|
|
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2019-09-10 12:56:11 +02:00
|
|
|
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordStopped, recordingGuid, send == 2 ? 1 : 0));
|
2014-03-22 23:31:55 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-10-30 11:26:29 +01:00
|
|
|
private static class MediaLoader implements NotificationCenter.NotificationCenterDelegate {
|
|
|
|
|
|
|
|
private AccountInstance currentAccount;
|
|
|
|
private AlertDialog progressDialog;
|
|
|
|
private ArrayList<MessageObject> messageObjects;
|
|
|
|
private HashMap<String, MessageObject> loadingMessageObjects = new HashMap<>();
|
|
|
|
private float finishedProgress;
|
|
|
|
private boolean cancelled;
|
|
|
|
private boolean finished;
|
|
|
|
private int copiedFiles;
|
|
|
|
private CountDownLatch waitingForFile;
|
|
|
|
private MessagesStorage.IntCallback onFinishRunnable;
|
|
|
|
private boolean isMusic;
|
|
|
|
|
|
|
|
public MediaLoader(Context context, AccountInstance accountInstance, ArrayList<MessageObject> messages, MessagesStorage.IntCallback onFinish) {
|
|
|
|
currentAccount = accountInstance;
|
|
|
|
messageObjects = messages;
|
|
|
|
onFinishRunnable = onFinish;
|
|
|
|
isMusic = messages.get(0).isMusic();
|
|
|
|
currentAccount.getNotificationCenter().addObserver(this, NotificationCenter.fileDidLoad);
|
|
|
|
currentAccount.getNotificationCenter().addObserver(this, NotificationCenter.FileLoadProgressChanged);
|
|
|
|
currentAccount.getNotificationCenter().addObserver(this, NotificationCenter.fileDidFailToLoad);
|
|
|
|
progressDialog = new AlertDialog(context, 2);
|
|
|
|
progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading));
|
|
|
|
progressDialog.setCanceledOnTouchOutside(false);
|
|
|
|
progressDialog.setCancelable(true);
|
|
|
|
progressDialog.setOnCancelListener(d -> cancelled = true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void start() {
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
if (!finished) {
|
|
|
|
progressDialog.show();
|
|
|
|
}
|
|
|
|
}, 250);
|
|
|
|
|
|
|
|
new Thread(() -> {
|
|
|
|
try {
|
|
|
|
File dir;
|
|
|
|
if (isMusic) {
|
|
|
|
dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
|
|
|
|
} else {
|
|
|
|
dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
|
|
|
}
|
|
|
|
dir.mkdir();
|
|
|
|
for (int b = 0, N = messageObjects.size(); b < N; b++) {
|
|
|
|
MessageObject message = messageObjects.get(b);
|
|
|
|
String name = message.getDocumentName();
|
|
|
|
File destFile = new File(dir, name);
|
|
|
|
if (destFile.exists()) {
|
|
|
|
int idx = name.lastIndexOf('.');
|
|
|
|
for (int a = 0; a < 10; a++) {
|
|
|
|
String newName;
|
|
|
|
if (idx != -1) {
|
|
|
|
newName = name.substring(0, idx) + "(" + (a + 1) + ")" + name.substring(idx);
|
|
|
|
} else {
|
|
|
|
newName = name + "(" + (a + 1) + ")";
|
|
|
|
}
|
|
|
|
destFile = new File(dir, newName);
|
|
|
|
if (!destFile.exists()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!destFile.exists()) {
|
|
|
|
destFile.createNewFile();
|
|
|
|
}
|
|
|
|
String path = message.messageOwner.attachPath;
|
|
|
|
if (path != null && path.length() > 0) {
|
|
|
|
File temp = new File(path);
|
|
|
|
if (!temp.exists()) {
|
|
|
|
path = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (path == null || path.length() == 0) {
|
|
|
|
path = FileLoader.getPathToMessage(message.messageOwner).toString();
|
|
|
|
}
|
|
|
|
File sourceFile = new File(path);
|
|
|
|
if (!sourceFile.exists()) {
|
|
|
|
waitingForFile = new CountDownLatch(1);
|
|
|
|
addMessageToLoad(message);
|
|
|
|
waitingForFile.await();
|
|
|
|
}
|
|
|
|
copyFile(sourceFile, destFile, message.getMimeType());
|
|
|
|
}
|
|
|
|
checkIfFinished();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
}).start();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void checkIfFinished() {
|
|
|
|
if (!loadingMessageObjects.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
try {
|
|
|
|
if (progressDialog.isShowing()) {
|
|
|
|
progressDialog.dismiss();
|
|
|
|
} else {
|
|
|
|
finished = true;
|
|
|
|
}
|
|
|
|
if (onFinishRunnable != null) {
|
|
|
|
AndroidUtilities.runOnUIThread(() -> onFinishRunnable.run(copiedFiles));
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
currentAccount.getNotificationCenter().removeObserver(this, NotificationCenter.fileDidLoad);
|
|
|
|
currentAccount.getNotificationCenter().removeObserver(this, NotificationCenter.FileLoadProgressChanged);
|
|
|
|
currentAccount.getNotificationCenter().removeObserver(this, NotificationCenter.fileDidFailToLoad);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private void addMessageToLoad(MessageObject messageObject) {
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
TLRPC.Document document = messageObject.getDocument();
|
|
|
|
if (document == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
String fileName = FileLoader.getAttachFileName(document);
|
|
|
|
loadingMessageObjects.put(fileName, messageObject);
|
|
|
|
currentAccount.getFileLoader().loadFile(document, messageObject, 1, 0);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean copyFile(File sourceFile, File destFile, String mime) {
|
|
|
|
if (AndroidUtilities.isInternalUri(Uri.fromFile(sourceFile))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
try (FileInputStream inputStream = new FileInputStream(sourceFile); FileChannel source = inputStream.getChannel(); FileChannel destination = new FileOutputStream(destFile).getChannel()) {
|
|
|
|
long size = source.size();
|
|
|
|
try {
|
|
|
|
@SuppressLint("DiscouragedPrivateApi") Method getInt = FileDescriptor.class.getDeclaredMethod("getInt$");
|
|
|
|
int fdint = (Integer) getInt.invoke(inputStream.getFD());
|
|
|
|
if (AndroidUtilities.isInternalUri(fdint)) {
|
|
|
|
if (progressDialog != null) {
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
try {
|
|
|
|
progressDialog.dismiss();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
long lastProgress = 0;
|
|
|
|
for (long a = 0; a < size; a += 4096) {
|
|
|
|
if (cancelled) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
destination.transferFrom(source, a, Math.min(4096, size - a));
|
|
|
|
}
|
|
|
|
if (!cancelled) {
|
|
|
|
if (isMusic) {
|
|
|
|
AndroidUtilities.addMediaToGallery(Uri.fromFile(destFile));
|
|
|
|
} else {
|
|
|
|
DownloadManager downloadManager = (DownloadManager) ApplicationLoader.applicationContext.getSystemService(Context.DOWNLOAD_SERVICE);
|
|
|
|
downloadManager.addCompletedDownload(destFile.getName(), destFile.getName(), false, mime, destFile.getAbsolutePath(), destFile.length(), true);
|
|
|
|
}
|
|
|
|
finishedProgress += 100.0f / messageObjects.size();
|
|
|
|
final int progress = (int) (finishedProgress);
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
try {
|
|
|
|
progressDialog.setProgress(progress);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
copiedFiles++;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
destFile.delete();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void didReceivedNotification(int id, int account, Object... args) {
|
|
|
|
if (id == NotificationCenter.fileDidLoad || id == NotificationCenter.fileDidFailToLoad) {
|
|
|
|
String fileName = (String) args[0];
|
|
|
|
if (loadingMessageObjects.remove(fileName) != null) {
|
|
|
|
waitingForFile.countDown();
|
|
|
|
}
|
|
|
|
} else if (id == NotificationCenter.FileLoadProgressChanged) {
|
|
|
|
String fileName = (String) args[0];
|
|
|
|
if (loadingMessageObjects.containsKey(fileName)) {
|
|
|
|
Long loadedSize = (Long) args[1];
|
|
|
|
Long totalSize = (Long) args[2];
|
|
|
|
float loadProgress = loadedSize / (float) totalSize;
|
|
|
|
final int progress = (int) (finishedProgress + loadProgress / messageObjects.size() * 100);
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
try {
|
|
|
|
progressDialog.setProgress(progress);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void saveFilesFromMessages(Context context, AccountInstance accountInstance, ArrayList<MessageObject> messageObjects, final MessagesStorage.IntCallback onSaved) {
|
|
|
|
new MediaLoader(context, accountInstance, messageObjects, onSaved).start();
|
|
|
|
}
|
|
|
|
|
2016-04-22 15:49:00 +02:00
|
|
|
public static void saveFile(String fullPath, Context context, final int type, final String name, final String mime) {
|
2020-10-30 11:26:29 +01:00
|
|
|
saveFile(fullPath, context, type, name, mime, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void saveFile(String fullPath, Context context, final int type, final String name, final String mime, final Runnable onSaved) {
|
2014-09-30 00:48:11 +02:00
|
|
|
if (fullPath == null) {
|
2014-04-03 23:18:54 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
File file = null;
|
2019-12-31 14:08:08 +01:00
|
|
|
if (!TextUtils.isEmpty(fullPath)) {
|
2014-04-03 23:18:54 +02:00
|
|
|
file = new File(fullPath);
|
2018-07-30 04:07:02 +02:00
|
|
|
if (!file.exists() || AndroidUtilities.isInternalUri(Uri.fromFile(file))) {
|
2014-04-03 23:18:54 +02:00
|
|
|
file = null;
|
|
|
|
}
|
|
|
|
}
|
2014-09-30 00:48:11 +02:00
|
|
|
|
2014-04-03 23:18:54 +02:00
|
|
|
if (file == null) {
|
2014-09-30 00:48:11 +02:00
|
|
|
return;
|
2014-04-03 23:18:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
final File sourceFile = file;
|
2017-12-08 18:35:59 +01:00
|
|
|
final boolean[] cancelled = new boolean[] {false};
|
2014-03-22 23:31:55 +01:00
|
|
|
if (sourceFile.exists()) {
|
2017-03-31 01:58:05 +02:00
|
|
|
AlertDialog progressDialog = null;
|
2020-10-30 11:26:29 +01:00
|
|
|
final boolean[] finished = new boolean[1];
|
2017-12-08 18:35:59 +01:00
|
|
|
if (context != null && type != 0) {
|
2014-11-21 11:59:05 +01:00
|
|
|
try {
|
2020-10-30 11:26:29 +01:00
|
|
|
final AlertDialog dialog = new AlertDialog(context, 2);
|
|
|
|
dialog.setMessage(LocaleController.getString("Loading", R.string.Loading));
|
|
|
|
dialog.setCanceledOnTouchOutside(false);
|
|
|
|
dialog.setCancelable(true);
|
|
|
|
dialog.setOnCancelListener(d -> cancelled[0] = true);
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
if (!finished[0]) {
|
|
|
|
dialog.show();
|
|
|
|
}
|
|
|
|
}, 250);
|
|
|
|
progressDialog = dialog;
|
2014-11-21 11:59:05 +01:00
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-11-21 11:59:05 +01:00
|
|
|
}
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
|
2017-03-31 01:58:05 +02:00
|
|
|
final AlertDialog finalProgress = progressDialog;
|
2014-03-22 23:31:55 +01:00
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
new Thread(() -> {
|
|
|
|
try {
|
|
|
|
File destFile;
|
|
|
|
if (type == 0) {
|
2019-12-31 14:08:08 +01:00
|
|
|
destFile = AndroidUtilities.generatePicturePath(false, FileLoader.getFileExtension(sourceFile));
|
2019-01-23 18:03:33 +01:00
|
|
|
} else if (type == 1) {
|
|
|
|
destFile = AndroidUtilities.generateVideoPath();
|
|
|
|
} else {
|
|
|
|
File dir;
|
|
|
|
if (type == 2) {
|
|
|
|
dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
2017-03-31 01:58:05 +02:00
|
|
|
} else {
|
2019-01-23 18:03:33 +01:00
|
|
|
dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
dir.mkdir();
|
|
|
|
destFile = new File(dir, name);
|
|
|
|
if (destFile.exists()) {
|
|
|
|
int idx = name.lastIndexOf('.');
|
|
|
|
for (int a = 0; a < 10; a++) {
|
|
|
|
String newName;
|
|
|
|
if (idx != -1) {
|
|
|
|
newName = name.substring(0, idx) + "(" + (a + 1) + ")" + name.substring(idx);
|
|
|
|
} else {
|
|
|
|
newName = name + "(" + (a + 1) + ")";
|
2016-10-11 13:57:01 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
destFile = new File(dir, newName);
|
|
|
|
if (!destFile.exists()) {
|
|
|
|
break;
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!destFile.exists()) {
|
|
|
|
destFile.createNewFile();
|
|
|
|
}
|
|
|
|
boolean result = true;
|
|
|
|
long lastProgress = System.currentTimeMillis() - 500;
|
2020-09-30 15:48:47 +02:00
|
|
|
try (FileInputStream inputStream = new FileInputStream(sourceFile); FileChannel source = inputStream.getChannel(); FileChannel destination = new FileOutputStream(destFile).getChannel()) {
|
2019-01-23 18:03:33 +01:00
|
|
|
long size = source.size();
|
2020-09-30 15:48:47 +02:00
|
|
|
try {
|
|
|
|
@SuppressLint("DiscouragedPrivateApi") Method getInt = FileDescriptor.class.getDeclaredMethod("getInt$");
|
|
|
|
int fdint = (Integer) getInt.invoke(inputStream.getFD());
|
|
|
|
if (AndroidUtilities.isInternalUri(fdint)) {
|
|
|
|
if (finalProgress != null) {
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
try {
|
|
|
|
finalProgress.dismiss();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
for (long a = 0; a < size; a += 4096) {
|
|
|
|
if (cancelled[0]) {
|
|
|
|
break;
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
destination.transferFrom(source, a, Math.min(4096, size - a));
|
|
|
|
if (finalProgress != null) {
|
|
|
|
if (lastProgress <= System.currentTimeMillis() - 500) {
|
|
|
|
lastProgress = System.currentTimeMillis();
|
|
|
|
final int progress = (int) ((float) a / (float) size * 100);
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
try {
|
|
|
|
finalProgress.setProgress(progress);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
});
|
2016-10-11 13:57:01 +02:00
|
|
|
}
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
result = false;
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
if (cancelled[0]) {
|
|
|
|
destFile.delete();
|
|
|
|
result = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result) {
|
|
|
|
if (type == 2) {
|
|
|
|
DownloadManager downloadManager = (DownloadManager) ApplicationLoader.applicationContext.getSystemService(Context.DOWNLOAD_SERVICE);
|
|
|
|
downloadManager.addCompletedDownload(destFile.getName(), destFile.getName(), false, mime, destFile.getAbsolutePath(), destFile.length(), true);
|
|
|
|
} else {
|
|
|
|
AndroidUtilities.addMediaToGallery(Uri.fromFile(destFile));
|
|
|
|
}
|
2020-10-30 11:26:29 +01:00
|
|
|
if (onSaved != null) {
|
|
|
|
AndroidUtilities.runOnUIThread(onSaved);
|
|
|
|
}
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
if (finalProgress != null) {
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
try {
|
2020-10-30 11:26:29 +01:00
|
|
|
if (finalProgress.isShowing()) {
|
|
|
|
finalProgress.dismiss();
|
|
|
|
} else {
|
|
|
|
finished[0] = true;
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
});
|
2014-03-22 23:31:55 +01:00
|
|
|
}
|
2014-06-13 12:42:21 +02:00
|
|
|
}).start();
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|
|
|
|
}
|
2014-03-31 16:14:49 +02:00
|
|
|
|
2015-01-02 23:15:07 +01:00
|
|
|
public static boolean isWebp(Uri uri) {
|
2016-03-16 13:26:32 +01:00
|
|
|
InputStream inputStream = null;
|
2015-01-02 23:15:07 +01:00
|
|
|
try {
|
2016-03-16 13:26:32 +01:00
|
|
|
inputStream = ApplicationLoader.applicationContext.getContentResolver().openInputStream(uri);
|
|
|
|
byte[] header = new byte[12];
|
|
|
|
if (inputStream.read(header, 0, 12) == 12) {
|
2015-01-02 23:15:07 +01:00
|
|
|
String str = new String(header);
|
|
|
|
if (str != null) {
|
|
|
|
str = str.toLowerCase();
|
2015-07-22 20:56:37 +02:00
|
|
|
if (str.startsWith("riff") && str.endsWith("webp")) {
|
2015-01-02 23:15:07 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2015-01-02 23:15:07 +01:00
|
|
|
} finally {
|
|
|
|
try {
|
2016-03-16 13:26:32 +01:00
|
|
|
if (inputStream != null) {
|
|
|
|
inputStream.close();
|
2015-01-02 23:15:07 +01:00
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e2);
|
2015-01-02 23:15:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-04-05 19:11:44 +02:00
|
|
|
public static boolean isGif(Uri uri) {
|
2016-03-16 13:26:32 +01:00
|
|
|
InputStream inputStream = null;
|
2014-04-05 19:11:44 +02:00
|
|
|
try {
|
2016-03-16 13:26:32 +01:00
|
|
|
inputStream = ApplicationLoader.applicationContext.getContentResolver().openInputStream(uri);
|
|
|
|
byte[] header = new byte[3];
|
|
|
|
if (inputStream.read(header, 0, 3) == 3) {
|
2014-04-05 19:11:44 +02:00
|
|
|
String str = new String(header);
|
|
|
|
if (str != null && str.equalsIgnoreCase("gif")) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-04-05 19:11:44 +02:00
|
|
|
} finally {
|
|
|
|
try {
|
2016-03-16 13:26:32 +01:00
|
|
|
if (inputStream != null) {
|
|
|
|
inputStream.close();
|
2014-04-05 19:11:44 +02:00
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e2);
|
2014-04-05 19:11:44 +02:00
|
|
|
}
|
2016-03-16 13:26:32 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String getFileName(Uri uri) {
|
|
|
|
String result = null;
|
|
|
|
if (uri.getScheme().equals("content")) {
|
2019-08-22 01:53:26 +02:00
|
|
|
try (Cursor cursor = ApplicationLoader.applicationContext.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null)) {
|
2016-03-16 13:26:32 +01:00
|
|
|
if (cursor.moveToFirst()) {
|
|
|
|
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-04-05 19:11:44 +02:00
|
|
|
}
|
|
|
|
}
|
2016-03-16 13:26:32 +01:00
|
|
|
if (result == null) {
|
|
|
|
result = uri.getPath();
|
|
|
|
int cut = result.lastIndexOf('/');
|
|
|
|
if (cut != -1) {
|
|
|
|
result = result.substring(cut + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
2014-04-05 19:11:44 +02:00
|
|
|
}
|
|
|
|
|
2020-09-30 15:48:47 +02:00
|
|
|
@SuppressLint("DiscouragedPrivateApi")
|
2016-03-16 13:26:32 +01:00
|
|
|
public static String copyFileToCache(Uri uri, String ext) {
|
|
|
|
InputStream inputStream = null;
|
2014-04-05 19:11:44 +02:00
|
|
|
FileOutputStream output = null;
|
|
|
|
try {
|
2018-07-30 04:07:02 +02:00
|
|
|
String name = FileLoader.fixFileName(getFileName(uri));
|
2016-03-16 13:26:32 +01:00
|
|
|
if (name == null) {
|
2018-07-30 04:07:02 +02:00
|
|
|
int id = SharedConfig.getLastLocalId();
|
|
|
|
SharedConfig.saveConfig();
|
2016-03-16 13:26:32 +01:00
|
|
|
name = String.format(Locale.US, "%d.%s", id, ext);
|
|
|
|
}
|
2019-12-31 14:08:08 +01:00
|
|
|
File f = AndroidUtilities.getSharingDirectory();
|
2017-12-08 18:35:59 +01:00
|
|
|
f.mkdirs();
|
|
|
|
f = new File(f, name);
|
2018-07-30 04:07:02 +02:00
|
|
|
if (AndroidUtilities.isInternalUri(Uri.fromFile(f))) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
inputStream = ApplicationLoader.applicationContext.getContentResolver().openInputStream(uri);
|
2020-09-30 15:48:47 +02:00
|
|
|
if (inputStream instanceof FileInputStream) {
|
|
|
|
FileInputStream fileInputStream = (FileInputStream) inputStream;
|
|
|
|
try {
|
|
|
|
Method getInt = FileDescriptor.class.getDeclaredMethod("getInt$");
|
|
|
|
int fdint = (Integer) getInt.invoke(fileInputStream.getFD());
|
|
|
|
if (AndroidUtilities.isInternalUri(fdint)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
}
|
2014-04-05 19:11:44 +02:00
|
|
|
output = new FileOutputStream(f);
|
2016-03-16 13:26:32 +01:00
|
|
|
byte[] buffer = new byte[1024 * 20];
|
|
|
|
int len;
|
|
|
|
while ((len = inputStream.read(buffer)) != -1) {
|
|
|
|
output.write(buffer, 0, len);
|
|
|
|
}
|
2014-04-05 19:11:44 +02:00
|
|
|
return f.getAbsolutePath();
|
|
|
|
} catch (Exception e) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e);
|
2014-04-05 19:11:44 +02:00
|
|
|
} finally {
|
|
|
|
try {
|
2016-03-16 13:26:32 +01:00
|
|
|
if (inputStream != null) {
|
|
|
|
inputStream.close();
|
2014-04-05 19:11:44 +02:00
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e2);
|
2014-04-05 19:11:44 +02:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (output != null) {
|
|
|
|
output.close();
|
|
|
|
}
|
|
|
|
} catch (Exception e2) {
|
2017-03-31 01:58:05 +02:00
|
|
|
FileLog.e(e2);
|
2014-04-05 19:11:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2014-06-12 03:13:15 +02:00
|
|
|
|
|
|
|
public static void loadGalleryPhotosAlbums(final int guid) {
|
2019-01-23 18:03:33 +01:00
|
|
|
Thread thread = new Thread(() -> {
|
|
|
|
final ArrayList<AlbumEntry> mediaAlbumsSorted = new ArrayList<>();
|
|
|
|
final ArrayList<AlbumEntry> photoAlbumsSorted = new ArrayList<>();
|
|
|
|
SparseArray<AlbumEntry> mediaAlbums = new SparseArray<>();
|
|
|
|
SparseArray<AlbumEntry> photoAlbums = new SparseArray<>();
|
|
|
|
AlbumEntry allPhotosAlbum = null;
|
2019-02-08 03:30:32 +01:00
|
|
|
AlbumEntry allVideosAlbum = null;
|
2019-01-23 18:03:33 +01:00
|
|
|
AlbumEntry allMediaAlbum = null;
|
|
|
|
String cameraFolder = null;
|
|
|
|
try {
|
|
|
|
cameraFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() + "/" + "Camera/";
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
|
|
|
Integer mediaCameraAlbumId = null;
|
|
|
|
Integer photoCameraAlbumId = null;
|
2014-06-12 03:13:15 +02:00
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
Cursor cursor = null;
|
|
|
|
try {
|
|
|
|
if (Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
2019-12-31 14:08:08 +01:00
|
|
|
cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projectionPhotos, null, null, (Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_MODIFIED : MediaStore.Images.Media.DATE_TAKEN) + " DESC");
|
2019-01-23 18:03:33 +01:00
|
|
|
if (cursor != null) {
|
|
|
|
int imageIdColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID);
|
|
|
|
int bucketIdColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID);
|
|
|
|
int bucketNameColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
|
|
|
|
int dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
|
2019-09-10 12:56:11 +02:00
|
|
|
int dateColumn = cursor.getColumnIndex(Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_MODIFIED : MediaStore.Images.Media.DATE_TAKEN);
|
2019-01-23 18:03:33 +01:00
|
|
|
int orientationColumn = cursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION);
|
2019-12-31 14:08:08 +01:00
|
|
|
int widthColumn = cursor.getColumnIndex(MediaStore.Images.Media.WIDTH);
|
|
|
|
int heightColumn = cursor.getColumnIndex(MediaStore.Images.Media.HEIGHT);
|
|
|
|
int sizeColumn = cursor.getColumnIndex(MediaStore.Images.Media.SIZE);
|
2019-01-23 18:03:33 +01:00
|
|
|
|
|
|
|
while (cursor.moveToNext()) {
|
2019-12-31 14:08:08 +01:00
|
|
|
String path = cursor.getString(dataColumn);
|
|
|
|
if (TextUtils.isEmpty(path)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
int imageId = cursor.getInt(imageIdColumn);
|
|
|
|
int bucketId = cursor.getInt(bucketIdColumn);
|
|
|
|
String bucketName = cursor.getString(bucketNameColumn);
|
|
|
|
long dateTaken = cursor.getLong(dateColumn);
|
|
|
|
int orientation = cursor.getInt(orientationColumn);
|
2019-12-31 14:08:08 +01:00
|
|
|
int width = cursor.getInt(widthColumn);
|
|
|
|
int height = cursor.getInt(heightColumn);
|
|
|
|
long size = cursor.getLong(sizeColumn);
|
2019-01-23 18:03:33 +01:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, orientation, false, width, height, size);
|
2014-06-12 03:13:15 +02:00
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
if (allPhotosAlbum == null) {
|
|
|
|
allPhotosAlbum = new AlbumEntry(0, LocaleController.getString("AllPhotos", R.string.AllPhotos), photoEntry);
|
|
|
|
photoAlbumsSorted.add(0, allPhotosAlbum);
|
|
|
|
}
|
|
|
|
if (allMediaAlbum == null) {
|
|
|
|
allMediaAlbum = new AlbumEntry(0, LocaleController.getString("AllMedia", R.string.AllMedia), photoEntry);
|
|
|
|
mediaAlbumsSorted.add(0, allMediaAlbum);
|
|
|
|
}
|
|
|
|
allPhotosAlbum.addPhoto(photoEntry);
|
|
|
|
allMediaAlbum.addPhoto(photoEntry);
|
|
|
|
|
|
|
|
AlbumEntry albumEntry = mediaAlbums.get(bucketId);
|
|
|
|
if (albumEntry == null) {
|
|
|
|
albumEntry = new AlbumEntry(bucketId, bucketName, photoEntry);
|
|
|
|
mediaAlbums.put(bucketId, albumEntry);
|
|
|
|
if (mediaCameraAlbumId == null && cameraFolder != null && path != null && path.startsWith(cameraFolder)) {
|
|
|
|
mediaAlbumsSorted.add(0, albumEntry);
|
|
|
|
mediaCameraAlbumId = bucketId;
|
|
|
|
} else {
|
|
|
|
mediaAlbumsSorted.add(albumEntry);
|
2014-06-12 03:13:15 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
}
|
|
|
|
albumEntry.addPhoto(photoEntry);
|
|
|
|
|
|
|
|
albumEntry = photoAlbums.get(bucketId);
|
|
|
|
if (albumEntry == null) {
|
|
|
|
albumEntry = new AlbumEntry(bucketId, bucketName, photoEntry);
|
|
|
|
photoAlbums.put(bucketId, albumEntry);
|
|
|
|
if (photoCameraAlbumId == null && cameraFolder != null && path != null && path.startsWith(cameraFolder)) {
|
|
|
|
photoAlbumsSorted.add(0, albumEntry);
|
|
|
|
photoCameraAlbumId = bucketId;
|
|
|
|
} else {
|
|
|
|
photoAlbumsSorted.add(albumEntry);
|
2017-07-08 18:32:04 +02:00
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
albumEntry.addPhoto(photoEntry);
|
2014-06-12 03:13:15 +02:00
|
|
|
}
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
}
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
} finally {
|
|
|
|
if (cursor != null) {
|
|
|
|
try {
|
|
|
|
cursor.close();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
2014-06-12 03:13:15 +02:00
|
|
|
}
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
}
|
2015-05-03 13:48:36 +02:00
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
try {
|
|
|
|
if (Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
2019-12-31 14:08:08 +01:00
|
|
|
cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projectionVideo, null, null, (Build.VERSION.SDK_INT > 28 ? MediaStore.Video.Media.DATE_MODIFIED : MediaStore.Video.Media.DATE_TAKEN) + " DESC");
|
2019-01-23 18:03:33 +01:00
|
|
|
if (cursor != null) {
|
|
|
|
int imageIdColumn = cursor.getColumnIndex(MediaStore.Video.Media._ID);
|
|
|
|
int bucketIdColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID);
|
|
|
|
int bucketNameColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME);
|
|
|
|
int dataColumn = cursor.getColumnIndex(MediaStore.Video.Media.DATA);
|
2019-09-10 12:56:11 +02:00
|
|
|
int dateColumn = cursor.getColumnIndex(Build.VERSION.SDK_INT > 28 ? MediaStore.Video.Media.DATE_MODIFIED : MediaStore.Video.Media.DATE_TAKEN);
|
2019-01-23 18:03:33 +01:00
|
|
|
int durationColumn = cursor.getColumnIndex(MediaStore.Video.Media.DURATION);
|
2019-12-31 14:08:08 +01:00
|
|
|
int widthColumn = cursor.getColumnIndex(MediaStore.Video.Media.WIDTH);
|
|
|
|
int heightColumn = cursor.getColumnIndex(MediaStore.Video.Media.HEIGHT);
|
|
|
|
int sizeColumn = cursor.getColumnIndex(MediaStore.Video.Media.SIZE);
|
2019-01-23 18:03:33 +01:00
|
|
|
|
|
|
|
while (cursor.moveToNext()) {
|
2019-12-31 14:08:08 +01:00
|
|
|
String path = cursor.getString(dataColumn);
|
|
|
|
if (TextUtils.isEmpty(path)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-01-23 18:03:33 +01:00
|
|
|
int imageId = cursor.getInt(imageIdColumn);
|
|
|
|
int bucketId = cursor.getInt(bucketIdColumn);
|
|
|
|
String bucketName = cursor.getString(bucketNameColumn);
|
|
|
|
long dateTaken = cursor.getLong(dateColumn);
|
|
|
|
long duration = cursor.getLong(durationColumn);
|
2019-12-31 14:08:08 +01:00
|
|
|
int width = cursor.getInt(widthColumn);
|
|
|
|
int height = cursor.getInt(heightColumn);
|
|
|
|
long size = cursor.getLong(sizeColumn);
|
2019-01-23 18:03:33 +01:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, (int) (duration / 1000), true, width, height, size);
|
2015-05-03 13:48:36 +02:00
|
|
|
|
2019-02-08 03:30:32 +01:00
|
|
|
if (allVideosAlbum == null) {
|
|
|
|
allVideosAlbum = new AlbumEntry(0, LocaleController.getString("AllVideos", R.string.AllVideos), photoEntry);
|
2019-08-22 01:53:26 +02:00
|
|
|
allVideosAlbum.videoOnly = true;
|
2019-02-08 03:30:32 +01:00
|
|
|
int index = 0;
|
|
|
|
if (allMediaAlbum != null) {
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
if (allPhotosAlbum != null) {
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
mediaAlbumsSorted.add(index, allVideosAlbum);
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
if (allMediaAlbum == null) {
|
|
|
|
allMediaAlbum = new AlbumEntry(0, LocaleController.getString("AllMedia", R.string.AllMedia), photoEntry);
|
|
|
|
mediaAlbumsSorted.add(0, allMediaAlbum);
|
|
|
|
}
|
2019-02-08 03:30:32 +01:00
|
|
|
allVideosAlbum.addPhoto(photoEntry);
|
2019-01-23 18:03:33 +01:00
|
|
|
allMediaAlbum.addPhoto(photoEntry);
|
|
|
|
|
|
|
|
AlbumEntry albumEntry = mediaAlbums.get(bucketId);
|
|
|
|
if (albumEntry == null) {
|
|
|
|
albumEntry = new AlbumEntry(bucketId, bucketName, photoEntry);
|
|
|
|
mediaAlbums.put(bucketId, albumEntry);
|
|
|
|
if (mediaCameraAlbumId == null && cameraFolder != null && path != null && path.startsWith(cameraFolder)) {
|
|
|
|
mediaAlbumsSorted.add(0, albumEntry);
|
|
|
|
mediaCameraAlbumId = bucketId;
|
|
|
|
} else {
|
|
|
|
mediaAlbumsSorted.add(albumEntry);
|
2015-05-03 13:48:36 +02:00
|
|
|
}
|
2015-10-29 18:10:07 +01:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
|
|
|
|
albumEntry.addPhoto(photoEntry);
|
2015-05-03 13:48:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
} finally {
|
|
|
|
if (cursor != null) {
|
|
|
|
try {
|
|
|
|
cursor.close();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
2017-07-08 18:32:04 +02:00
|
|
|
}
|
2014-06-12 03:13:15 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
for (int a = 0; a < mediaAlbumsSorted.size(); a++) {
|
|
|
|
Collections.sort(mediaAlbumsSorted.get(a).photos, (o1, o2) -> {
|
|
|
|
if (o1.dateTaken < o2.dateTaken) {
|
|
|
|
return 1;
|
|
|
|
} else if (o1.dateTaken > o2.dateTaken) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
}
|
2019-02-08 03:30:32 +01:00
|
|
|
broadcastNewPhotos(guid, mediaAlbumsSorted, photoAlbumsSorted, mediaCameraAlbumId, allMediaAlbum, allPhotosAlbum, allVideosAlbum, 0);
|
2016-04-22 15:49:00 +02:00
|
|
|
});
|
|
|
|
thread.setPriority(Thread.MIN_PRIORITY);
|
|
|
|
thread.start();
|
2014-06-12 03:13:15 +02:00
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-02-08 03:30:32 +01:00
|
|
|
private static void broadcastNewPhotos(final int guid, final ArrayList<AlbumEntry> mediaAlbumsSorted, final ArrayList<AlbumEntry> photoAlbumsSorted, final Integer cameraAlbumIdFinal, final AlbumEntry allMediaAlbumFinal, final AlbumEntry allPhotosAlbumFinal, final AlbumEntry allVideosAlbumFinal, int delay) {
|
2016-10-11 13:57:01 +02:00
|
|
|
if (broadcastPhotosRunnable != null) {
|
|
|
|
AndroidUtilities.cancelRunOnUIThread(broadcastPhotosRunnable);
|
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
AndroidUtilities.runOnUIThread(broadcastPhotosRunnable = () -> {
|
|
|
|
if (PhotoViewer.getInstance().isVisible()) {
|
2019-02-08 03:30:32 +01:00
|
|
|
broadcastNewPhotos(guid, mediaAlbumsSorted, photoAlbumsSorted, cameraAlbumIdFinal, allMediaAlbumFinal, allPhotosAlbumFinal, allVideosAlbumFinal, 1000);
|
2019-01-23 18:03:33 +01:00
|
|
|
return;
|
|
|
|
}
|
2019-08-22 01:53:26 +02:00
|
|
|
allMediaAlbums = mediaAlbumsSorted;
|
|
|
|
allPhotoAlbums = photoAlbumsSorted;
|
2019-01-23 18:03:33 +01:00
|
|
|
broadcastPhotosRunnable = null;
|
|
|
|
allPhotosAlbumEntry = allPhotosAlbumFinal;
|
|
|
|
allMediaAlbumEntry = allMediaAlbumFinal;
|
2019-02-08 03:30:32 +01:00
|
|
|
allVideosAlbumEntry = allVideosAlbumFinal;
|
2020-04-24 11:21:58 +02:00
|
|
|
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.albumsDidLoad, guid, mediaAlbumsSorted, photoAlbumsSorted, cameraAlbumIdFinal);
|
2016-10-11 13:57:01 +02:00
|
|
|
}, delay);
|
|
|
|
}
|
|
|
|
|
2014-09-28 15:37:26 +02:00
|
|
|
public void scheduleVideoConvert(MessageObject messageObject) {
|
2017-03-31 01:58:05 +02:00
|
|
|
scheduleVideoConvert(messageObject, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean scheduleVideoConvert(MessageObject messageObject, boolean isEmpty) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (messageObject == null || messageObject.videoEditedInfo == null) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-03-31 01:58:05 +02:00
|
|
|
if (isEmpty && !videoConvertQueue.isEmpty()) {
|
|
|
|
return false;
|
|
|
|
} else if (isEmpty) {
|
|
|
|
new File(messageObject.messageOwner.attachPath).delete();
|
|
|
|
}
|
2020-01-01 19:32:12 +01:00
|
|
|
videoConvertQueue.add(new VideoConvertMessage(messageObject, messageObject.videoEditedInfo));
|
2014-09-28 15:37:26 +02:00
|
|
|
if (videoConvertQueue.size() == 1) {
|
|
|
|
startVideoConvertFromQueue();
|
|
|
|
}
|
2017-03-31 01:58:05 +02:00
|
|
|
return true;
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void cancelVideoConvert(MessageObject messageObject) {
|
2019-12-31 14:08:08 +01:00
|
|
|
if (messageObject != null) {
|
2014-09-30 00:48:11 +02:00
|
|
|
if (!videoConvertQueue.isEmpty()) {
|
2018-07-30 04:07:02 +02:00
|
|
|
for (int a = 0; a < videoConvertQueue.size(); a++) {
|
2020-01-01 19:32:12 +01:00
|
|
|
VideoConvertMessage videoConvertMessage = videoConvertQueue.get(a);
|
|
|
|
MessageObject object = videoConvertMessage.messageObject;
|
|
|
|
if (object.equals(messageObject) && object.currentAccount == messageObject.currentAccount) {
|
2018-07-30 04:07:02 +02:00
|
|
|
if (a == 0) {
|
|
|
|
synchronized (videoConvertSync) {
|
2020-01-01 19:32:12 +01:00
|
|
|
videoConvertMessage.videoEditedInfo.canceled = true;
|
2018-07-30 04:07:02 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
videoConvertQueue.remove(a);
|
|
|
|
}
|
|
|
|
break;
|
2014-09-30 00:48:11 +02:00
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-31 01:58:05 +02:00
|
|
|
private boolean startVideoConvertFromQueue() {
|
2014-09-28 15:37:26 +02:00
|
|
|
if (!videoConvertQueue.isEmpty()) {
|
2020-01-01 19:32:12 +01:00
|
|
|
VideoConvertMessage videoConvertMessage = videoConvertQueue.get(0);
|
|
|
|
MessageObject messageObject = videoConvertMessage.messageObject;
|
|
|
|
VideoEditedInfo videoEditedInfo = videoConvertMessage.videoEditedInfo;
|
2014-09-30 00:48:11 +02:00
|
|
|
synchronized (videoConvertSync) {
|
2020-01-01 19:32:12 +01:00
|
|
|
if (videoEditedInfo != null) {
|
|
|
|
videoEditedInfo.canceled = false;
|
2019-12-31 20:46:59 +01:00
|
|
|
}
|
2014-09-30 00:48:11 +02:00
|
|
|
}
|
|
|
|
Intent intent = new Intent(ApplicationLoader.applicationContext, VideoEncodingService.class);
|
|
|
|
intent.putExtra("path", messageObject.messageOwner.attachPath);
|
2018-07-30 04:07:02 +02:00
|
|
|
intent.putExtra("currentAccount", messageObject.currentAccount);
|
2016-10-11 13:57:01 +02:00
|
|
|
if (messageObject.messageOwner.media.document != null) {
|
|
|
|
for (int a = 0; a < messageObject.messageOwner.media.document.attributes.size(); a++) {
|
|
|
|
TLRPC.DocumentAttribute documentAttribute = messageObject.messageOwner.media.document.attributes.get(a);
|
|
|
|
if (documentAttribute instanceof TLRPC.TL_documentAttributeAnimated) {
|
|
|
|
intent.putExtra("gif", true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-03-31 01:58:05 +02:00
|
|
|
if (messageObject.getId() != 0) {
|
2018-07-30 04:07:02 +02:00
|
|
|
try {
|
|
|
|
ApplicationLoader.applicationContext.startService(intent);
|
|
|
|
} catch (Throwable e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
2017-03-31 01:58:05 +02:00
|
|
|
}
|
2020-01-01 19:32:12 +01:00
|
|
|
VideoConvertRunnable.runConversion(videoConvertMessage);
|
2017-03-31 01:58:05 +02:00
|
|
|
return true;
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
2017-03-31 01:58:05 +02:00
|
|
|
return false;
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
|
2015-05-21 23:27:27 +02:00
|
|
|
@SuppressLint("NewApi")
|
2014-10-07 22:14:27 +02:00
|
|
|
public static MediaCodecInfo selectCodec(String mimeType) {
|
2014-09-28 15:37:26 +02:00
|
|
|
int numCodecs = MediaCodecList.getCodecCount();
|
|
|
|
MediaCodecInfo lastCodecInfo = null;
|
|
|
|
for (int i = 0; i < numCodecs; i++) {
|
|
|
|
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
|
|
|
|
if (!codecInfo.isEncoder()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
String[] types = codecInfo.getSupportedTypes();
|
|
|
|
for (String type : types) {
|
|
|
|
if (type.equalsIgnoreCase(mimeType)) {
|
|
|
|
lastCodecInfo = codecInfo;
|
2018-07-30 04:07:02 +02:00
|
|
|
String name = lastCodecInfo.getName();
|
|
|
|
if (name != null) {
|
|
|
|
if (!name.equals("OMX.SEC.avc.enc")) {
|
|
|
|
return lastCodecInfo;
|
|
|
|
} else if (name.equals("OMX.SEC.AVC.Encoder")) {
|
|
|
|
return lastCodecInfo;
|
|
|
|
}
|
2014-09-30 00:48:11 +02:00
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return lastCodecInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static boolean isRecognizedFormat(int colorFormat) {
|
|
|
|
switch (colorFormat) {
|
|
|
|
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
|
|
|
|
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
|
|
|
|
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
|
|
|
|
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
|
|
|
|
case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-21 23:27:27 +02:00
|
|
|
@SuppressLint("NewApi")
|
2014-10-07 22:14:27 +02:00
|
|
|
public static int selectColorFormat(MediaCodecInfo codecInfo, String mimeType) {
|
2014-09-28 15:37:26 +02:00
|
|
|
MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
|
2014-09-30 00:48:11 +02:00
|
|
|
int lastColorFormat = 0;
|
2014-09-28 15:37:26 +02:00
|
|
|
for (int i = 0; i < capabilities.colorFormats.length; i++) {
|
|
|
|
int colorFormat = capabilities.colorFormats[i];
|
|
|
|
if (isRecognizedFormat(colorFormat)) {
|
2014-09-30 00:48:11 +02:00
|
|
|
lastColorFormat = colorFormat;
|
|
|
|
if (!(codecInfo.getName().equals("OMX.SEC.AVC.Encoder") && colorFormat == 19)) {
|
|
|
|
return colorFormat;
|
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
}
|
2014-09-30 00:48:11 +02:00
|
|
|
return lastColorFormat;
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
public static int findTrack(MediaExtractor extractor, boolean audio) {
|
2014-09-28 15:37:26 +02:00
|
|
|
int numTracks = extractor.getTrackCount();
|
|
|
|
for (int i = 0; i < numTracks; i++) {
|
|
|
|
MediaFormat format = extractor.getTrackFormat(i);
|
|
|
|
String mime = format.getString(MediaFormat.KEY_MIME);
|
|
|
|
if (audio) {
|
|
|
|
if (mime.startsWith("audio/")) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (mime.startsWith("video/")) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -5;
|
|
|
|
}
|
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
private void didWriteData(final VideoConvertMessage message, final File file, final boolean last, final long lastFrameTimestamp, long availableSize, final boolean error, final float progress) {
|
2020-01-01 19:32:12 +01:00
|
|
|
final boolean firstWrite = message.videoEditedInfo.videoConvertFirstWrite;
|
2014-09-28 15:37:26 +02:00
|
|
|
if (firstWrite) {
|
2020-01-01 19:32:12 +01:00
|
|
|
message.videoEditedInfo.videoConvertFirstWrite = false;
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
2019-01-23 18:03:33 +01:00
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
|
|
if (error || last) {
|
|
|
|
synchronized (videoConvertSync) {
|
2020-01-01 19:32:12 +01:00
|
|
|
message.videoEditedInfo.canceled = false;
|
2017-03-31 01:58:05 +02:00
|
|
|
}
|
2020-01-01 19:32:12 +01:00
|
|
|
videoConvertQueue.remove(message);
|
2019-01-23 18:03:33 +01:00
|
|
|
startVideoConvertFromQueue();
|
|
|
|
}
|
|
|
|
if (error) {
|
2020-07-26 10:03:38 +02:00
|
|
|
NotificationCenter.getInstance(message.currentAccount).postNotificationName(NotificationCenter.filePreparingFailed, message.messageObject, file.toString(), progress, lastFrameTimestamp);
|
2019-01-23 18:03:33 +01:00
|
|
|
} else {
|
|
|
|
if (firstWrite) {
|
2020-07-26 10:03:38 +02:00
|
|
|
NotificationCenter.getInstance(message.currentAccount).postNotificationName(NotificationCenter.filePreparingStarted, message.messageObject, file.toString(), progress, lastFrameTimestamp);
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
2020-07-26 10:03:38 +02:00
|
|
|
NotificationCenter.getInstance(message.currentAccount).postNotificationName(NotificationCenter.fileNewChunkAvailable, message.messageObject, file.toString(), availableSize, last ? file.length() : 0, progress, lastFrameTimestamp);
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private static class VideoConvertRunnable implements Runnable {
|
|
|
|
|
2020-01-01 19:32:12 +01:00
|
|
|
private VideoConvertMessage convertMessage;
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2020-01-01 19:32:12 +01:00
|
|
|
private VideoConvertRunnable(VideoConvertMessage message) {
|
|
|
|
convertMessage = message;
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void run() {
|
2020-01-01 19:32:12 +01:00
|
|
|
MediaController.getInstance().convertVideo(convertMessage);
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
|
2020-01-01 19:32:12 +01:00
|
|
|
public static void runConversion(final VideoConvertMessage obj) {
|
2019-01-23 18:03:33 +01:00
|
|
|
new Thread(() -> {
|
|
|
|
try {
|
|
|
|
VideoConvertRunnable wrapper = new VideoConvertRunnable(obj);
|
|
|
|
Thread th = new Thread(wrapper, "VideoConvertRunnable");
|
|
|
|
th.start();
|
|
|
|
th.join();
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
|
|
|
}).start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-01-01 19:32:12 +01:00
|
|
|
private boolean convertVideo(final VideoConvertMessage convertMessage) {
|
|
|
|
MessageObject messageObject = convertMessage.messageObject;
|
|
|
|
VideoEditedInfo info = convertMessage.videoEditedInfo;
|
2019-12-31 20:46:59 +01:00
|
|
|
if (messageObject == null || info == null) {
|
2019-01-23 18:03:33 +01:00
|
|
|
return false;
|
|
|
|
}
|
2019-12-31 20:46:59 +01:00
|
|
|
String videoPath = info.originalPath;
|
|
|
|
long startTime = info.startTime;
|
2020-07-26 10:03:38 +02:00
|
|
|
long avatarStartTime = info.avatarStartTime;
|
2019-12-31 20:46:59 +01:00
|
|
|
long endTime = info.endTime;
|
|
|
|
int resultWidth = info.resultWidth;
|
|
|
|
int resultHeight = info.resultHeight;
|
|
|
|
int rotationValue = info.rotationValue;
|
|
|
|
int originalWidth = info.originalWidth;
|
|
|
|
int originalHeight = info.originalHeight;
|
|
|
|
int framerate = info.framerate;
|
|
|
|
int bitrate = info.bitrate;
|
2020-07-26 10:03:38 +02:00
|
|
|
int originalBitrate = info.originalBitrate;
|
2018-07-30 04:07:02 +02:00
|
|
|
boolean isSecret = ((int) messageObject.getDialogId()) == 0;
|
2019-12-31 14:08:08 +01:00
|
|
|
final File cacheFile = new File(messageObject.messageOwner.attachPath);
|
|
|
|
if (cacheFile.exists()) {
|
|
|
|
cacheFile.delete();
|
|
|
|
}
|
2020-07-26 10:03:38 +02:00
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
|
|
FileLog.d("begin convert " + videoPath + " startTime = " + startTime + " avatarStartTime = " + avatarStartTime + " endTime " + endTime + " rWidth = " + resultWidth + " rHeight = " + resultHeight + " rotation = " + rotationValue + " oWidth = " + originalWidth + " oHeight = " + originalHeight + " framerate = " + framerate + " bitrate = " + bitrate + " originalBitrate = " + originalBitrate);
|
|
|
|
}
|
2019-12-31 14:08:08 +01:00
|
|
|
|
2018-07-30 04:07:02 +02:00
|
|
|
if (videoPath == null) {
|
|
|
|
videoPath = "";
|
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
long duration;
|
|
|
|
if (startTime > 0 && endTime > 0) {
|
|
|
|
duration = endTime - startTime;
|
|
|
|
} else if (endTime > 0) {
|
|
|
|
duration = endTime;
|
|
|
|
} else if (startTime > 0) {
|
2019-12-31 20:46:59 +01:00
|
|
|
duration = info.originalDuration - startTime;
|
2019-12-31 14:08:08 +01:00
|
|
|
} else {
|
2019-12-31 20:46:59 +01:00
|
|
|
duration = info.originalDuration;
|
2019-12-31 14:08:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (framerate == 0) {
|
|
|
|
framerate = 25;
|
2020-08-14 18:58:22 +02:00
|
|
|
}/* else if (framerate > 59) {
|
2019-12-31 14:08:08 +01:00
|
|
|
framerate = 59;
|
2020-08-14 18:58:22 +02:00
|
|
|
}*/
|
2019-12-31 14:08:08 +01:00
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
if (rotationValue == 90 || rotationValue == 270) {
|
2019-12-31 14:08:08 +01:00
|
|
|
int temp = resultHeight;
|
|
|
|
resultHeight = resultWidth;
|
|
|
|
resultWidth = temp;
|
2014-09-30 00:48:11 +02:00
|
|
|
}
|
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
boolean needCompress = avatarStartTime != -1 || info.cropState != null || info.mediaEntities != null || info.paintPath != null || info.filterState != null ||
|
|
|
|
resultWidth != originalWidth || resultHeight != originalHeight || rotationValue != 0 || info.roundVideo || startTime != -1;
|
2019-12-31 14:08:08 +01:00
|
|
|
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("videoconvert", Activity.MODE_PRIVATE);
|
2014-09-28 15:37:26 +02:00
|
|
|
|
|
|
|
long time = System.currentTimeMillis();
|
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
VideoConvertorListener callback = new VideoConvertorListener() {
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2020-07-26 10:03:38 +02:00
|
|
|
private long lastAvailableSize = 0;
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
@Override
|
|
|
|
public boolean checkConversionCanceled() {
|
2019-12-31 20:46:59 +01:00
|
|
|
return info.canceled;
|
2019-12-31 14:08:08 +01:00
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
@Override
|
|
|
|
public void didWriteData(long availableSize, float progress) {
|
2019-12-31 20:46:59 +01:00
|
|
|
if (info.canceled) {
|
|
|
|
return;
|
|
|
|
}
|
2019-12-31 14:08:08 +01:00
|
|
|
if (availableSize < 0) {
|
|
|
|
availableSize = cacheFile.length();
|
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 20:46:59 +01:00
|
|
|
if (!info.needUpdateProgress && lastAvailableSize == availableSize) {
|
2019-12-31 14:08:08 +01:00
|
|
|
return;
|
|
|
|
}
|
2018-07-30 04:07:02 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
lastAvailableSize = availableSize;
|
2020-07-26 10:03:38 +02:00
|
|
|
MediaController.this.didWriteData(convertMessage, cacheFile, false, 0, availableSize, false, progress);
|
2019-12-31 14:08:08 +01:00
|
|
|
}
|
|
|
|
};
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 20:46:59 +01:00
|
|
|
info.videoConvertFirstWrite = true;
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
MediaCodecVideoConvertor videoConvertor = new MediaCodecVideoConvertor();
|
|
|
|
boolean error = videoConvertor.convertVideo(videoPath, cacheFile,
|
|
|
|
rotationValue, isSecret,
|
|
|
|
resultWidth, resultHeight,
|
2020-07-26 10:03:38 +02:00
|
|
|
framerate, bitrate, originalBitrate,
|
|
|
|
startTime, endTime, avatarStartTime,
|
2019-12-31 14:08:08 +01:00
|
|
|
needCompress, duration,
|
2020-06-04 18:47:15 +02:00
|
|
|
info.filterState,
|
|
|
|
info.paintPath,
|
|
|
|
info.mediaEntities,
|
|
|
|
info.isPhoto,
|
2020-07-26 10:03:38 +02:00
|
|
|
info.cropState,
|
2019-12-31 14:08:08 +01:00
|
|
|
callback);
|
2014-09-28 15:37:26 +02:00
|
|
|
|
|
|
|
|
2019-12-31 20:46:59 +01:00
|
|
|
boolean canceled = info.canceled;
|
2019-12-31 14:08:08 +01:00
|
|
|
if (!canceled) {
|
|
|
|
synchronized (videoConvertSync) {
|
2019-12-31 20:46:59 +01:00
|
|
|
canceled = info.canceled;
|
2019-12-31 14:08:08 +01:00
|
|
|
}
|
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
|
|
FileLog.d("time=" + (System.currentTimeMillis() - time) + " canceled=" + canceled);
|
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
preferences.edit().putBoolean("isPreviousOk", true).apply();
|
2020-07-26 10:03:38 +02:00
|
|
|
didWriteData(convertMessage, cacheFile, true, videoConvertor.getLastFrameTimestamp(), cacheFile.length(), error || canceled, 1f);
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
return true;
|
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
public static int getVideoBitrate(String path) {
|
|
|
|
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
|
|
|
int bitrate = 0;
|
|
|
|
try {
|
|
|
|
retriever.setDataSource(path);
|
|
|
|
bitrate = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE));
|
|
|
|
} catch (Exception e) {
|
|
|
|
FileLog.e(e);
|
|
|
|
}
|
2014-09-28 15:37:26 +02:00
|
|
|
|
2019-12-31 14:08:08 +01:00
|
|
|
retriever.release();
|
|
|
|
return bitrate;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int makeVideoBitrate(int originalHeight, int originalWidth, int originalBitrate, int height, int width) {
|
|
|
|
float compressFactor;
|
|
|
|
float minCompressFactor;
|
|
|
|
int maxBitrate;
|
|
|
|
if (Math.min(height, width) >= 1080) {
|
|
|
|
maxBitrate = 6800_000;
|
|
|
|
compressFactor = 1f;
|
|
|
|
minCompressFactor = 1f;
|
|
|
|
} else if (Math.min(height, width) >= 720) {
|
|
|
|
maxBitrate = 2621_440;
|
|
|
|
compressFactor = 1f;
|
|
|
|
minCompressFactor = 1f;
|
|
|
|
} else if (Math.min(height, width) >= 480) {
|
|
|
|
maxBitrate = 1000_000;
|
|
|
|
compressFactor = 0.8f;
|
|
|
|
minCompressFactor = 0.9f;
|
2014-09-28 15:37:26 +02:00
|
|
|
} else {
|
2019-12-31 14:08:08 +01:00
|
|
|
maxBitrate = 750_000;
|
|
|
|
compressFactor = 0.6f;
|
|
|
|
minCompressFactor = 0.7f;
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
2019-12-31 14:08:08 +01:00
|
|
|
int remeasuredBitrate = (int) (originalBitrate / (Math.min(originalHeight / (float) (height), originalWidth / (float) (width))));
|
|
|
|
remeasuredBitrate *= compressFactor;
|
|
|
|
int minBitrate = (int) (getVideoBitrateWithFactor(minCompressFactor) / (1280f * 720f / (width * height)));
|
2020-06-04 18:47:15 +02:00
|
|
|
if (originalBitrate < minBitrate) {
|
|
|
|
return remeasuredBitrate;
|
|
|
|
}
|
|
|
|
if (remeasuredBitrate > maxBitrate) {
|
|
|
|
return maxBitrate;
|
|
|
|
}
|
|
|
|
return Math.max(remeasuredBitrate, minBitrate);
|
2019-12-31 14:08:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private static int getVideoBitrateWithFactor(float f) {
|
|
|
|
return (int) (f * 2000f * 1000f * 1.13f);
|
|
|
|
}
|
|
|
|
|
|
|
|
public interface VideoConvertorListener {
|
|
|
|
boolean checkConversionCanceled();
|
2020-07-26 10:03:38 +02:00
|
|
|
void didWriteData(long availableSize, float progress);
|
2014-09-28 15:37:26 +02:00
|
|
|
}
|
2020-09-30 15:48:47 +02:00
|
|
|
|
|
|
|
public static class PlaylistGlobalSearchParams {
|
|
|
|
final String query;
|
|
|
|
final FiltersView.MediaFilterData filter;
|
|
|
|
final int dialogId;
|
|
|
|
final long minDate;
|
|
|
|
final long maxDate;
|
|
|
|
public int totalCount;
|
|
|
|
public boolean endReached;
|
|
|
|
public int nextSearchRate;
|
|
|
|
public int folderId;
|
|
|
|
|
|
|
|
public PlaylistGlobalSearchParams(String query, int dialogId, long minDate, long maxDate, FiltersView.MediaFilterData filter) {
|
|
|
|
this.filter = filter;
|
|
|
|
this.query = query;
|
|
|
|
this.dialogId = dialogId;
|
|
|
|
this.minDate = minDate;
|
|
|
|
this.maxDate = maxDate;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean currentPlaylistIsGlobalSearch() {
|
|
|
|
return playlistGlobalSearchParams != null;
|
|
|
|
}
|
2014-02-28 23:28:25 +01:00
|
|
|
}
|