mirror of https://github.com/procxx/kepka.git
audio player done
This commit is contained in:
parent
61a2a44584
commit
1268774517
|
@ -368,6 +368,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||||
"lng_profile_files_header" = "Files overview";
|
"lng_profile_files_header" = "Files overview";
|
||||||
"lng_profile_audios" = "{count:_not_used_|# voice message|# voice messages} »";
|
"lng_profile_audios" = "{count:_not_used_|# voice message|# voice messages} »";
|
||||||
"lng_profile_audios_header" = "Voice messages overview";
|
"lng_profile_audios_header" = "Voice messages overview";
|
||||||
|
"lng_profile_audio_files_header" = "Playlist";
|
||||||
"lng_profile_show_all_types" = "Show all types";
|
"lng_profile_show_all_types" = "Show all types";
|
||||||
"lng_profile_copy_phone" = "Copy phone number";
|
"lng_profile_copy_phone" = "Copy phone number";
|
||||||
|
|
||||||
|
@ -602,7 +603,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
"lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}";
|
"lng_new_version_wrap" = "Telegram Desktop was updated to version {version}\n\n{changes}\n\nFull version history is available here:\n{link}";
|
||||||
"lng_new_version_minor" = "— Bug fixes and other minor improvements";
|
"lng_new_version_minor" = "— Bug fixes and other minor improvements";
|
||||||
"lng_new_version_text" = "— Forward photos, media and stickers with drag-n-drop\n— Drag-n-drop text messages by timestamp to forward them\n— Larger stickers panel\n— IPv6 checkbox added to Connection Type in Settings";
|
"lng_new_version_text" = "— Improved in-app media playback\n— Bug fixes and other minor improvements";
|
||||||
|
|
||||||
"lng_menu_insert_unicode" = "Insert Unicode control character";
|
"lng_menu_insert_unicode" = "Insert Unicode control character";
|
||||||
|
|
||||||
|
|
|
@ -1971,3 +1971,29 @@ botDescSkip: 8px;
|
||||||
|
|
||||||
suppressAll: 0.2;
|
suppressAll: 0.2;
|
||||||
suppressSong: 0.05;
|
suppressSong: 0.05;
|
||||||
|
|
||||||
|
playerHeight: 44px;
|
||||||
|
playerBg: #e4e9ef;
|
||||||
|
playerFg: #54748f;
|
||||||
|
playerTimeFg: #a4afba;
|
||||||
|
playerLineHeight: 3px;
|
||||||
|
playerMoverSize: size(2px, 7px);
|
||||||
|
playerLineActive: #6389a8;
|
||||||
|
playerLineInactive: #bac7d4;
|
||||||
|
playerSkip: 8px;
|
||||||
|
playerNameStyle: textStyle(defaultTextStyle) {
|
||||||
|
lnkColor: #6389a8;
|
||||||
|
lnkDownColor: #6389a8;
|
||||||
|
lnkFlags: font(fsize semibold);
|
||||||
|
lnkOverFlags: font(fsize semibold);
|
||||||
|
}
|
||||||
|
playerPlay: sprite(377px, 109px, 19px, 22px);
|
||||||
|
playerPause: sprite(379px, 131px, 17px, 20px);
|
||||||
|
playerNext: sprite(374px, 151px, 22px, 14px);
|
||||||
|
playerPrev: sprite(374px, 165px, 22px, 14px);
|
||||||
|
playerClose: sprite(361px, 97px, 12px, 12px);
|
||||||
|
playerFull: sprite(365px, 109px, 12px, 12px);
|
||||||
|
playerVolume: sprite(352px, 179px, 44px, 12px);
|
||||||
|
playerInactiveOpacity: 0.8;
|
||||||
|
playerUnavailableOpacity: 0.3;
|
||||||
|
playerDuration: 200;
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 168 KiB |
Binary file not shown.
Before Width: | Height: | Size: 221 KiB After Width: | Height: | Size: 222 KiB |
|
@ -273,8 +273,9 @@ _loader(new AudioPlayerLoaders(&_loaderThread)) {
|
||||||
connect(this, SIGNAL(suppressSong()), _fader, SLOT(onSuppressSong()));
|
connect(this, SIGNAL(suppressSong()), _fader, SLOT(onSuppressSong()));
|
||||||
connect(this, SIGNAL(unsuppressSong()), _fader, SLOT(onUnsuppressSong()));
|
connect(this, SIGNAL(unsuppressSong()), _fader, SLOT(onUnsuppressSong()));
|
||||||
connect(this, SIGNAL(suppressAll()), _fader, SLOT(onSuppressAll()));
|
connect(this, SIGNAL(suppressAll()), _fader, SLOT(onSuppressAll()));
|
||||||
connect(this, SIGNAL(loaderOnStart(const AudioMsgId&)), _loader, SLOT(onStart(const AudioMsgId&)));
|
connect(this, SIGNAL(songVolumeChanged()), _fader, SLOT(onSongVolumeChanged()));
|
||||||
connect(this, SIGNAL(loaderOnStart(const SongMsgId&)), _loader, SLOT(onStart(const SongMsgId&)));
|
connect(this, SIGNAL(loaderOnStart(const AudioMsgId&,qint64)), _loader, SLOT(onStart(const AudioMsgId&,qint64)));
|
||||||
|
connect(this, SIGNAL(loaderOnStart(const SongMsgId&,qint64)), _loader, SLOT(onStart(const SongMsgId&,qint64)));
|
||||||
connect(this, SIGNAL(loaderOnCancel(const AudioMsgId&)), _loader, SLOT(onCancel(const AudioMsgId&)));
|
connect(this, SIGNAL(loaderOnCancel(const AudioMsgId&)), _loader, SLOT(onCancel(const AudioMsgId&)));
|
||||||
connect(this, SIGNAL(loaderOnCancel(const SongMsgId&)), _loader, SLOT(onCancel(const SongMsgId&)));
|
connect(this, SIGNAL(loaderOnCancel(const SongMsgId&)), _loader, SLOT(onCancel(const SongMsgId&)));
|
||||||
connect(&_faderThread, SIGNAL(started()), _fader, SLOT(onInit()));
|
connect(&_faderThread, SIGNAL(started()), _fader, SLOT(onInit()));
|
||||||
|
@ -292,6 +293,8 @@ _loader(new AudioPlayerLoaders(&_loaderThread)) {
|
||||||
connect(_fader, SIGNAL(audioStopped(const SongMsgId&)), this, SLOT(onStopped(const SongMsgId&)));
|
connect(_fader, SIGNAL(audioStopped(const SongMsgId&)), this, SLOT(onStopped(const SongMsgId&)));
|
||||||
connect(_fader, SIGNAL(error(const AudioMsgId&)), this, SLOT(onError(const AudioMsgId&)));
|
connect(_fader, SIGNAL(error(const AudioMsgId&)), this, SLOT(onError(const AudioMsgId&)));
|
||||||
connect(_fader, SIGNAL(error(const SongMsgId&)), this, SLOT(onError(const SongMsgId&)));
|
connect(_fader, SIGNAL(error(const SongMsgId&)), this, SLOT(onError(const SongMsgId&)));
|
||||||
|
connect(this, SIGNAL(stoppedOnError(const AudioMsgId&)), this, SIGNAL(stopped(const AudioMsgId&)), Qt::QueuedConnection);
|
||||||
|
connect(this, SIGNAL(stoppedOnError(const SongMsgId&)), this, SIGNAL(stopped(const SongMsgId&)), Qt::QueuedConnection);
|
||||||
_loaderThread.start();
|
_loaderThread.start();
|
||||||
_faderThread.start();
|
_faderThread.start();
|
||||||
}
|
}
|
||||||
|
@ -335,12 +338,12 @@ AudioPlayer::~AudioPlayer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayer::onError(const AudioMsgId &audio) {
|
void AudioPlayer::onError(const AudioMsgId &audio) {
|
||||||
emit stopped(audio);
|
emit stoppedOnError(audio);
|
||||||
emit unsuppressSong();
|
emit unsuppressSong();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayer::onError(const SongMsgId &song) {
|
void AudioPlayer::onError(const SongMsgId &song) {
|
||||||
emit stopped(song);
|
emit stoppedOnError(song);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayer::onStopped(const AudioMsgId &audio) {
|
void AudioPlayer::onStopped(const AudioMsgId &audio) {
|
||||||
|
@ -366,20 +369,20 @@ bool AudioPlayer::updateCurrentStarted(MediaOverviewType type, int32 pos) {
|
||||||
} else {
|
} else {
|
||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
}
|
if (!_checkALError()) {
|
||||||
if (!_checkALError()) {
|
setStoppedState(data, AudioPlayerStoppedAtError);
|
||||||
data->state = AudioPlayerStopped;
|
switch (type) {
|
||||||
switch (type) {
|
case OverviewAudios: onError(_audioData[_audioCurrent].audio); break;
|
||||||
case OverviewAudios: onError(_audioData[_audioCurrent].audio); break;
|
case OverviewDocuments: onError(_songData[_songCurrent].song); break;
|
||||||
case OverviewDocuments: onError(_songData[_songCurrent].song); break;
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
data->started = data->position = pos + data->skipStart;
|
data->started = data->position = pos + data->skipStart;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AudioPlayer::startedOther(MediaOverviewType type, bool &fadedStart) {
|
bool AudioPlayer::fadedStop(MediaOverviewType type, bool *fadedStart) {
|
||||||
Msg *current = 0;
|
Msg *current = 0;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case OverviewAudios: current = &_audioData[_audioCurrent]; break;
|
case OverviewAudios: current = &_audioData[_audioCurrent]; break;
|
||||||
|
@ -393,20 +396,21 @@ bool AudioPlayer::startedOther(MediaOverviewType type, bool &fadedStart) {
|
||||||
case AudioPlayerPlaying:
|
case AudioPlayerPlaying:
|
||||||
current->state = AudioPlayerFinishing;
|
current->state = AudioPlayerFinishing;
|
||||||
updateCurrentStarted(type);
|
updateCurrentStarted(type);
|
||||||
fadedStart = true;
|
if (fadedStart) *fadedStart = true;
|
||||||
break;
|
break;
|
||||||
case AudioPlayerPausing:
|
case AudioPlayerPausing:
|
||||||
current->state = AudioPlayerFinishing;
|
current->state = AudioPlayerFinishing;
|
||||||
fadedStart = true;
|
if (fadedStart) *fadedStart = true;
|
||||||
break;
|
break;
|
||||||
case AudioPlayerPaused:
|
case AudioPlayerPaused:
|
||||||
current->state = AudioPlayerStopped;
|
case AudioPlayerPausedAtEnd:
|
||||||
|
setStoppedState(current);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayer::play(const AudioMsgId &audio) {
|
void AudioPlayer::play(const AudioMsgId &audio, int64 position) {
|
||||||
AudioMsgId stopped;
|
AudioMsgId stopped;
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&playerMutex);
|
QMutexLocker lock(&playerMutex);
|
||||||
|
@ -414,7 +418,7 @@ void AudioPlayer::play(const AudioMsgId &audio) {
|
||||||
bool fadedStart = false;
|
bool fadedStart = false;
|
||||||
AudioMsg *current = &_audioData[_audioCurrent];
|
AudioMsg *current = &_audioData[_audioCurrent];
|
||||||
if (current->audio != audio) {
|
if (current->audio != audio) {
|
||||||
if (startedOther(OverviewAudios, fadedStart)) {
|
if (fadedStop(OverviewAudios, &fadedStart)) {
|
||||||
stopped = current->audio;
|
stopped = current->audio;
|
||||||
}
|
}
|
||||||
if (current->audio) {
|
if (current->audio) {
|
||||||
|
@ -438,19 +442,19 @@ void AudioPlayer::play(const AudioMsgId &audio) {
|
||||||
current->fname = audio.audio->already(true);
|
current->fname = audio.audio->already(true);
|
||||||
current->data = audio.audio->data;
|
current->data = audio.audio->data;
|
||||||
if (current->fname.isEmpty() && current->data.isEmpty()) {
|
if (current->fname.isEmpty() && current->data.isEmpty()) {
|
||||||
current->state = AudioPlayerStopped;
|
setStoppedState(current, AudioPlayerStoppedAtError);
|
||||||
onError(audio);
|
onError(audio);
|
||||||
} else if (updateCurrentStarted(OverviewAudios, 0)) {
|
} else {
|
||||||
current->state = fadedStart ? AudioPlayerStarting : AudioPlayerPlaying;
|
current->state = fadedStart ? AudioPlayerStarting : AudioPlayerPlaying;
|
||||||
current->loading = true;
|
current->loading = true;
|
||||||
emit loaderOnStart(audio);
|
emit loaderOnStart(audio, position);
|
||||||
emit suppressSong();
|
emit suppressSong();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stopped) emit updated(stopped);
|
if (stopped) emit updated(stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayer::play(const SongMsgId &song) {
|
void AudioPlayer::play(const SongMsgId &song, int64 position) {
|
||||||
SongMsgId stopped;
|
SongMsgId stopped;
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&playerMutex);
|
QMutexLocker lock(&playerMutex);
|
||||||
|
@ -458,7 +462,7 @@ void AudioPlayer::play(const SongMsgId &song) {
|
||||||
bool fadedStart = false;
|
bool fadedStart = false;
|
||||||
SongMsg *current = &_songData[_songCurrent];
|
SongMsg *current = &_songData[_songCurrent];
|
||||||
if (current->song != song) {
|
if (current->song != song) {
|
||||||
if (startedOther(OverviewDocuments, fadedStart)) {
|
if (fadedStop(OverviewDocuments, &fadedStart)) {
|
||||||
stopped = current->song;
|
stopped = current->song;
|
||||||
}
|
}
|
||||||
if (current->song) {
|
if (current->song) {
|
||||||
|
@ -482,18 +486,38 @@ void AudioPlayer::play(const SongMsgId &song) {
|
||||||
current->fname = song.song->already(true);
|
current->fname = song.song->already(true);
|
||||||
current->data = song.song->data;
|
current->data = song.song->data;
|
||||||
if (current->fname.isEmpty() && current->data.isEmpty()) {
|
if (current->fname.isEmpty() && current->data.isEmpty()) {
|
||||||
current->state = AudioPlayerStopped;
|
setStoppedState(current);
|
||||||
onError(song);
|
if (!song.song->loader) {
|
||||||
} else if (updateCurrentStarted(OverviewDocuments, 0)) {
|
DocumentOpenLink::doOpen(song.song);
|
||||||
|
song.song->openOnSave = song.song->openOnSaveMsgId = 0;
|
||||||
|
if (song.song->loader) song.song->loader->start(true, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
current->state = fadedStart ? AudioPlayerStarting : AudioPlayerPlaying;
|
current->state = fadedStart ? AudioPlayerStarting : AudioPlayerPlaying;
|
||||||
current->loading = true;
|
current->loading = true;
|
||||||
emit loaderOnStart(song);
|
emit loaderOnStart(song, position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stopped) emit updated(stopped);
|
if (stopped) emit updated(stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayer::pauseresume(MediaOverviewType type) {
|
bool AudioPlayer::checkCurrentALError(MediaOverviewType type) {
|
||||||
|
if (_checkALError()) return true;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case OverviewAudios:
|
||||||
|
setStoppedState(&_audioData[_audioCurrent], AudioPlayerStoppedAtError);
|
||||||
|
onError(_audioData[_audioCurrent].audio);
|
||||||
|
break;
|
||||||
|
case OverviewDocuments:
|
||||||
|
setStoppedState(&_songData[_songCurrent], AudioPlayerStoppedAtError);
|
||||||
|
onError(_songData[_songCurrent].song);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioPlayer::pauseresume(MediaOverviewType type, bool fast) {
|
||||||
QMutexLocker lock(&playerMutex);
|
QMutexLocker lock(&playerMutex);
|
||||||
|
|
||||||
Msg *current = 0;
|
Msg *current = 0;
|
||||||
|
@ -505,21 +529,38 @@ void AudioPlayer::pauseresume(MediaOverviewType type) {
|
||||||
break;
|
break;
|
||||||
case OverviewDocuments:
|
case OverviewDocuments:
|
||||||
current = &_songData[_songCurrent];
|
current = &_songData[_songCurrent];
|
||||||
suppressGain = suppressSongGain;
|
suppressGain = suppressSongGain * cSongVolume();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (current->state) {
|
switch (current->state) {
|
||||||
case AudioPlayerPausing:
|
case AudioPlayerPausing:
|
||||||
case AudioPlayerPaused:
|
case AudioPlayerPaused:
|
||||||
|
case AudioPlayerPausedAtEnd: {
|
||||||
if (current->state == AudioPlayerPaused) {
|
if (current->state == AudioPlayerPaused) {
|
||||||
updateCurrentStarted(type);
|
updateCurrentStarted(type);
|
||||||
|
} else if (current->state == AudioPlayerPausedAtEnd) {
|
||||||
|
if (alIsSource(current->source)) {
|
||||||
|
alSourcei(current->source, AL_SAMPLE_OFFSET, qMax(current->position - current->skipStart, 0LL));
|
||||||
|
if (!checkCurrentALError(type)) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current->state = fast ? AudioPlayerPlaying : AudioPlayerResuming;
|
||||||
|
|
||||||
|
ALint state = AL_INITIAL;
|
||||||
|
alGetSourcei(current->source, AL_SOURCE_STATE, &state);
|
||||||
|
if (!checkCurrentALError(type)) return;
|
||||||
|
|
||||||
|
if (state != AL_PLAYING) {
|
||||||
|
audioPlayer()->resumeDevice();
|
||||||
|
|
||||||
|
alSourcef(current->source, AL_GAIN, suppressGain);
|
||||||
|
if (!checkCurrentALError(type)) return;
|
||||||
|
|
||||||
|
alSourcePlay(current->source);
|
||||||
|
if (!checkCurrentALError(type)) return;
|
||||||
}
|
}
|
||||||
current->state = AudioPlayerResuming;
|
|
||||||
resumeDevice();
|
|
||||||
alSourcef(current->source, AL_GAIN, suppressGain);
|
|
||||||
alSourcePlay(current->source);
|
|
||||||
if (type == OverviewAudios) emit suppressSong();
|
if (type == OverviewAudios) emit suppressSong();
|
||||||
break;
|
} break;
|
||||||
case AudioPlayerStarting:
|
case AudioPlayerStarting:
|
||||||
case AudioPlayerResuming:
|
case AudioPlayerResuming:
|
||||||
case AudioPlayerPlaying:
|
case AudioPlayerPlaying:
|
||||||
|
@ -532,6 +573,78 @@ void AudioPlayer::pauseresume(MediaOverviewType type) {
|
||||||
emit faderOnTimer();
|
emit faderOnTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioPlayer::seek(int64 position) {
|
||||||
|
QMutexLocker lock(&playerMutex);
|
||||||
|
|
||||||
|
MediaOverviewType type = OverviewDocuments;
|
||||||
|
Msg *current = 0;
|
||||||
|
float64 suppressGain = 1.;
|
||||||
|
AudioMsgId audio;
|
||||||
|
SongMsgId song;
|
||||||
|
switch (type) {
|
||||||
|
case OverviewAudios:
|
||||||
|
current = &_audioData[_audioCurrent];
|
||||||
|
audio = _audioData[_audioCurrent].audio;
|
||||||
|
suppressGain = suppressAllGain;
|
||||||
|
break;
|
||||||
|
case OverviewDocuments:
|
||||||
|
current = &_songData[_songCurrent];
|
||||||
|
song = _songData[_songCurrent].song;
|
||||||
|
suppressGain = suppressSongGain * cSongVolume();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSource = alIsSource(current->source);
|
||||||
|
bool fastSeek = (position >= current->skipStart && position < current->duration - current->skipEnd - (current->skipEnd ? AudioVoiceMsgFrequency : 0));
|
||||||
|
if (fastSeek && isSource) {
|
||||||
|
alSourcei(current->source, AL_SAMPLE_OFFSET, position - current->skipStart);
|
||||||
|
if (!checkCurrentALError(type)) return;
|
||||||
|
alSourcef(current->source, AL_GAIN, 1. * suppressGain);
|
||||||
|
if (!checkCurrentALError(type)) return;
|
||||||
|
updateCurrentStarted(type, position - current->skipStart);
|
||||||
|
} else {
|
||||||
|
setStoppedState(current);
|
||||||
|
if (isSource) alSourceStop(current->source);
|
||||||
|
}
|
||||||
|
switch (current->state) {
|
||||||
|
case AudioPlayerPausing:
|
||||||
|
case AudioPlayerPaused:
|
||||||
|
case AudioPlayerPausedAtEnd: {
|
||||||
|
if (current->state == AudioPlayerPausedAtEnd) {
|
||||||
|
current->state = AudioPlayerPaused;
|
||||||
|
}
|
||||||
|
lock.unlock();
|
||||||
|
return pauseresume(type, true);
|
||||||
|
} break;
|
||||||
|
case AudioPlayerStarting:
|
||||||
|
case AudioPlayerResuming:
|
||||||
|
case AudioPlayerPlaying:
|
||||||
|
current->state = AudioPlayerPausing;
|
||||||
|
updateCurrentStarted(type);
|
||||||
|
if (type == OverviewAudios) emit unsuppressSong();
|
||||||
|
break;
|
||||||
|
case AudioPlayerFinishing:
|
||||||
|
case AudioPlayerStopped:
|
||||||
|
case AudioPlayerStoppedAtEnd:
|
||||||
|
case AudioPlayerStoppedAtError:
|
||||||
|
case AudioPlayerStoppedAtStart:
|
||||||
|
lock.unlock();
|
||||||
|
switch (type) {
|
||||||
|
case OverviewAudios: if (audio) return play(audio, position);
|
||||||
|
case OverviewDocuments: if (song) return play(song, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit faderOnTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioPlayer::stop(MediaOverviewType type) {
|
||||||
|
fadedStop(type);
|
||||||
|
switch (type) {
|
||||||
|
case OverviewAudios: if (_audioData[_audioCurrent].audio) emit updated(_audioData[_audioCurrent].audio); break;
|
||||||
|
case OverviewDocuments: if (_songData[_songCurrent].song) emit updated(_songData[_songCurrent].song); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AudioPlayer::currentState(AudioMsgId *audio, AudioPlayerState *state, int64 *position, int64 *duration, int32 *frequency) {
|
void AudioPlayer::currentState(AudioMsgId *audio, AudioPlayerState *state, int64 *position, int64 *duration, int32 *frequency) {
|
||||||
QMutexLocker lock(&playerMutex);
|
QMutexLocker lock(&playerMutex);
|
||||||
AudioMsg *current = &_audioData[_audioCurrent];
|
AudioMsg *current = &_audioData[_audioCurrent];
|
||||||
|
@ -553,17 +666,22 @@ void AudioPlayer::currentState(Msg *current, AudioPlayerState *state, int64 *pos
|
||||||
if (frequency) *frequency = current->frequency;
|
if (frequency) *frequency = current->frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioPlayer::setStoppedState(Msg *current, AudioPlayerState state) {
|
||||||
|
current->state = state;
|
||||||
|
current->position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void AudioPlayer::clearStoppedAtStart(const AudioMsgId &audio) {
|
void AudioPlayer::clearStoppedAtStart(const AudioMsgId &audio) {
|
||||||
QMutexLocker lock(&playerMutex);
|
QMutexLocker lock(&playerMutex);
|
||||||
if (_audioData[_audioCurrent].audio == audio && _audioData[_audioCurrent].state == AudioPlayerStoppedAtStart) {
|
if (_audioData[_audioCurrent].audio == audio && _audioData[_audioCurrent].state == AudioPlayerStoppedAtStart) {
|
||||||
_audioData[_audioCurrent].state = AudioPlayerStopped;
|
setStoppedState(&_audioData[_audioCurrent]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayer::clearStoppedAtStart(const SongMsgId &song) {
|
void AudioPlayer::clearStoppedAtStart(const SongMsgId &song) {
|
||||||
QMutexLocker lock(&playerMutex);
|
QMutexLocker lock(&playerMutex);
|
||||||
if (_songData[_songCurrent].song == song && _songData[_songCurrent].state == AudioPlayerStoppedAtStart) {
|
if (_songData[_songCurrent].song == song && _songData[_songCurrent].state == AudioPlayerStoppedAtStart) {
|
||||||
_songData[_songCurrent].state = AudioPlayerStopped;
|
setStoppedState(&_songData[_songCurrent]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,7 +794,7 @@ void AudioPlayerFader::onTimer() {
|
||||||
|
|
||||||
for (int32 i = 0; i < AudioVoiceMsgSimultaneously; ++i) {
|
for (int32 i = 0; i < AudioVoiceMsgSimultaneously; ++i) {
|
||||||
AudioPlayer::AudioMsg &m(voice->_audioData[i]);
|
AudioPlayer::AudioMsg &m(voice->_audioData[i]);
|
||||||
if (m.state == AudioPlayerStopped || m.state == AudioPlayerStoppedAtStart || m.state == AudioPlayerPaused || !m.source) continue;
|
if ((m.state & AudioPlayerStoppedMask) || m.state == AudioPlayerPaused || !m.source) continue;
|
||||||
|
|
||||||
int32 emitSignals = updateOnePlayback(&m, hasPlaying, hasFading, suppressAllGain, suppressAudioChanged);
|
int32 emitSignals = updateOnePlayback(&m, hasPlaying, hasFading, suppressAllGain, suppressAudioChanged);
|
||||||
if (emitSignals & EmitError) emit error(m.audio);
|
if (emitSignals & EmitError) emit error(m.audio);
|
||||||
|
@ -687,14 +805,15 @@ void AudioPlayerFader::onTimer() {
|
||||||
|
|
||||||
for (int32 i = 0; i < AudioSongSimultaneously; ++i) {
|
for (int32 i = 0; i < AudioSongSimultaneously; ++i) {
|
||||||
AudioPlayer::SongMsg &m(voice->_songData[i]);
|
AudioPlayer::SongMsg &m(voice->_songData[i]);
|
||||||
if (m.state == AudioPlayerStopped || m.state == AudioPlayerStoppedAtStart || m.state == AudioPlayerPaused || !m.source) continue;
|
if ((m.state & AudioPlayerStoppedMask) || m.state == AudioPlayerPaused || !m.source) continue;
|
||||||
|
|
||||||
int32 emitSignals = updateOnePlayback(&m, hasPlaying, hasFading, suppressSongGain, suppressSongChanged);
|
int32 emitSignals = updateOnePlayback(&m, hasPlaying, hasFading, suppressSongGain * cSongVolume(), suppressSongChanged || _songVolumeChanged);
|
||||||
if (emitSignals & EmitError) emit error(m.song);
|
if (emitSignals & EmitError) emit error(m.song);
|
||||||
if (emitSignals & EmitStopped) emit audioStopped(m.song);
|
if (emitSignals & EmitStopped) emit audioStopped(m.song);
|
||||||
if (emitSignals & EmitPositionUpdated) emit playPositionUpdated(m.song);
|
if (emitSignals & EmitPositionUpdated) emit playPositionUpdated(m.song);
|
||||||
if (emitSignals & EmitNeedToPreload) emit needToPreload(m.song);
|
if (emitSignals & EmitNeedToPreload) emit needToPreload(m.song);
|
||||||
}
|
}
|
||||||
|
_songVolumeChanged = false;
|
||||||
|
|
||||||
if (!hasFading) {
|
if (!hasFading) {
|
||||||
if (!hasPlaying) {
|
if (!hasPlaying) {
|
||||||
|
@ -724,11 +843,9 @@ int32 AudioPlayerFader::updateOnePlayback(AudioPlayer::Msg *m, bool &hasPlaying,
|
||||||
ALint pos = 0;
|
ALint pos = 0;
|
||||||
ALint state = AL_INITIAL;
|
ALint state = AL_INITIAL;
|
||||||
alGetSourcei(m->source, AL_SAMPLE_OFFSET, &pos);
|
alGetSourcei(m->source, AL_SAMPLE_OFFSET, &pos);
|
||||||
|
if (!_checkALError()) { setStoppedState(m, AudioPlayerStoppedAtError); return EmitError; }
|
||||||
alGetSourcei(m->source, AL_SOURCE_STATE, &state);
|
alGetSourcei(m->source, AL_SOURCE_STATE, &state);
|
||||||
if (!_checkALError()) {
|
if (!_checkALError()) { setStoppedState(m, AudioPlayerStoppedAtError); return EmitError; }
|
||||||
m->state = AudioPlayerStopped;
|
|
||||||
return EmitError;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 emitSignals = 0;
|
int32 emitSignals = 0;
|
||||||
switch (m->state) {
|
switch (m->state) {
|
||||||
|
@ -746,17 +863,33 @@ int32 AudioPlayerFader::updateOnePlayback(AudioPlayer::Msg *m, bool &hasPlaying,
|
||||||
if (state != AL_PLAYING) {
|
if (state != AL_PLAYING) {
|
||||||
fading = false;
|
fading = false;
|
||||||
if (m->source) {
|
if (m->source) {
|
||||||
alSourcef(m->source, AL_GAIN, 1);
|
|
||||||
alSourceStop(m->source);
|
alSourceStop(m->source);
|
||||||
|
if (!_checkALError()) { setStoppedState(m, AudioPlayerStoppedAtError); return EmitError; }
|
||||||
|
alSourcef(m->source, AL_GAIN, 1);
|
||||||
|
if (!_checkALError()) { setStoppedState(m, AudioPlayerStoppedAtError); return EmitError; }
|
||||||
|
}
|
||||||
|
if (m->state == AudioPlayerPausing) {
|
||||||
|
m->state = AudioPlayerPausedAtEnd;
|
||||||
|
} else {
|
||||||
|
setStoppedState(m, AudioPlayerStoppedAtEnd);
|
||||||
}
|
}
|
||||||
m->state = AudioPlayerStopped;
|
|
||||||
emitSignals |= EmitStopped;
|
emitSignals |= EmitStopped;
|
||||||
} else if (1000 * (pos + m->skipStart - m->started) >= AudioFadeDuration * m->frequency) {
|
} else if (1000 * (pos + m->skipStart - m->started) >= AudioFadeDuration * m->frequency) {
|
||||||
fading = false;
|
fading = false;
|
||||||
alSourcef(m->source, AL_GAIN, 1. * suppressGain);
|
alSourcef(m->source, AL_GAIN, 1. * suppressGain);
|
||||||
|
if (!_checkALError()) { setStoppedState(m, AudioPlayerStoppedAtError); return EmitError; }
|
||||||
switch (m->state) {
|
switch (m->state) {
|
||||||
case AudioPlayerFinishing: alSourceStop(m->source); m->state = AudioPlayerStopped; break;
|
case AudioPlayerFinishing:
|
||||||
case AudioPlayerPausing: alSourcePause(m->source); m->state = AudioPlayerPaused; break;
|
alSourceStop(m->source);
|
||||||
|
if (!_checkALError()) { setStoppedState(m, AudioPlayerStoppedAtError); return EmitError; }
|
||||||
|
setStoppedState(m);
|
||||||
|
state = AL_STOPPED;
|
||||||
|
break;
|
||||||
|
case AudioPlayerPausing:
|
||||||
|
alSourcePause(m->source);
|
||||||
|
if (!_checkALError()) { setStoppedState(m, AudioPlayerStoppedAtError); return EmitError; }
|
||||||
|
m->state = AudioPlayerPaused;
|
||||||
|
break;
|
||||||
case AudioPlayerStarting:
|
case AudioPlayerStarting:
|
||||||
case AudioPlayerResuming:
|
case AudioPlayerResuming:
|
||||||
m->state = AudioPlayerPlaying;
|
m->state = AudioPlayerPlaying;
|
||||||
|
@ -769,18 +902,22 @@ int32 AudioPlayerFader::updateOnePlayback(AudioPlayer::Msg *m, bool &hasPlaying,
|
||||||
newGain = 1. - newGain;
|
newGain = 1. - newGain;
|
||||||
}
|
}
|
||||||
alSourcef(m->source, AL_GAIN, newGain * suppressGain);
|
alSourcef(m->source, AL_GAIN, newGain * suppressGain);
|
||||||
|
if (!_checkALError()) { setStoppedState(m, AudioPlayerStoppedAtError); return EmitError; }
|
||||||
}
|
}
|
||||||
} else if (playing && (state == AL_PLAYING || !m->loading)) {
|
} else if (playing && (state == AL_PLAYING || !m->loading)) {
|
||||||
if (state != AL_PLAYING) {
|
if (state != AL_PLAYING) {
|
||||||
playing = false;
|
playing = false;
|
||||||
if (m->source) {
|
if (m->source) {
|
||||||
alSourceStop(m->source);
|
alSourceStop(m->source);
|
||||||
|
if (!_checkALError()) { setStoppedState(m, AudioPlayerStoppedAtError); return EmitError; }
|
||||||
alSourcef(m->source, AL_GAIN, 1);
|
alSourcef(m->source, AL_GAIN, 1);
|
||||||
|
if (!_checkALError()) { setStoppedState(m, AudioPlayerStoppedAtError); return EmitError; }
|
||||||
}
|
}
|
||||||
m->state = AudioPlayerStopped;
|
setStoppedState(m, AudioPlayerStoppedAtEnd);
|
||||||
emitSignals |= EmitStopped;
|
emitSignals |= EmitStopped;
|
||||||
} else if (suppressGainChanged) {
|
} else if (suppressGainChanged) {
|
||||||
alSourcef(m->source, AL_GAIN, suppressGain);
|
alSourcef(m->source, AL_GAIN, suppressGain);
|
||||||
|
if (!_checkALError()) { setStoppedState(m, AudioPlayerStoppedAtError); return EmitError; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (state == AL_PLAYING && pos + m->skipStart - m->position >= AudioCheckPositionDelta) {
|
if (state == AL_PLAYING && pos + m->skipStart - m->position >= AudioCheckPositionDelta) {
|
||||||
|
@ -799,6 +936,11 @@ int32 AudioPlayerFader::updateOnePlayback(AudioPlayer::Msg *m, bool &hasPlaying,
|
||||||
return emitSignals;
|
return emitSignals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioPlayerFader::setStoppedState(AudioPlayer::Msg *m, AudioPlayerState state) {
|
||||||
|
m->state = state;
|
||||||
|
m->position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void AudioPlayerFader::onPauseTimer() {
|
void AudioPlayerFader::onPauseTimer() {
|
||||||
QMutexLocker lock(&_pauseMutex);
|
QMutexLocker lock(&_pauseMutex);
|
||||||
if (_pauseFlag) {
|
if (_pauseFlag) {
|
||||||
|
@ -838,6 +980,11 @@ void AudioPlayerFader::onSuppressAll() {
|
||||||
onTimer();
|
onTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioPlayerFader::onSongVolumeChanged() {
|
||||||
|
_songVolumeChanged = true;
|
||||||
|
onTimer();
|
||||||
|
}
|
||||||
|
|
||||||
void AudioPlayerFader::resumeDevice() {
|
void AudioPlayerFader::resumeDevice() {
|
||||||
QMutexLocker lock(&_pauseMutex);
|
QMutexLocker lock(&_pauseMutex);
|
||||||
_pauseFlag = false;
|
_pauseFlag = false;
|
||||||
|
@ -859,7 +1006,7 @@ public:
|
||||||
return this->fname == fname && this->data.size() == data.size();
|
return this->fname == fname && this->data.size() == data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool open() = 0;
|
virtual bool open(qint64 position = 0) = 0;
|
||||||
virtual int64 duration() = 0;
|
virtual int64 duration() = 0;
|
||||||
virtual int32 frequency() = 0;
|
virtual int32 frequency() = 0;
|
||||||
virtual int32 format() = 0;
|
virtual int32 format() = 0;
|
||||||
|
@ -904,7 +1051,7 @@ public:
|
||||||
frame = av_frame_alloc();
|
frame = av_frame_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool open() {
|
bool open(qint64 position = 0) {
|
||||||
if (!AudioPlayerLoader::openFile()) {
|
if (!AudioPlayerLoader::openFile()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -950,7 +1097,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
freq = fmtContext->streams[streamId]->codec->sample_rate;
|
freq = fmtContext->streams[streamId]->codec->sample_rate;
|
||||||
len = (fmtContext->streams[streamId]->duration * freq) / fmtContext->streams[streamId]->time_base.den;
|
len = (fmtContext->streams[streamId]->duration * freq * fmtContext->streams[streamId]->time_base.num) / fmtContext->streams[streamId]->time_base.den;
|
||||||
uint64_t layout = fmtContext->streams[streamId]->codec->channel_layout;
|
uint64_t layout = fmtContext->streams[streamId]->codec->channel_layout;
|
||||||
inputFormat = fmtContext->streams[streamId]->codec->sample_fmt;
|
inputFormat = fmtContext->streams[streamId]->codec->sample_fmt;
|
||||||
switch (layout) {
|
switch (layout) {
|
||||||
|
@ -1016,6 +1163,16 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (position) {
|
||||||
|
int64 ts = (position * fmtContext->streams[streamId]->time_base.den) / (freq * fmtContext->streams[streamId]->time_base.num);
|
||||||
|
if (av_seek_frame(fmtContext, streamId, ts, AVSEEK_FLAG_ANY) < 0) {
|
||||||
|
if (av_seek_frame(fmtContext, streamId, ts, 0) < 0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (dstSamplesData) {
|
||||||
|
// position = qRound(srcRate * (position / float64(dstRate)));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1180,18 +1337,18 @@ AudioPlayerLoaders::~AudioPlayerLoaders() {
|
||||||
void AudioPlayerLoaders::onInit() {
|
void AudioPlayerLoaders::onInit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayerLoaders::onStart(const AudioMsgId &audio) {
|
void AudioPlayerLoaders::onStart(const AudioMsgId &audio, qint64 position) {
|
||||||
_audio = AudioMsgId();
|
_audio = AudioMsgId();
|
||||||
delete _audioLoader;
|
delete _audioLoader;
|
||||||
_audioLoader = 0;
|
_audioLoader = 0;
|
||||||
onLoad(audio);
|
loadData(OverviewAudios, static_cast<const void*>(&audio), position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayerLoaders::onStart(const SongMsgId &song) {
|
void AudioPlayerLoaders::onStart(const SongMsgId &song, qint64 position) {
|
||||||
_song = SongMsgId();
|
_song = SongMsgId();
|
||||||
delete _songLoader;
|
delete _songLoader;
|
||||||
_songLoader = 0;
|
_songLoader = 0;
|
||||||
onLoad(song);
|
loadData(OverviewDocuments, static_cast<const void*>(&song), position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayerLoaders::clear(MediaOverviewType type) {
|
void AudioPlayerLoaders::clear(MediaOverviewType type) {
|
||||||
|
@ -1201,6 +1358,11 @@ void AudioPlayerLoaders::clear(MediaOverviewType type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioPlayerLoaders::setStoppedState(AudioPlayer::Msg *m, AudioPlayerState state) {
|
||||||
|
m->state = state;
|
||||||
|
m->position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void AudioPlayerLoaders::emitError(MediaOverviewType type) {
|
void AudioPlayerLoaders::emitError(MediaOverviewType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case OverviewAudios: emit error(clearAudio()); break;
|
case OverviewAudios: emit error(clearAudio()); break;
|
||||||
|
@ -1225,16 +1387,16 @@ SongMsgId AudioPlayerLoaders::clearSong() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayerLoaders::onLoad(const AudioMsgId &audio) {
|
void AudioPlayerLoaders::onLoad(const AudioMsgId &audio) {
|
||||||
loadData(OverviewAudios, static_cast<const void*>(&audio));
|
loadData(OverviewAudios, static_cast<const void*>(&audio), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayerLoaders::onLoad(const SongMsgId &song) {
|
void AudioPlayerLoaders::onLoad(const SongMsgId &song) {
|
||||||
loadData(OverviewDocuments, static_cast<const void*>(&song));
|
loadData(OverviewDocuments, static_cast<const void*>(&song), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioPlayerLoaders::loadData(MediaOverviewType type, const void *objId) {
|
void AudioPlayerLoaders::loadData(MediaOverviewType type, const void *objId, qint64 position) {
|
||||||
SetupError err = SetupNoErrorStarted;
|
SetupError err = SetupNoErrorStarted;
|
||||||
AudioPlayerLoader *l = setupLoader(type, objId, err);
|
AudioPlayerLoader *l = setupLoader(type, objId, err, position);
|
||||||
if (!l) {
|
if (!l) {
|
||||||
if (err == SetupErrorAtStart) {
|
if (err == SetupErrorAtStart) {
|
||||||
emitError(type);
|
emitError(type);
|
||||||
|
@ -1277,19 +1439,22 @@ void AudioPlayerLoaders::loadData(MediaOverviewType type, const void *objId) {
|
||||||
}
|
}
|
||||||
m->nextBuffer = 0;
|
m->nextBuffer = 0;
|
||||||
}
|
}
|
||||||
|
m->skipStart = position;
|
||||||
|
m->skipEnd = m->duration - position;
|
||||||
|
m->position = 0;
|
||||||
|
m->started = 0;
|
||||||
}
|
}
|
||||||
if (samplesAdded) {
|
if (samplesAdded) {
|
||||||
if (!m->source) {
|
if (!m->source) {
|
||||||
alGenSources(1, &m->source);
|
alGenSources(1, &m->source);
|
||||||
alSourcef(m->source, AL_PITCH, 1.f);
|
alSourcef(m->source, AL_PITCH, 1.f);
|
||||||
alSourcef(m->source, AL_GAIN, 1.f);
|
|
||||||
alSource3f(m->source, AL_POSITION, 0, 0, 0);
|
alSource3f(m->source, AL_POSITION, 0, 0, 0);
|
||||||
alSource3f(m->source, AL_VELOCITY, 0, 0, 0);
|
alSource3f(m->source, AL_VELOCITY, 0, 0, 0);
|
||||||
alSourcei(m->source, AL_LOOPING, 0);
|
alSourcei(m->source, AL_LOOPING, 0);
|
||||||
}
|
}
|
||||||
if (!m->buffers[m->nextBuffer]) alGenBuffers(3, m->buffers);
|
if (!m->buffers[m->nextBuffer]) alGenBuffers(3, m->buffers);
|
||||||
if (!_checkALError()) {
|
if (!_checkALError()) {
|
||||||
m->state = AudioPlayerStopped;
|
setStoppedState(m, AudioPlayerStoppedAtError);
|
||||||
emitError(type);
|
emitError(type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1307,7 +1472,7 @@ void AudioPlayerLoaders::loadData(MediaOverviewType type, const void *objId) {
|
||||||
m->nextBuffer = (m->nextBuffer + 1) % 3;
|
m->nextBuffer = (m->nextBuffer + 1) % 3;
|
||||||
|
|
||||||
if (!_checkALError()) {
|
if (!_checkALError()) {
|
||||||
m->state = AudioPlayerStopped;
|
setStoppedState(m, AudioPlayerStoppedAtError);
|
||||||
emitError(type);
|
emitError(type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1326,18 +1491,34 @@ void AudioPlayerLoaders::loadData(MediaOverviewType type, const void *objId) {
|
||||||
if (_checkALError()) {
|
if (_checkALError()) {
|
||||||
if (state != AL_PLAYING) {
|
if (state != AL_PLAYING) {
|
||||||
audioPlayer()->resumeDevice();
|
audioPlayer()->resumeDevice();
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case OverviewAudios: alSourcef(m->source, AL_GAIN, suppressAllGain); break;
|
case OverviewAudios: alSourcef(m->source, AL_GAIN, suppressAllGain); break;
|
||||||
case OverviewDocuments: alSourcef(m->source, AL_GAIN, suppressSongGain); break;
|
case OverviewDocuments: alSourcef(m->source, AL_GAIN, suppressSongGain * cSongVolume()); break;
|
||||||
}
|
}
|
||||||
|
if (!_checkALError()) {
|
||||||
|
setStoppedState(m, AudioPlayerStoppedAtError);
|
||||||
|
emitError(type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
alSourcePlay(m->source);
|
alSourcePlay(m->source);
|
||||||
|
if (!_checkALError()) {
|
||||||
|
setStoppedState(m, AudioPlayerStoppedAtError);
|
||||||
|
emitError(type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
emit needToCheck();
|
emit needToCheck();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
setStoppedState(m, AudioPlayerStoppedAtError);
|
||||||
|
emitError(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioPlayerLoader *AudioPlayerLoaders::setupLoader(MediaOverviewType type, const void *objId, SetupError &err) {
|
AudioPlayerLoader *AudioPlayerLoaders::setupLoader(MediaOverviewType type, const void *objId, SetupError &err, qint64 position) {
|
||||||
err = SetupErrorAtStart;
|
err = SetupErrorAtStart;
|
||||||
QMutexLocker lock(&playerMutex);
|
QMutexLocker lock(&playerMutex);
|
||||||
AudioPlayer *voice = audioPlayer();
|
AudioPlayer *voice = audioPlayer();
|
||||||
|
@ -1410,7 +1591,7 @@ AudioPlayerLoader *AudioPlayerLoaders::setupLoader(MediaOverviewType type, const
|
||||||
*l = new FFMpegLoader(m->fname, m->data);
|
*l = new FFMpegLoader(m->fname, m->data);
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
if (!(*l)->open()) {
|
if (!(*l)->open(position)) {
|
||||||
m->state = AudioPlayerStoppedAtStart;
|
m->state = AudioPlayerStoppedAtStart;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1422,10 +1603,6 @@ AudioPlayerLoader *AudioPlayerLoaders::setupLoader(MediaOverviewType type, const
|
||||||
m->duration = duration;
|
m->duration = duration;
|
||||||
m->frequency = (*l)->frequency();
|
m->frequency = (*l)->frequency();
|
||||||
if (!m->frequency) m->frequency = AudioVoiceMsgFrequency;
|
if (!m->frequency) m->frequency = AudioVoiceMsgFrequency;
|
||||||
m->skipStart = 0;
|
|
||||||
m->skipEnd = duration;
|
|
||||||
m->position = 0;
|
|
||||||
m->started = 0;
|
|
||||||
err = SetupNoErrorStarted;
|
err = SetupNoErrorStarted;
|
||||||
} else {
|
} else {
|
||||||
if (!m->skipEnd) {
|
if (!m->skipEnd) {
|
||||||
|
@ -1985,7 +2162,7 @@ public:
|
||||||
_opened(false) {
|
_opened(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool open() {
|
bool open(qint64 position = 0) {
|
||||||
if (!AudioPlayerLoader::openFile()) {
|
if (!AudioPlayerLoader::openFile()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,19 @@ void audioPlayNotify();
|
||||||
void audioFinish();
|
void audioFinish();
|
||||||
|
|
||||||
enum AudioPlayerState {
|
enum AudioPlayerState {
|
||||||
AudioPlayerStopped,
|
AudioPlayerStopped = 0x01,
|
||||||
AudioPlayerStoppedAtStart,
|
AudioPlayerStoppedAtEnd = 0x02,
|
||||||
AudioPlayerStarting,
|
AudioPlayerStoppedAtError = 0x03,
|
||||||
AudioPlayerPlaying,
|
AudioPlayerStoppedAtStart = 0x04,
|
||||||
AudioPlayerFinishing,
|
AudioPlayerStoppedMask = 0x07,
|
||||||
AudioPlayerPausing,
|
|
||||||
AudioPlayerPaused,
|
AudioPlayerStarting = 0x08,
|
||||||
AudioPlayerResuming,
|
AudioPlayerPlaying = 0x10,
|
||||||
|
AudioPlayerFinishing = 0x18,
|
||||||
|
AudioPlayerPausing = 0x20,
|
||||||
|
AudioPlayerPaused = 0x28,
|
||||||
|
AudioPlayerPausedAtEnd = 0x30,
|
||||||
|
AudioPlayerResuming = 0x38,
|
||||||
};
|
};
|
||||||
|
|
||||||
class AudioPlayerFader;
|
class AudioPlayerFader;
|
||||||
|
@ -45,9 +50,11 @@ public:
|
||||||
|
|
||||||
AudioPlayer();
|
AudioPlayer();
|
||||||
|
|
||||||
void play(const AudioMsgId &audio);
|
void play(const AudioMsgId &audio, int64 position = 0);
|
||||||
void play(const SongMsgId &song);
|
void play(const SongMsgId &song, int64 position = 0);
|
||||||
void pauseresume(MediaOverviewType type);
|
void pauseresume(MediaOverviewType type, bool fast = false);
|
||||||
|
void seek(int64 position); // type == OverviewDocuments
|
||||||
|
void stop(MediaOverviewType type);
|
||||||
|
|
||||||
void currentState(AudioMsgId *audio, AudioPlayerState *state = 0, int64 *position = 0, int64 *duration = 0, int32 *frequency = 0);
|
void currentState(AudioMsgId *audio, AudioPlayerState *state = 0, int64 *position = 0, int64 *duration = 0, int32 *frequency = 0);
|
||||||
void currentState(SongMsgId *song, AudioPlayerState *state = 0, int64 *position = 0, int64 *duration = 0, int32 *frequency = 0);
|
void currentState(SongMsgId *song, AudioPlayerState *state = 0, int64 *position = 0, int64 *duration = 0, int32 *frequency = 0);
|
||||||
|
@ -75,21 +82,28 @@ signals:
|
||||||
void stopped(const AudioMsgId &audio);
|
void stopped(const AudioMsgId &audio);
|
||||||
void stopped(const SongMsgId &song);
|
void stopped(const SongMsgId &song);
|
||||||
|
|
||||||
void loaderOnStart(const AudioMsgId &audio);
|
void stoppedOnError(const AudioMsgId &audio);
|
||||||
void loaderOnStart(const SongMsgId &song);
|
void stoppedOnError(const SongMsgId &song);
|
||||||
|
|
||||||
|
void loaderOnStart(const AudioMsgId &audio, qint64 position);
|
||||||
|
void loaderOnStart(const SongMsgId &song, qint64 position);
|
||||||
|
|
||||||
void loaderOnCancel(const AudioMsgId &audio);
|
void loaderOnCancel(const AudioMsgId &audio);
|
||||||
void loaderOnCancel(const SongMsgId &song);
|
void loaderOnCancel(const SongMsgId &song);
|
||||||
|
|
||||||
void faderOnTimer();
|
void faderOnTimer();
|
||||||
|
|
||||||
void suppressSong();
|
void suppressSong();
|
||||||
void unsuppressSong();
|
void unsuppressSong();
|
||||||
void suppressAll();
|
void suppressAll();
|
||||||
|
|
||||||
|
void songVolumeChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool startedOther(MediaOverviewType type, bool &fadedStart);
|
bool fadedStop(MediaOverviewType type, bool *fadedStart = 0);
|
||||||
bool updateCurrentStarted(MediaOverviewType type, int32 pos = -1);
|
bool updateCurrentStarted(MediaOverviewType type, int32 pos = -1);
|
||||||
|
bool checkCurrentALError(MediaOverviewType type);
|
||||||
|
|
||||||
struct Msg {
|
struct Msg {
|
||||||
Msg() : position(0), duration(0), frequency(AudioVoiceMsgFrequency), skipStart(0), skipEnd(0), loading(0), started(0),
|
Msg() : position(0), duration(0), frequency(AudioVoiceMsgFrequency), skipStart(0), skipEnd(0), loading(0), started(0),
|
||||||
|
@ -124,6 +138,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
void currentState(Msg *current, AudioPlayerState *state, int64 *position, int64 *duration, int32 *frequency);
|
void currentState(Msg *current, AudioPlayerState *state, int64 *position, int64 *duration, int32 *frequency);
|
||||||
|
void setStoppedState(Msg *current, AudioPlayerState state = AudioPlayerStopped);
|
||||||
|
|
||||||
int32 _audioCurrent;
|
int32 _audioCurrent;
|
||||||
AudioMsg _audioData[AudioVoiceMsgSimultaneously];
|
AudioMsg _audioData[AudioVoiceMsgSimultaneously];
|
||||||
|
@ -210,6 +225,7 @@ public slots:
|
||||||
void onSuppressSong();
|
void onSuppressSong();
|
||||||
void onUnsuppressSong();
|
void onUnsuppressSong();
|
||||||
void onSuppressAll();
|
void onSuppressAll();
|
||||||
|
void onSongVolumeChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -220,12 +236,13 @@ private:
|
||||||
EmitNeedToPreload = 0x08,
|
EmitNeedToPreload = 0x08,
|
||||||
};
|
};
|
||||||
int32 updateOnePlayback(AudioPlayer::Msg *m, bool &hasPlaying, bool &hasFading, float64 suppressGain, bool suppressGainChanged);
|
int32 updateOnePlayback(AudioPlayer::Msg *m, bool &hasPlaying, bool &hasFading, float64 suppressGain, bool suppressGainChanged);
|
||||||
|
void setStoppedState(AudioPlayer::Msg *m, AudioPlayerState state = AudioPlayerStopped);
|
||||||
|
|
||||||
QTimer _timer, _pauseTimer;
|
QTimer _timer, _pauseTimer;
|
||||||
QMutex _pauseMutex;
|
QMutex _pauseMutex;
|
||||||
bool _pauseFlag, _paused;
|
bool _pauseFlag, _paused;
|
||||||
|
|
||||||
bool _suppressAll, _suppressAllAnim, _suppressSong, _suppressSongAnim;
|
bool _suppressAll, _suppressAllAnim, _suppressSong, _suppressSongAnim, _songVolumeChanged;
|
||||||
anim::fvalue _suppressAllGain, _suppressSongGain;
|
anim::fvalue _suppressAllGain, _suppressSongGain;
|
||||||
uint64 _suppressAllStart, _suppressSongStart;
|
uint64 _suppressAllStart, _suppressSongStart;
|
||||||
|
|
||||||
|
@ -250,8 +267,8 @@ public slots:
|
||||||
|
|
||||||
void onInit();
|
void onInit();
|
||||||
|
|
||||||
void onStart(const AudioMsgId &audio);
|
void onStart(const AudioMsgId &audio, qint64 position);
|
||||||
void onStart(const SongMsgId &audio);
|
void onStart(const SongMsgId &audio, qint64 position);
|
||||||
|
|
||||||
void onLoad(const AudioMsgId &audio);
|
void onLoad(const AudioMsgId &audio);
|
||||||
void onLoad(const SongMsgId &audio);
|
void onLoad(const SongMsgId &audio);
|
||||||
|
@ -269,6 +286,7 @@ private:
|
||||||
|
|
||||||
void emitError(MediaOverviewType type);
|
void emitError(MediaOverviewType type);
|
||||||
void clear(MediaOverviewType type);
|
void clear(MediaOverviewType type);
|
||||||
|
void setStoppedState(AudioPlayer::Msg *m, AudioPlayerState state = AudioPlayerStopped);
|
||||||
AudioMsgId clearAudio();
|
AudioMsgId clearAudio();
|
||||||
SongMsgId clearSong();
|
SongMsgId clearSong();
|
||||||
|
|
||||||
|
@ -278,8 +296,8 @@ private:
|
||||||
SetupErrorLoadedFull = 2,
|
SetupErrorLoadedFull = 2,
|
||||||
SetupNoErrorStarted = 3,
|
SetupNoErrorStarted = 3,
|
||||||
};
|
};
|
||||||
void loadData(MediaOverviewType type, const void *objId);
|
void loadData(MediaOverviewType type, const void *objId, qint64 position);
|
||||||
AudioPlayerLoader *setupLoader(MediaOverviewType type, const void *objId, SetupError &err);
|
AudioPlayerLoader *setupLoader(MediaOverviewType type, const void *objId, SetupError &err, qint64 position);
|
||||||
AudioPlayer::Msg *checkLoader(MediaOverviewType type);
|
AudioPlayer::Msg *checkLoader(MediaOverviewType type);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -87,7 +87,7 @@ enum {
|
||||||
AudioVoiceMsgSimultaneously = 4,
|
AudioVoiceMsgSimultaneously = 4,
|
||||||
AudioSongSimultaneously = 4,
|
AudioSongSimultaneously = 4,
|
||||||
AudioCheckPositionTimeout = 100, // 100ms per check audio pos
|
AudioCheckPositionTimeout = 100, // 100ms per check audio pos
|
||||||
AudioCheckPositionDelta = 4800, // update position called each 4800 samples
|
AudioCheckPositionDelta = 2400, // update position called each 2400 samples
|
||||||
AudioFadeTimeout = 7, // 7ms
|
AudioFadeTimeout = 7, // 7ms
|
||||||
AudioFadeDuration = 500,
|
AudioFadeDuration = 500,
|
||||||
AudioVoiceMsgSkip = 400, // 200ms
|
AudioVoiceMsgSkip = 400, // 200ms
|
||||||
|
|
|
@ -1929,9 +1929,16 @@ void DialogsWidget::resizeEvent(QResizeEvent *e) {
|
||||||
_addContact.move(w - _addContact.width() - st::dlgPaddingHor, _filter.y());
|
_addContact.move(w - _addContact.width() - st::dlgPaddingHor, _filter.y());
|
||||||
_cancelSearch.move(w - _cancelSearch.width() - st::dlgPaddingHor, _filter.y());
|
_cancelSearch.move(w - _cancelSearch.width() - st::dlgPaddingHor, _filter.y());
|
||||||
scroll.move(0, _filter.height() + 2 * st::dlgFilterPadding);
|
scroll.move(0, _filter.height() + 2 * st::dlgFilterPadding);
|
||||||
|
|
||||||
|
int32 addToY = App::main() ? App::main()->contentScrollAddToY() : 0;
|
||||||
|
int32 newScrollY = scroll.scrollTop() + addToY;
|
||||||
scroll.resize(w, height() - _filter.y() - _filter.height() - st::dlgFilterPadding - st::dlgPaddingVer);
|
scroll.resize(w, height() - _filter.y() - _filter.height() - st::dlgFilterPadding - st::dlgPaddingVer);
|
||||||
list.resize(w, list.height());
|
list.resize(w, list.height());
|
||||||
onListScroll();
|
if (addToY) {
|
||||||
|
scroll.scrollToY(newScrollY);
|
||||||
|
} else {
|
||||||
|
onListScroll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogsWidget::keyPressEvent(QKeyEvent *e) {
|
void DialogsWidget::keyPressEvent(QKeyEvent *e) {
|
||||||
|
|
|
@ -2611,6 +2611,15 @@ bool MentionsInner::moveSel(int direction) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MentionsInner::select() {
|
bool MentionsInner::select() {
|
||||||
|
QString sel = getSelected();
|
||||||
|
if (!sel.isEmpty()) {
|
||||||
|
emit chosen(sel);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MentionsInner::getSelected() const {
|
||||||
int32 maxSel = (_rows->isEmpty() ? (_hrows->isEmpty() ? _crows->size() : _hrows->size()) : _rows->size());
|
int32 maxSel = (_rows->isEmpty() ? (_hrows->isEmpty() ? _crows->size() : _hrows->size()) : _rows->size());
|
||||||
if (_sel >= 0 && _sel < maxSel) {
|
if (_sel >= 0 && _sel < maxSel) {
|
||||||
QString result;
|
QString result;
|
||||||
|
@ -2628,10 +2637,9 @@ bool MentionsInner::select() {
|
||||||
result = '/' + command.command;
|
result = '/' + command.command;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emit chosen(result);
|
return result;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MentionsInner::mousePressEvent(QMouseEvent *e) {
|
void MentionsInner::mousePressEvent(QMouseEvent *e) {
|
||||||
|
@ -2991,6 +2999,10 @@ int32 MentionsDropdown::innerBottom() {
|
||||||
return _scroll.scrollTop() + _scroll.height();
|
return _scroll.scrollTop() + _scroll.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString MentionsDropdown::getSelected() const {
|
||||||
|
return _inner.getSelected();
|
||||||
|
}
|
||||||
|
|
||||||
bool MentionsDropdown::eventFilter(QObject *obj, QEvent *e) {
|
bool MentionsDropdown::eventFilter(QObject *obj, QEvent *e) {
|
||||||
if (isHidden()) return QWidget::eventFilter(obj, e);
|
if (isHidden()) return QWidget::eventFilter(obj, e);
|
||||||
if (e->type() == QEvent::KeyPress) {
|
if (e->type() == QEvent::KeyPress) {
|
||||||
|
|
|
@ -503,6 +503,8 @@ public:
|
||||||
bool moveSel(int direction);
|
bool moveSel(int direction);
|
||||||
bool select();
|
bool select();
|
||||||
|
|
||||||
|
QString getSelected() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void chosen(QString mentionOrHashtag);
|
void chosen(QString mentionOrHashtag);
|
||||||
|
@ -552,6 +554,7 @@ public:
|
||||||
int32 innerBottom();
|
int32 innerBottom();
|
||||||
|
|
||||||
bool eventFilter(QObject *obj, QEvent *e);
|
bool eventFilter(QObject *obj, QEvent *e);
|
||||||
|
QString getSelected() const;
|
||||||
|
|
||||||
~MentionsDropdown();
|
~MentionsDropdown();
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,17 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||||
#include <QtGui/QCursor>
|
#include <QtGui/QCursor>
|
||||||
#include <QtGui/QFont>
|
#include <QtGui/QFont>
|
||||||
|
|
||||||
|
inline QPoint rtlpoint(int x, int y, int outerw) {
|
||||||
|
return QPoint(rtl() ? (outerw - x) : x, y);
|
||||||
|
}
|
||||||
|
inline QPoint rtlpoint(const QPoint &p, int outerw) {
|
||||||
|
return rtl() ? QPoint(outerw - p.x(), p.y()) : p;
|
||||||
|
}
|
||||||
inline QRect rtlrect(int x, int y, int w, int h, int outerw) {
|
inline QRect rtlrect(int x, int y, int w, int h, int outerw) {
|
||||||
return rtl() ? QRect(outerw - x - w, y, w, h) : QRect(x, y, w, h);
|
return QRect(rtl() ? (outerw - x - w) : x, y, w, h);
|
||||||
|
}
|
||||||
|
inline QRect rtlrect(const QRect &r, int outerw) {
|
||||||
|
return rtl() ? QRect(outerw - r.x() - r.width(), r.y(), r.width(), r.height()) : r;
|
||||||
}
|
}
|
||||||
inline QRect centerrect(const QRect &inRect, const QRect &rect) {
|
inline QRect centerrect(const QRect &inRect, const QRect &rect) {
|
||||||
return QRect(inRect.x() + (inRect.width() - rect.width()) / 2, inRect.y() + (inRect.height() - rect.height()) / 2, rect.width(), rect.height());
|
return QRect(inRect.x() + (inRect.width() - rect.width()) / 2, inRect.y() + (inRect.height() - rect.height()) / 2, rect.width(), rect.height());
|
||||||
|
|
|
@ -24,7 +24,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const QRegularExpression _reDomain(QString::fromUtf8("(?<![\\w\\$\\-\\_%=\\.])(?:([a-zA-Z]+)://)?((?:[A-Za-zА-яА-ЯёЁ0-9\\-\\_]+\\.){1,5}([A-Za-zрф\\-\\d]{2,22})(\\:\\d+)?)"), QRegularExpression::UseUnicodePropertiesOption);
|
const QRegularExpression _reDomain(QString::fromUtf8("(?<![\\w\\$\\-\\_%=\\.])(?:([a-zA-Z]+)://)?((?:[A-Za-zА-яА-ЯёЁ0-9\\-\\_]+\\.){1,10}([A-Za-zрф\\-\\d]{2,22})(\\:\\d+)?)"), QRegularExpression::UseUnicodePropertiesOption);
|
||||||
const QRegularExpression _reExplicitDomain(QString::fromUtf8("(?<![\\w\\$\\-\\_%=\\.])(?:([a-zA-Z]+)://)((?:[A-Za-zА-яА-ЯёЁ0-9\\-\\_]+\\.){0,5}([A-Za-zрф\\-\\d]{2,22})(\\:\\d+)?)"), QRegularExpression::UseUnicodePropertiesOption);
|
const QRegularExpression _reExplicitDomain(QString::fromUtf8("(?<![\\w\\$\\-\\_%=\\.])(?:([a-zA-Z]+)://)((?:[A-Za-zА-яА-ЯёЁ0-9\\-\\_]+\\.){0,5}([A-Za-zрф\\-\\d]{2,22})(\\:\\d+)?)"), QRegularExpression::UseUnicodePropertiesOption);
|
||||||
const QRegularExpression _reMailName(qsl("[a-zA-Z\\-_\\.0-9]{1,256}$"));
|
const QRegularExpression _reMailName(qsl("[a-zA-Z\\-_\\.0-9]{1,256}$"));
|
||||||
const QRegularExpression _reMailStart(qsl("^[a-zA-Z\\-_\\.0-9]{1,256}\\@"));
|
const QRegularExpression _reMailStart(qsl("^[a-zA-Z\\-_\\.0-9]{1,256}\\@"));
|
||||||
|
@ -1617,21 +1617,23 @@ public:
|
||||||
void eSetFont(ITextBlock *block) {
|
void eSetFont(ITextBlock *block) {
|
||||||
style::font newFont = _t->_font;
|
style::font newFont = _t->_font;
|
||||||
int flags = block->flags();
|
int flags = block->flags();
|
||||||
if (!flags && block->lnkIndex()) {
|
if (block->lnkIndex()) {
|
||||||
const TextLinkPtr &l(_t->_links.at(block->lnkIndex() - 1));
|
const TextLinkPtr &l(_t->_links.at(block->lnkIndex() - 1));
|
||||||
if (l == _overLnk) {
|
if (l == _overLnk) {
|
||||||
if (l == _downLnk || !_downLnk) {
|
if (l == _downLnk || !_downLnk) {
|
||||||
flags = _textStyle->lnkOverFlags->flags();
|
newFont = _textStyle->lnkOverFlags;
|
||||||
} else {
|
} else {
|
||||||
flags = _textStyle->lnkFlags->flags();
|
newFont = _textStyle->lnkFlags;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
flags = _textStyle->lnkFlags->flags();
|
newFont = _textStyle->lnkFlags;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
flags = block->flags();
|
||||||
|
if (flags & TextBlockBold) newFont = newFont->bold();
|
||||||
|
if (flags & TextBlockItalic) newFont = newFont->italic();
|
||||||
|
if (flags & TextBlockUnderline) newFont = newFont->underline();
|
||||||
}
|
}
|
||||||
if (flags & TextBlockBold) newFont = newFont->bold();
|
|
||||||
if (flags & TextBlockItalic) newFont = newFont->italic();
|
|
||||||
if (flags & TextBlockUnderline) newFont = newFont->underline();
|
|
||||||
if (newFont != _f) {
|
if (newFont != _f) {
|
||||||
_f = newFont;
|
_f = newFont;
|
||||||
_e->fnt = _f->f;
|
_e->fnt = _f->f;
|
||||||
|
|
|
@ -17,20 +17,6 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
class Widget : public QWidget {
|
|
||||||
public:
|
|
||||||
|
|
||||||
Widget(QWidget *parent = 0) : QWidget(parent) {
|
|
||||||
}
|
|
||||||
void moveToLeft(int x, int y, int outerw) {
|
|
||||||
move(rtl() ? (outerw - x - width()) : x, y);
|
|
||||||
}
|
|
||||||
void moveToRight(int x, int y, int outerw) {
|
|
||||||
move(rtl() ? x : (outerw - x - width()), y);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace App {
|
namespace App {
|
||||||
const QPixmap &sprite();
|
const QPixmap &sprite();
|
||||||
}
|
}
|
||||||
|
@ -119,14 +105,20 @@ public:
|
||||||
void drawSpriteCenter(const QRect &in, const style::sprite &sprite) {
|
void drawSpriteCenter(const QRect &in, const style::sprite &sprite) {
|
||||||
return drawPixmap(QPoint(in.x() + (in.width() - sprite.pxWidth()) / 2, in.y() + (in.height() - sprite.pxHeight()) / 2), App::sprite(), sprite);
|
return drawPixmap(QPoint(in.x() + (in.width() - sprite.pxWidth()) / 2, in.y() + (in.height() - sprite.pxHeight()) / 2), App::sprite(), sprite);
|
||||||
}
|
}
|
||||||
|
void drawSpriteCenterLeft(const QRect &in, int outerw, const style::sprite &sprite) {
|
||||||
|
return drawPixmapLeft(QPoint(in.x() + (in.width() - sprite.pxWidth()) / 2, in.y() + (in.height() - sprite.pxHeight()) / 2), outerw, App::sprite(), sprite);
|
||||||
|
}
|
||||||
|
void drawSpriteCenterRight(const QRect &in, int outerw, const style::sprite &sprite) {
|
||||||
|
return drawPixmapRight(QPoint(in.x() + (in.width() - sprite.pxWidth()) / 2, in.y() + (in.height() - sprite.pxHeight()) / 2), outerw, App::sprite(), sprite);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class TWidget : public Widget {
|
class TWidget : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TWidget(QWidget *parent = 0) : Widget(parent) {
|
TWidget(QWidget *parent = 0) : QWidget(parent) {
|
||||||
}
|
}
|
||||||
TWidget *tparent() {
|
TWidget *tparent() {
|
||||||
return qobject_cast<TWidget*>(parentWidget());
|
return qobject_cast<TWidget*>(parentWidget());
|
||||||
|
@ -140,6 +132,27 @@ public:
|
||||||
virtual void enterFromChildEvent(QEvent *e) { // e -- from leaveEvent() of child TWidget
|
virtual void enterFromChildEvent(QEvent *e) { // e -- from leaveEvent() of child TWidget
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void moveToLeft(int x, int y, int outerw) {
|
||||||
|
move(rtl() ? (outerw - x - width()) : x, y);
|
||||||
|
}
|
||||||
|
void moveToRight(int x, int y, int outerw) {
|
||||||
|
move(rtl() ? x : (outerw - x - width()), y);
|
||||||
|
}
|
||||||
|
QPoint myrtlpoint(int x, int y) const {
|
||||||
|
return rtlpoint(x, y, width());
|
||||||
|
}
|
||||||
|
QPoint myrtlpoint(const QPoint p) const {
|
||||||
|
return rtlpoint(p, width());
|
||||||
|
}
|
||||||
|
QRect myrtlrect(int x, int y, int w, int h) const {
|
||||||
|
return rtlrect(x, y, w, h, width());
|
||||||
|
}
|
||||||
|
QRect myrtlrect(const QRect &r) {
|
||||||
|
return rtlrect(r, width());
|
||||||
|
}
|
||||||
|
void rtlupdate(const QRect &r) {
|
||||||
|
update(myrtlrect(r));
|
||||||
|
}
|
||||||
bool event(QEvent *e) {
|
bool event(QEvent *e) {
|
||||||
return QWidget::event(e);
|
return QWidget::event(e);
|
||||||
}
|
}
|
||||||
|
@ -149,12 +162,12 @@ protected:
|
||||||
void enterEvent(QEvent *e) {
|
void enterEvent(QEvent *e) {
|
||||||
TWidget *p(tparent());
|
TWidget *p(tparent());
|
||||||
if (p) p->leaveToChildEvent(e);
|
if (p) p->leaveToChildEvent(e);
|
||||||
return Widget::enterEvent(e);
|
return QWidget::enterEvent(e);
|
||||||
}
|
}
|
||||||
void leaveEvent(QEvent *e) {
|
void leaveEvent(QEvent *e) {
|
||||||
TWidget *p(tparent());
|
TWidget *p(tparent());
|
||||||
if (p) p->enterFromChildEvent(e);
|
if (p) p->enterFromChildEvent(e);
|
||||||
return Widget::leaveEvent(e);
|
return QWidget::leaveEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -372,6 +372,28 @@ bool History::updateTyping(uint64 ms, uint32 dots, bool force) {
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void History::eraseFromOverview(MediaOverviewType type, MsgId msgId) {
|
||||||
|
if (_overviewIds[type].isEmpty()) return;
|
||||||
|
|
||||||
|
History::MediaOverviewIds::iterator i = _overviewIds[type].find(msgId);
|
||||||
|
if (i == _overviewIds[type].cend()) return;
|
||||||
|
|
||||||
|
_overviewIds[type].erase(i);
|
||||||
|
for (History::MediaOverview::iterator i = _overview[type].begin(), e = _overview[type].end(); i != e; ++i) {
|
||||||
|
if ((*i) == msgId) {
|
||||||
|
_overview[type].erase(i);
|
||||||
|
if (_overviewCount[type] > 0) {
|
||||||
|
--_overviewCount[type];
|
||||||
|
if (!_overviewCount[type]) {
|
||||||
|
_overviewCount[type] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, type);
|
||||||
|
}
|
||||||
|
|
||||||
bool DialogsList::del(const PeerId &peerId, DialogRow *replacedBy) {
|
bool DialogsList::del(const PeerId &peerId, DialogRow *replacedBy) {
|
||||||
RowByPeer::iterator i = rowByPeer.find(peerId);
|
RowByPeer::iterator i = rowByPeer.find(peerId);
|
||||||
if (i == rowByPeer.cend()) return false;
|
if (i == rowByPeer.cend()) return false;
|
||||||
|
@ -803,13 +825,23 @@ HistoryItem *History::doAddToBack(HistoryBlock *to, bool newBlock, HistoryItem *
|
||||||
}
|
}
|
||||||
HistoryMedia *media = adding->getMedia(true);
|
HistoryMedia *media = adding->getMedia(true);
|
||||||
if (media) {
|
if (media) {
|
||||||
MediaOverviewType t = mediaToOverviewType(media->type());
|
HistoryMediaType mt = media->type();
|
||||||
|
MediaOverviewType t = mediaToOverviewType(mt);
|
||||||
if (t != OverviewCount) {
|
if (t != OverviewCount) {
|
||||||
if (_overviewIds[t].constFind(adding->id) == _overviewIds[t].cend()) {
|
if (_overviewIds[t].constFind(adding->id) == _overviewIds[t].cend()) {
|
||||||
_overview[t].push_back(adding->id);
|
_overview[t].push_back(adding->id);
|
||||||
_overviewIds[t].insert(adding->id, NullType());
|
_overviewIds[t].insert(adding->id, NullType());
|
||||||
if (_overviewCount[t] > 0) ++_overviewCount[t];
|
if (_overviewCount[t] > 0) ++_overviewCount[t];
|
||||||
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer);
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, t);
|
||||||
|
}
|
||||||
|
if (mt == MediaTypeDocument && static_cast<HistoryDocument*>(media)->document()->song()) {
|
||||||
|
t = OverviewAudioDocuments;
|
||||||
|
if (_overviewIds[t].constFind(adding->id) == _overviewIds[t].cend()) {
|
||||||
|
_overview[t].push_back(adding->id);
|
||||||
|
_overviewIds[t].insert(adding->id, NullType());
|
||||||
|
if (_overviewCount[t] > 0) ++_overviewCount[t];
|
||||||
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer, t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -933,16 +965,27 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
|
||||||
++skip;
|
++skip;
|
||||||
|
|
||||||
if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors
|
if (loadedAtBottom()) { // add photos to overview and authors to lastAuthors
|
||||||
|
int32 mask = 0;
|
||||||
QList<UserData*> *lastAuthors = peer->chat ? &(peer->asChat()->lastAuthors) : 0;
|
QList<UserData*> *lastAuthors = peer->chat ? &(peer->asChat()->lastAuthors) : 0;
|
||||||
for (int32 i = block->size(); i > 0; --i) {
|
for (int32 i = block->size(); i > 0; --i) {
|
||||||
HistoryItem *item = (*block)[i - 1];
|
HistoryItem *item = (*block)[i - 1];
|
||||||
HistoryMedia *media = item->getMedia(true);
|
HistoryMedia *media = item->getMedia(true);
|
||||||
if (media) {
|
if (media) {
|
||||||
MediaOverviewType t = mediaToOverviewType(media->type());
|
HistoryMediaType mt = media->type();
|
||||||
|
MediaOverviewType t = mediaToOverviewType(mt);
|
||||||
if (t != OverviewCount) {
|
if (t != OverviewCount) {
|
||||||
if (_overviewIds[t].constFind(item->id) == _overviewIds[t].cend()) {
|
if (_overviewIds[t].constFind(item->id) == _overviewIds[t].cend()) {
|
||||||
_overview[t].push_front(item->id);
|
_overview[t].push_front(item->id);
|
||||||
_overviewIds[t].insert(item->id, NullType());
|
_overviewIds[t].insert(item->id, NullType());
|
||||||
|
mask |= (1 << t);
|
||||||
|
}
|
||||||
|
if (mt == MediaTypeDocument && static_cast<HistoryDocument*>(media)->document()->song()) {
|
||||||
|
t = OverviewAudioDocuments;
|
||||||
|
if (_overviewIds[t].constFind(item->id) == _overviewIds[t].cend()) {
|
||||||
|
_overview[t].push_front(item->id);
|
||||||
|
_overviewIds[t].insert(item->id, NullType());
|
||||||
|
mask |= (1 << t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -987,7 +1030,9 @@ void History::addToFront(const QVector<MTPMessage> &slice) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer);
|
for (int32 t = 0; t < OverviewCount; ++t) {
|
||||||
|
if ((mask & (1 << t)) && App::wnd()) App::wnd()->mediaOverviewUpdated(peer, MediaOverviewType(t));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
delete block;
|
delete block;
|
||||||
|
@ -1062,10 +1107,14 @@ void History::addToBack(const QVector<MTPMessage> &slice) {
|
||||||
delete block;
|
delete block;
|
||||||
}
|
}
|
||||||
if (!wasLoadedAtBottom && loadedAtBottom()) { // add all loaded photos to overview
|
if (!wasLoadedAtBottom && loadedAtBottom()) { // add all loaded photos to overview
|
||||||
|
int32 mask = 0;
|
||||||
for (int32 i = 0; i < OverviewCount; ++i) {
|
for (int32 i = 0; i < OverviewCount; ++i) {
|
||||||
if (_overviewCount[i] == 0) continue; // all loaded
|
if (_overviewCount[i] == 0) continue; // all loaded
|
||||||
_overview[i].clear();
|
if (!_overview[i].isEmpty() || !_overviewIds[i].isEmpty()) {
|
||||||
_overviewIds[i].clear();
|
_overview[i].clear();
|
||||||
|
_overviewIds[i].clear();
|
||||||
|
mask |= (1 << i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (int32 i = 0; i < size(); ++i) {
|
for (int32 i = 0; i < size(); ++i) {
|
||||||
HistoryBlock *b = (*this)[i];
|
HistoryBlock *b = (*this)[i];
|
||||||
|
@ -1073,15 +1122,29 @@ void History::addToBack(const QVector<MTPMessage> &slice) {
|
||||||
HistoryItem *item = (*b)[j];
|
HistoryItem *item = (*b)[j];
|
||||||
HistoryMedia *media = item->getMedia(true);
|
HistoryMedia *media = item->getMedia(true);
|
||||||
if (media) {
|
if (media) {
|
||||||
MediaOverviewType t = mediaToOverviewType(media->type());
|
HistoryMediaType mt = media->type();
|
||||||
if (t != OverviewCount && _overviewCount[t] != 0) {
|
MediaOverviewType t = mediaToOverviewType(mt);
|
||||||
_overview[t].push_back(item->id);
|
if (t != OverviewCount) {
|
||||||
_overviewIds[t].insert(item->id, NullType());
|
if (_overviewCount[t] != 0) {
|
||||||
|
_overview[t].push_back(item->id);
|
||||||
|
_overviewIds[t].insert(item->id, NullType());
|
||||||
|
mask |= (1 << t);
|
||||||
|
}
|
||||||
|
if (mt == MediaTypeDocument && static_cast<HistoryDocument*>(media)->document()->song()) {
|
||||||
|
t = OverviewAudioDocuments;
|
||||||
|
if (_overviewCount[t] != 0) {
|
||||||
|
_overview[t].push_back(item->id);
|
||||||
|
_overviewIds[t].insert(item->id, NullType());
|
||||||
|
mask |= (1 << t);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (App::wnd()) App::wnd()->mediaOverviewUpdated(peer);
|
for (int32 t = 0; t < OverviewCount; ++t) {
|
||||||
|
if ((mask & (1 << t)) && App::wnd()) App::wnd()->mediaOverviewUpdated(peer, MediaOverviewType(t));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (wasEmpty && !isEmpty()) {
|
if (wasEmpty && !isEmpty()) {
|
||||||
HistoryBlock *dateBlock = new HistoryBlock(this);
|
HistoryBlock *dateBlock = new HistoryBlock(this);
|
||||||
|
@ -1328,11 +1391,13 @@ void History::clear(bool leaveItems) {
|
||||||
showFrom = 0;
|
showFrom = 0;
|
||||||
}
|
}
|
||||||
for (int32 i = 0; i < OverviewCount; ++i) {
|
for (int32 i = 0; i < OverviewCount; ++i) {
|
||||||
if (_overviewCount[i] == 0) _overviewCount[i] = _overview[i].size();
|
if (!_overview[i].isEmpty() || !_overviewIds[i].isEmpty()) {
|
||||||
_overview[i].clear();
|
if (_overviewCount[i] == 0) _overviewCount[i] = _overview[i].size();
|
||||||
_overviewIds[i].clear();
|
_overview[i].clear();
|
||||||
|
_overviewIds[i].clear();
|
||||||
|
if (App::wnd() && !App::quiting()) App::wnd()->mediaOverviewUpdated(peer, MediaOverviewType(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (App::wnd() && !App::quiting()) App::wnd()->mediaOverviewUpdated(peer);
|
|
||||||
for (Parent::const_iterator i = cbegin(), e = cend(); i != e; ++i) {
|
for (Parent::const_iterator i = cbegin(), e = cend(); i != e; ++i) {
|
||||||
if (leaveItems) {
|
if (leaveItems) {
|
||||||
(*i)->clear(true);
|
(*i)->clear(true);
|
||||||
|
@ -1580,23 +1645,10 @@ void HistoryItem::destroy() {
|
||||||
}
|
}
|
||||||
HistoryMedia *m = getMedia(true);
|
HistoryMedia *m = getMedia(true);
|
||||||
MediaOverviewType t = m ? mediaToOverviewType(m->type()) : OverviewCount;
|
MediaOverviewType t = m ? mediaToOverviewType(m->type()) : OverviewCount;
|
||||||
if (t != OverviewCount && !history()->_overviewIds[t].isEmpty()) {
|
if (t != OverviewCount) {
|
||||||
History::MediaOverviewIds::iterator i = history()->_overviewIds[t].find(id);
|
history()->eraseFromOverview(t, id);
|
||||||
if (i != history()->_overviewIds[t].cend()) {
|
if (m->type() == MediaTypeDocument && static_cast<HistoryDocument*>(m)->document()->song()) {
|
||||||
history()->_overviewIds[t].erase(i);
|
history()->eraseFromOverview(OverviewAudioDocuments, id);
|
||||||
for (History::MediaOverview::iterator i = history()->_overview[t].begin(), e = history()->_overview[t].end(); i != e; ++i) {
|
|
||||||
if ((*i) == id) {
|
|
||||||
history()->_overview[t].erase(i);
|
|
||||||
if (history()->_overviewCount[t] > 0) {
|
|
||||||
--history()->_overviewCount[t];
|
|
||||||
if (!history()->_overviewCount[t]) {
|
|
||||||
history()->_overviewCount[t] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (App::wnd()) App::wnd()->mediaOverviewUpdated(history()->peer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -2339,8 +2391,9 @@ void HistoryVideo::draw(QPainter &p, const HistoryItem *parent, bool selected, i
|
||||||
p.setPen(status->p);
|
p.setPen(status->p);
|
||||||
|
|
||||||
if (data->loader) {
|
if (data->loader) {
|
||||||
if (_dldTextCache.isEmpty() || _dldDone != data->loader->currentOffset()) {
|
int32 offset = data->loader->currentOffset();
|
||||||
_dldDone = data->loader->currentOffset();
|
if (_dldTextCache.isEmpty() || _dldDone != offset) {
|
||||||
|
_dldDone = offset;
|
||||||
_dldTextCache = formatDownloadText(_dldDone, data->size);
|
_dldTextCache = formatDownloadText(_dldDone, data->size);
|
||||||
}
|
}
|
||||||
statusText = _dldTextCache;
|
statusText = _dldTextCache;
|
||||||
|
@ -2563,7 +2616,7 @@ void HistoryAudio::draw(QPainter &p, const HistoryItem *parent, bool selected, i
|
||||||
img = out ? st::mediaAudioOutImg : st::mediaAudioInImg;
|
img = out ? st::mediaAudioOutImg : st::mediaAudioInImg;
|
||||||
} else if (already || hasdata) {
|
} else if (already || hasdata) {
|
||||||
bool showPause = false;
|
bool showPause = false;
|
||||||
if (playing.msgId == parent->id && playingState != AudioPlayerStopped && playingState != AudioPlayerStoppedAtStart) {
|
if (playing.msgId == parent->id && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||||
statusText = formatDurationText(playingPosition / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency)) + qsl(" / ") + formatDurationText(playingDuration / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency));
|
statusText = formatDurationText(playingPosition / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency)) + qsl(" / ") + formatDurationText(playingDuration / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency));
|
||||||
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
|
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2572,8 +2625,9 @@ void HistoryAudio::draw(QPainter &p, const HistoryItem *parent, bool selected, i
|
||||||
img = out ? (showPause ? st::mediaPauseOutImg : st::mediaPlayOutImg) : (showPause ? st::mediaPauseInImg : st::mediaPlayInImg);
|
img = out ? (showPause ? st::mediaPauseOutImg : st::mediaPlayOutImg) : (showPause ? st::mediaPauseInImg : st::mediaPlayInImg);
|
||||||
} else {
|
} else {
|
||||||
if (data->loader) {
|
if (data->loader) {
|
||||||
if (_dldTextCache.isEmpty() || _dldDone != data->loader->currentOffset()) {
|
int32 offset = data->loader->currentOffset();
|
||||||
_dldDone = data->loader->currentOffset();
|
if (_dldTextCache.isEmpty() || _dldDone != offset) {
|
||||||
|
_dldDone = offset;
|
||||||
_dldTextCache = formatDownloadText(_dldDone, data->size);
|
_dldTextCache = formatDownloadText(_dldDone, data->size);
|
||||||
}
|
}
|
||||||
statusText = _dldTextCache;
|
statusText = _dldTextCache;
|
||||||
|
@ -2733,7 +2787,7 @@ namespace {
|
||||||
SongData *song = document->song();
|
SongData *song = document->song();
|
||||||
if (!song || (song->title.isEmpty() && song->performer.isEmpty())) return document->name;
|
if (!song || (song->title.isEmpty() && song->performer.isEmpty())) return document->name;
|
||||||
if (song->performer.isEmpty()) return song->title;
|
if (song->performer.isEmpty()) return song->title;
|
||||||
return song->performer + QString::fromUtf8(" \xe2\x80\x94 ") + (song->title.isEmpty() ? qsl("Unknown Track") : song->title);
|
return song->performer + QString::fromUtf8(" \xe2\x80\x93 ") + (song->title.isEmpty() ? qsl("Unknown Track") : song->title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2905,17 +2959,19 @@ void HistoryDocument::draw(QPainter &p, const HistoryItem *parent, bool selected
|
||||||
img = out ? st::mediaAudioOutImg : st::mediaAudioInImg;
|
img = out ? st::mediaAudioOutImg : st::mediaAudioInImg;
|
||||||
} else if (already || hasdata) {
|
} else if (already || hasdata) {
|
||||||
bool showPause = false;
|
bool showPause = false;
|
||||||
if (playing.msgId == parent->id && playingState != AudioPlayerStopped && playingState != AudioPlayerStoppedAtStart) {
|
if (playing.msgId == parent->id && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||||
statusText = formatDurationText(playingPosition / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency)) + qsl(" / ") + formatDurationText(playingDuration / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency));
|
statusText = formatDurationText(playingPosition / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency)) + qsl(" / ") + formatDurationText(playingDuration / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency));
|
||||||
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
|
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
|
||||||
} else {
|
} else {
|
||||||
statusText = formatDurationText(data->song()->duration);
|
statusText = formatDurationText(data->song()->duration);
|
||||||
}
|
}
|
||||||
|
if (!showPause && playing.msgId == parent->id && App::main() && App::main()->player()->seekingSong(playing)) showPause = true;
|
||||||
img = out ? (showPause ? st::mediaPauseOutImg : st::mediaPlayOutImg) : (showPause ? st::mediaPauseInImg : st::mediaPlayInImg);
|
img = out ? (showPause ? st::mediaPauseOutImg : st::mediaPlayOutImg) : (showPause ? st::mediaPauseInImg : st::mediaPlayInImg);
|
||||||
} else {
|
} else {
|
||||||
if (data->loader) {
|
if (data->loader) {
|
||||||
if (_dldTextCache.isEmpty() || _dldDone != data->loader->currentOffset()) {
|
int32 offset = data->loader->currentOffset();
|
||||||
_dldDone = data->loader->currentOffset();
|
if (_dldTextCache.isEmpty() || _dldDone != offset) {
|
||||||
|
_dldDone = offset;
|
||||||
_dldTextCache = formatDownloadText(_dldDone, data->size);
|
_dldTextCache = formatDownloadText(_dldDone, data->size);
|
||||||
}
|
}
|
||||||
statusText = _dldTextCache;
|
statusText = _dldTextCache;
|
||||||
|
@ -2936,8 +2992,9 @@ void HistoryDocument::draw(QPainter &p, const HistoryItem *parent, bool selected
|
||||||
}
|
}
|
||||||
statusText = _uplTextCache;
|
statusText = _uplTextCache;
|
||||||
} else if (data->loader) {
|
} else if (data->loader) {
|
||||||
if (_dldTextCache.isEmpty() || _dldDone != data->loader->currentOffset()) {
|
int32 offset = data->loader->currentOffset();
|
||||||
_dldDone = data->loader->currentOffset();
|
if (_dldTextCache.isEmpty() || _dldDone != offset) {
|
||||||
|
_dldDone = offset;
|
||||||
_dldTextCache = formatDownloadText(_dldDone, data->size);
|
_dldTextCache = formatDownloadText(_dldDone, data->size);
|
||||||
}
|
}
|
||||||
statusText = _dldTextCache;
|
statusText = _dldTextCache;
|
||||||
|
@ -3147,8 +3204,8 @@ HistorySticker::HistorySticker(DocumentData *document) : HistoryMedia()
|
||||||
, pixw(1), pixh(1), data(document), lastw(0)
|
, pixw(1), pixh(1), data(document), lastw(0)
|
||||||
{
|
{
|
||||||
data->thumb->load();
|
data->thumb->load();
|
||||||
if (!data->sticker->alt.isEmpty()) {
|
if (!data->sticker()->alt.isEmpty()) {
|
||||||
_emoji = data->sticker->alt;
|
_emoji = data->sticker()->alt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,7 @@ enum MediaOverviewType {
|
||||||
OverviewVideos,
|
OverviewVideos,
|
||||||
OverviewDocuments,
|
OverviewDocuments,
|
||||||
OverviewAudios,
|
OverviewAudios,
|
||||||
|
OverviewAudioDocuments,
|
||||||
|
|
||||||
OverviewCount
|
OverviewCount
|
||||||
};
|
};
|
||||||
|
@ -127,6 +128,7 @@ inline MTPMessagesFilter typeToMediaFilter(MediaOverviewType &type) {
|
||||||
case OverviewVideos: return MTP_inputMessagesFilterVideo();
|
case OverviewVideos: return MTP_inputMessagesFilterVideo();
|
||||||
case OverviewDocuments: return MTP_inputMessagesFilterDocument();
|
case OverviewDocuments: return MTP_inputMessagesFilterDocument();
|
||||||
case OverviewAudios: return MTP_inputMessagesFilterAudio();
|
case OverviewAudios: return MTP_inputMessagesFilterAudio();
|
||||||
|
case OverviewAudioDocuments: return MTP_inputMessagesFilterAudioDocuments();
|
||||||
default: type = OverviewCount; break;
|
default: type = OverviewCount; break;
|
||||||
}
|
}
|
||||||
return MTPMessagesFilter();
|
return MTPMessagesFilter();
|
||||||
|
@ -286,6 +288,8 @@ struct History : public QList<HistoryBlock*> {
|
||||||
MediaOverviewIds _overviewIds[OverviewCount];
|
MediaOverviewIds _overviewIds[OverviewCount];
|
||||||
int32 _overviewCount[OverviewCount]; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded
|
int32 _overviewCount[OverviewCount]; // -1 - not loaded, 0 - all loaded, > 0 - count, but not all loaded
|
||||||
|
|
||||||
|
void eraseFromOverview(MediaOverviewType type, MsgId msgId);
|
||||||
|
|
||||||
static const int32 ScrollMax = INT_MAX;
|
static const int32 ScrollMax = INT_MAX;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2225,6 +2225,7 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
||||||
connect(&_attachPhoto, SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
|
connect(&_attachPhoto, SIGNAL(clicked()), this, SLOT(onPhotoSelect()));
|
||||||
connect(&_field, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
|
connect(&_field, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
|
||||||
connect(&_field, SIGNAL(cancelled()), this, SLOT(onCancel()));
|
connect(&_field, SIGNAL(cancelled()), this, SLOT(onCancel()));
|
||||||
|
connect(&_field, SIGNAL(tabbed()), this, SLOT(onFieldTabbed()));
|
||||||
connect(&_field, SIGNAL(resized()), this, SLOT(onFieldResize()));
|
connect(&_field, SIGNAL(resized()), this, SLOT(onFieldResize()));
|
||||||
connect(&_field, SIGNAL(focused()), this, SLOT(onFieldFocused()));
|
connect(&_field, SIGNAL(focused()), this, SLOT(onFieldFocused()));
|
||||||
connect(&imageLoader, SIGNAL(imageReady()), this, SLOT(onPhotoReady()));
|
connect(&imageLoader, SIGNAL(imageReady()), this, SLOT(onPhotoReady()));
|
||||||
|
@ -3501,20 +3502,7 @@ bool HistoryWidget::showStep(float64 ms) {
|
||||||
_bgAnimCache = _animCache = _animTopBarCache = _bgAnimTopBarCache = QPixmap();
|
_bgAnimCache = _animCache = _animTopBarCache = _bgAnimTopBarCache = QPixmap();
|
||||||
App::main()->topBar()->stopAnim();
|
App::main()->topBar()->stopAnim();
|
||||||
App::main()->topBar()->enableShadow();
|
App::main()->topBar()->enableShadow();
|
||||||
if (hist && hist->readyForWork()) {
|
doneShow();
|
||||||
_scroll.show();
|
|
||||||
if (hist->lastScrollTop == History::ScrollMax) {
|
|
||||||
_scroll.scrollToY(hist->lastScrollTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
onListScroll();
|
|
||||||
}
|
|
||||||
if (hist) {
|
|
||||||
if (!_histInited) checkUnreadLoaded();
|
|
||||||
if (_histNeedUpdate) updateListSize();
|
|
||||||
}
|
|
||||||
updateControlsVisibility();
|
|
||||||
App::wnd()->setInnerFocus();
|
|
||||||
} else {
|
} else {
|
||||||
a_bgCoord.update(dt1, st::introHideFunc);
|
a_bgCoord.update(dt1, st::introHideFunc);
|
||||||
a_bgAlpha.update(dt1, st::introAlphaHideFunc);
|
a_bgAlpha.update(dt1, st::introAlphaHideFunc);
|
||||||
|
@ -3526,6 +3514,23 @@ bool HistoryWidget::showStep(float64 ms) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryWidget::doneShow() {
|
||||||
|
if (hist && hist->readyForWork()) {
|
||||||
|
_scroll.show();
|
||||||
|
if (hist->lastScrollTop == History::ScrollMax) {
|
||||||
|
_scroll.scrollToY(hist->lastScrollTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
onListScroll();
|
||||||
|
}
|
||||||
|
if (hist) {
|
||||||
|
if (!_histInited) checkUnreadLoaded();
|
||||||
|
if (_histNeedUpdate) updateListSize();
|
||||||
|
}
|
||||||
|
updateControlsVisibility();
|
||||||
|
App::wnd()->setInnerFocus();
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryWidget::animStop() {
|
void HistoryWidget::animStop() {
|
||||||
if (!_showAnim.animating()) return;
|
if (!_showAnim.animating()) return;
|
||||||
_showAnim.stop();
|
_showAnim.stop();
|
||||||
|
@ -4502,7 +4507,7 @@ void HistoryWidget::resizeEvent(QResizeEvent *e) {
|
||||||
_attachPhoto.move(_attachDocument.x(), _attachDocument.y());
|
_attachPhoto.move(_attachDocument.x(), _attachDocument.y());
|
||||||
|
|
||||||
_replyForwardPreviewCancel.move(width() - _replyForwardPreviewCancel.width(), _field.y() - st::sendPadding - _replyForwardPreviewCancel.height());
|
_replyForwardPreviewCancel.move(width() - _replyForwardPreviewCancel.width(), _field.y() - st::sendPadding - _replyForwardPreviewCancel.height());
|
||||||
updateListSize();
|
updateListSize(App::main() ? App::main()->contentScrollAddToY() : 0);
|
||||||
|
|
||||||
bool kbShowShown = hist && !_kbShown && _keyboard.hasMarkup();
|
bool kbShowShown = hist && !_kbShown && _keyboard.hasMarkup();
|
||||||
_field.resize(width() - _send.width() - _attachDocument.width() - _attachEmoji.width() - (kbShowShown ? _kbShow.width() : 0) - (_cmdStartShown ? _cmdStart.width() : 0), _field.height());
|
_field.resize(width() - _send.width() - _attachDocument.width() - _attachEmoji.width() - (kbShowShown ? _kbShow.width() : 0) - (_cmdStartShown ? _cmdStart.width() : 0), _field.height());
|
||||||
|
@ -4841,6 +4846,13 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryWidget::onFieldTabbed() {
|
||||||
|
QString sel = _attachMention.isHidden() ? QString() : _attachMention.getSelected();
|
||||||
|
if (!sel.isEmpty()) {
|
||||||
|
_field.onMentionHashtagOrBotCommandInsert(sel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryWidget::onStickerSend(DocumentData *sticker) {
|
void HistoryWidget::onStickerSend(DocumentData *sticker) {
|
||||||
if (!hist || !sticker) return;
|
if (!hist || !sticker) return;
|
||||||
|
|
||||||
|
@ -5403,9 +5415,9 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasTopBar = !App::main()->topBar()->isHidden();
|
bool hasTopBar = !App::main()->topBar()->isHidden(), hasPlayer = !App::main()->player()->isHidden();
|
||||||
QRect fill(0, 0, width(), App::main()->height());
|
QRect fill(0, 0, width(), App::main()->height());
|
||||||
int fromy = hasTopBar ? (-st::topBarHeight) : 0, x = 0, y = 0;
|
int fromy = (hasTopBar ? (-st::topBarHeight) : 0) + (hasPlayer ? (-st::playerHeight) : 0), x = 0, y = 0;
|
||||||
QPixmap cached = App::main()->cachedBackground(fill, x, y);
|
QPixmap cached = App::main()->cachedBackground(fill, x, y);
|
||||||
if (cached.isNull()) {
|
if (cached.isNull()) {
|
||||||
const QPixmap &pix(*cChatBackground());
|
const QPixmap &pix(*cChatBackground());
|
||||||
|
|
|
@ -416,6 +416,7 @@ public:
|
||||||
void animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTopBarCache, bool back = false);
|
void animShow(const QPixmap &bgAnimCache, const QPixmap &bgAnimTopBarCache, bool back = false);
|
||||||
bool showStep(float64 ms);
|
bool showStep(float64 ms);
|
||||||
void animStop();
|
void animStop();
|
||||||
|
void doneShow();
|
||||||
|
|
||||||
QPoint clampMousePosition(QPoint point);
|
QPoint clampMousePosition(QPoint point);
|
||||||
|
|
||||||
|
@ -528,6 +529,7 @@ public slots:
|
||||||
void onMentionHashtagOrBotCommandInsert(QString str);
|
void onMentionHashtagOrBotCommandInsert(QString str);
|
||||||
void onTextChange();
|
void onTextChange();
|
||||||
|
|
||||||
|
void onFieldTabbed();
|
||||||
void onStickerSend(DocumentData *sticker);
|
void onStickerSend(DocumentData *sticker);
|
||||||
|
|
||||||
void onVisibleChanged();
|
void onVisibleChanged();
|
||||||
|
|
|
@ -1036,6 +1036,14 @@ namespace {
|
||||||
cSetDialogLastPath(path);
|
cSetDialogLastPath(path);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case dbiSongVolume: {
|
||||||
|
qint32 v;
|
||||||
|
stream >> v;
|
||||||
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
|
||||||
|
cSetSongVolume(snap(v / 1e6, 0., 1.));
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG(("App Error: unknown blockId in _readSetting: %1").arg(blockId));
|
LOG(("App Error: unknown blockId in _readSetting: %1").arg(blockId));
|
||||||
return false;
|
return false;
|
||||||
|
@ -1257,7 +1265,7 @@ namespace {
|
||||||
_writeMap(WriteMapFast);
|
_writeMap(WriteMapFast);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 size = 11 * (sizeof(quint32) + sizeof(qint32));
|
uint32 size = 12 * (sizeof(quint32) + sizeof(qint32));
|
||||||
size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath());
|
size += sizeof(quint32) + _stringSize(cAskDownloadPath() ? QString() : cDownloadPath());
|
||||||
size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort));
|
size += sizeof(quint32) + sizeof(qint32) + (cRecentEmojisPreload().isEmpty() ? cGetRecentEmojis().size() : cRecentEmojisPreload().size()) * (sizeof(uint64) + sizeof(ushort));
|
||||||
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
|
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
|
||||||
|
@ -1278,6 +1286,7 @@ namespace {
|
||||||
data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage());
|
data.stream << quint32(dbiCompressPastedImage) << qint32(cCompressPastedImage());
|
||||||
data.stream << quint32(dbiEmojiTab) << qint32(cEmojiTab());
|
data.stream << quint32(dbiEmojiTab) << qint32(cEmojiTab());
|
||||||
data.stream << quint32(dbiDialogLastPath) << cDialogLastPath();
|
data.stream << quint32(dbiDialogLastPath) << cDialogLastPath();
|
||||||
|
data.stream << quint32(dbiSongVolume) << qint32(qRound(cSongVolume() * 1e6));
|
||||||
|
|
||||||
{
|
{
|
||||||
RecentEmojisPreload v(cRecentEmojisPreload());
|
RecentEmojisPreload v(cRecentEmojisPreload());
|
||||||
|
|
|
@ -277,7 +277,7 @@ void TopBarWidget::showAll() {
|
||||||
resizeEvent(0);
|
resizeEvent(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PeerData *p = App::main() ? App::main()->profilePeer() : 0;
|
PeerData *p = App::main() ? App::main()->profilePeer() : 0, *o = App::main() ? App::main()->overviewPeer() : 0;
|
||||||
if (p && (p->chat || p->asUser()->contact >= 0)) {
|
if (p && (p->chat || p->asUser()->contact >= 0)) {
|
||||||
if (p->chat) {
|
if (p->chat) {
|
||||||
if (p->asChat()->forbidden) {
|
if (p->asChat()->forbidden) {
|
||||||
|
@ -324,7 +324,7 @@ void TopBarWidget::showAll() {
|
||||||
_mediaType.hide();
|
_mediaType.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (App::main() && App::main()->historyPeer() && !p && _clearSelection.isHidden() && !cWideMode()) {
|
if (App::main() && App::main()->historyPeer() && !o && !p && _clearSelection.isHidden() && !cWideMode()) {
|
||||||
_info.show();
|
_info.show();
|
||||||
} else {
|
} else {
|
||||||
_info.hide();
|
_info.hide();
|
||||||
|
@ -350,9 +350,12 @@ MainWidget *TopBarWidget::main() {
|
||||||
return static_cast<MainWidget*>(parentWidget());
|
return static_cast<MainWidget*>(parentWidget());
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWidget::MainWidget(Window *window) : QWidget(window), _started(0), failedObjId(0), _toForwardNameVersion(0), _dialogsWidth(st::dlgMinWidth),
|
MainWidget::MainWidget(Window *window) : QWidget(window),
|
||||||
dialogs(this), history(this), profile(0), overview(0), _topBar(this), _forwardConfirm(0), hider(0), _mediaType(this), _mediaTypeMask(0),
|
_started(0), failedObjId(0), _toForwardNameVersion(0), _dialogsWidth(st::dlgMinWidth),
|
||||||
updGoodPts(0), updLastPts(0), updPtsCount(0), updDate(0), updQts(-1), updSeq(0), updInited(false), updSkipPtsUpdateLevel(0), _onlineRequest(0), _lastWasOnline(false), _lastSetOnline(0), _isIdle(false),
|
dialogs(this), history(this), profile(0), overview(0), _player(this), _topBar(this),
|
||||||
|
_forwardConfirm(0), hider(0), _contentScrollAddToY(0), _playerHeight(0), _mediaType(this), _mediaTypeMask(0),
|
||||||
|
updGoodPts(0), updLastPts(0), updPtsCount(0), updDate(0), updQts(-1), updSeq(0), updInited(false), updSkipPtsUpdateLevel(0),
|
||||||
|
_onlineRequest(0), _lastWasOnline(false), _lastSetOnline(0), _isIdle(false),
|
||||||
_failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _background(0), _api(new ApiWrap(this)) {
|
_failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _background(0), _api(new ApiWrap(this)) {
|
||||||
setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight));
|
setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight));
|
||||||
|
|
||||||
|
@ -397,7 +400,10 @@ _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _backgr
|
||||||
App::wnd()->getTitle()->updateBackButton();
|
App::wnd()->getTitle()->updateBackButton();
|
||||||
_topBar.hide();
|
_topBar.hide();
|
||||||
|
|
||||||
|
_player.hide();
|
||||||
|
|
||||||
_topBar.raise();
|
_topBar.raise();
|
||||||
|
_player.raise();
|
||||||
dialogs.raise();
|
dialogs.raise();
|
||||||
_mediaType.raise();
|
_mediaType.raise();
|
||||||
|
|
||||||
|
@ -613,7 +619,7 @@ void MainWidget::noHider(HistoryHider *destroyed) {
|
||||||
onPeerShown(history.peer());
|
onPeerShown(history.peer());
|
||||||
if (profile || overview || (history.peer() && history.peer()->id)) {
|
if (profile || overview || (history.peer() && history.peer()->id)) {
|
||||||
dialogs.enableShadow(false);
|
dialogs.enableShadow(false);
|
||||||
QPixmap animCache = myGrab(this, QRect(0, st::topBarHeight, _dialogsWidth, height() - st::topBarHeight)),
|
QPixmap animCache = myGrab(this, QRect(0, _playerHeight + st::topBarHeight, _dialogsWidth, height() - _playerHeight - st::topBarHeight)),
|
||||||
animTopBarCache = myGrab(this, QRect(_topBar.x(), _topBar.y(), _topBar.width(), st::topBarHeight));
|
animTopBarCache = myGrab(this, QRect(_topBar.x(), _topBar.y(), _topBar.width(), st::topBarHeight));
|
||||||
dialogs.enableShadow();
|
dialogs.enableShadow();
|
||||||
_topBar.enableShadow();
|
_topBar.enableShadow();
|
||||||
|
@ -651,7 +657,7 @@ void MainWidget::hiderLayer(HistoryHider *h) {
|
||||||
|
|
||||||
hider->hide();
|
hider->hide();
|
||||||
dialogs.enableShadow(false);
|
dialogs.enableShadow(false);
|
||||||
QPixmap animCache = myGrab(this, QRect(0, 0, _dialogsWidth, height()));
|
QPixmap animCache = myGrab(this, QRect(0, _playerHeight, _dialogsWidth, height() - _playerHeight));
|
||||||
dialogs.enableShadow();
|
dialogs.enableShadow();
|
||||||
_topBar.enableShadow();
|
_topBar.enableShadow();
|
||||||
|
|
||||||
|
@ -1138,13 +1144,14 @@ void MainWidget::overviewPreloaded(PeerData *peer, const MTPmessages_Messages &r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaOverviewUpdated(peer);
|
mediaOverviewUpdated(peer, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::mediaOverviewUpdated(PeerData *peer) {
|
void MainWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
|
||||||
if (profile) profile->mediaOverviewUpdated(peer);
|
if (profile) profile->mediaOverviewUpdated(peer, type);
|
||||||
|
if (!_player.isHidden()) _player.mediaOverviewUpdated(peer, type);
|
||||||
if (overview && overview->peer() == peer) {
|
if (overview && overview->peer() == peer) {
|
||||||
overview->mediaOverviewUpdated(peer);
|
overview->mediaOverviewUpdated(peer, type);
|
||||||
|
|
||||||
int32 mask = 0;
|
int32 mask = 0;
|
||||||
History *h = peer ? App::historyLoaded(peer->id) : 0;
|
History *h = peer ? App::historyLoaded(peer->id) : 0;
|
||||||
|
@ -1336,7 +1343,7 @@ void MainWidget::photosLoaded(History *h, const MTPmessages_Messages &msgs, mtpR
|
||||||
h->_overview[type].push_front(item->id);
|
h->_overview[type].push_front(item->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (App::wnd()) App::wnd()->mediaOverviewUpdated(h->peer);
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(h->peer, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::partWasRead(PeerData *peer, const MTPmessages_AffectedHistory &result) {
|
void MainWidget::partWasRead(PeerData *peer, const MTPmessages_AffectedHistory &result) {
|
||||||
|
@ -1417,7 +1424,7 @@ void MainWidget::audioLoadProgress(mtpFileLoader *loader) {
|
||||||
AudioMsgId playing;
|
AudioMsgId playing;
|
||||||
AudioPlayerState state = AudioPlayerStopped;
|
AudioPlayerState state = AudioPlayerStopped;
|
||||||
audioPlayer()->currentState(&playing, &state);
|
audioPlayer()->currentState(&playing, &state);
|
||||||
if (playing.msgId == audio->openOnSaveMsgId && state != AudioPlayerStopped) {
|
if (playing.msgId == audio->openOnSaveMsgId && !(state & AudioPlayerStoppedMask) && state != AudioPlayerFinishing) {
|
||||||
audioPlayer()->pauseresume(OverviewAudios);
|
audioPlayer()->pauseresume(OverviewAudios);
|
||||||
} else {
|
} else {
|
||||||
audioPlayer()->play(AudioMsgId(audio, audio->openOnSaveMsgId));
|
audioPlayer()->play(AudioMsgId(audio, audio->openOnSaveMsgId));
|
||||||
|
@ -1480,9 +1487,12 @@ void MainWidget::audioPlayProgress(const AudioMsgId &audioId) {
|
||||||
|
|
||||||
void MainWidget::documentPlayProgress(const SongMsgId &songId) {
|
void MainWidget::documentPlayProgress(const SongMsgId &songId) {
|
||||||
SongMsgId playing;
|
SongMsgId playing;
|
||||||
AudioPlayerState state = AudioPlayerStopped;
|
AudioPlayerState playingState = AudioPlayerStopped;
|
||||||
audioPlayer()->currentState(&playing, &state);
|
int64 playingPosition = 0, playingDuration = 0;
|
||||||
if (playing == songId && state == AudioPlayerStoppedAtStart) {
|
int32 playingFrequency = 0;
|
||||||
|
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
|
||||||
|
if (playing == songId && playingState == AudioPlayerStoppedAtStart) {
|
||||||
|
playingState = AudioPlayerStopped;
|
||||||
audioPlayer()->clearStoppedAtStart(songId);
|
audioPlayer()->clearStoppedAtStart(songId);
|
||||||
|
|
||||||
DocumentData *document = songId.song;
|
DocumentData *document = songId.song;
|
||||||
|
@ -1518,11 +1528,33 @@ void MainWidget::documentPlayProgress(const SongMsgId &songId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (playing == songId) {
|
||||||
|
_player.updateState(playing, playingState, playingPosition, playingDuration, playingFrequency);
|
||||||
|
|
||||||
|
if (!(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||||
|
if (_player.isHidden()) {
|
||||||
|
_player.clearSelection();
|
||||||
|
_player.show();
|
||||||
|
_playerHeight = _contentScrollAddToY = _player.height();
|
||||||
|
resizeEvent(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (HistoryItem *item = App::histItemById(songId.msgId)) {
|
if (HistoryItem *item = App::histItemById(songId.msgId)) {
|
||||||
msgUpdated(item->history()->peer->id, item);
|
msgUpdated(item->history()->peer->id, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWidget::hidePlayer() {
|
||||||
|
if (!_player.isHidden()) {
|
||||||
|
_player.hide();
|
||||||
|
_contentScrollAddToY = -_player.height();
|
||||||
|
_playerHeight = 0;
|
||||||
|
resizeEvent(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWidget::audioLoadFailed(mtpFileLoader *loader, bool started) {
|
void MainWidget::audioLoadFailed(mtpFileLoader *loader, bool started) {
|
||||||
loadFailed(loader, started, SLOT(audioLoadRetry()));
|
loadFailed(loader, started, SLOT(audioLoadRetry()));
|
||||||
AudioData *audio = App::audio(loader->objId());
|
AudioData *audio = App::audio(loader->objId());
|
||||||
|
@ -1552,10 +1584,12 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
|
||||||
SongMsgId playing;
|
SongMsgId playing;
|
||||||
AudioPlayerState playingState = AudioPlayerStopped;
|
AudioPlayerState playingState = AudioPlayerStopped;
|
||||||
audioPlayer()->currentState(&playing, &playingState);
|
audioPlayer()->currentState(&playing, &playingState);
|
||||||
if (playing.msgId == item->id && playingState != AudioPlayerStopped) {
|
if (playing.msgId == item->id && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||||
audioPlayer()->pauseresume(OverviewDocuments);
|
audioPlayer()->pauseresume(OverviewDocuments);
|
||||||
} else {
|
} else {
|
||||||
audioPlayer()->play(SongMsgId(document, item->id));
|
SongMsgId song(document, item->id);
|
||||||
|
audioPlayer()->play(song);
|
||||||
|
if (App::main()) App::main()->documentPlayProgress(song);
|
||||||
}
|
}
|
||||||
} else if(document->openOnSave > 0 && document->size < MediaViewImageSizeLimit) {
|
} else if(document->openOnSave > 0 && document->size < MediaViewImageSizeLimit) {
|
||||||
QImageReader reader(already);
|
QImageReader reader(already);
|
||||||
|
@ -1589,6 +1623,21 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
App::wnd()->documentUpdated(document);
|
App::wnd()->documentUpdated(document);
|
||||||
|
|
||||||
|
if (audioPlayer()) {
|
||||||
|
SongMsgId playing;
|
||||||
|
AudioPlayerState playingState = AudioPlayerStopped;
|
||||||
|
int64 playingPosition = 0, playingDuration = 0;
|
||||||
|
int32 playingFrequency = 0;
|
||||||
|
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
|
||||||
|
if (playing.song == document && !_player.isHidden()) {
|
||||||
|
if (document->loader) {
|
||||||
|
_player.updateState(playing, playingState, playingPosition, playingDuration, playingFrequency);
|
||||||
|
} else {
|
||||||
|
audioPlayer()->play(playing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::documentLoadFailed(mtpFileLoader *loader, bool started) {
|
void MainWidget::documentLoadFailed(mtpFileLoader *loader, bool started) {
|
||||||
|
@ -1848,19 +1897,19 @@ void MainWidget::showPeer(quint64 peerId, qint32 msgId, bool back, bool force) {
|
||||||
hider = 0;
|
hider = 0;
|
||||||
}
|
}
|
||||||
if (force || !selectingPeer()) {
|
if (force || !selectingPeer()) {
|
||||||
if (!animating() && ((history.isHidden() && (profile || overview)) || (!cWideMode() && (history.isHidden() || !peerId)))) {
|
if (!animating() && ((history.isHidden() && history.activePeer() && (profile || overview)) || (!cWideMode() && (history.isHidden() || !peerId)))) {
|
||||||
dialogs.enableShadow(false);
|
dialogs.enableShadow(false);
|
||||||
if (peerId) {
|
if (peerId) {
|
||||||
_topBar.enableShadow(false);
|
_topBar.enableShadow(false);
|
||||||
if (cWideMode()) {
|
if (cWideMode()) {
|
||||||
animCache = myGrab(this, QRect(_dialogsWidth, st::topBarHeight, width() - _dialogsWidth, height() - st::topBarHeight));
|
animCache = myGrab(this, QRect(_dialogsWidth, _playerHeight + st::topBarHeight, width() - _dialogsWidth, height() - _playerHeight - st::topBarHeight));
|
||||||
} else {
|
} else {
|
||||||
animCache = myGrab(this, QRect(0, st::topBarHeight, _dialogsWidth, height() - st::topBarHeight));
|
animCache = myGrab(this, QRect(0, _playerHeight + st::topBarHeight, _dialogsWidth, height() - _playerHeight - st::topBarHeight));
|
||||||
}
|
}
|
||||||
} else if (cWideMode()) {
|
} else if (cWideMode()) {
|
||||||
animCache = myGrab(this, QRect(_dialogsWidth, 0, width() - _dialogsWidth, height()));
|
animCache = myGrab(this, QRect(_dialogsWidth, _playerHeight, width() - _dialogsWidth, height() - _playerHeight));
|
||||||
} else {
|
} else {
|
||||||
animCache = myGrab(this, QRect(0, 0, _dialogsWidth, height()));
|
animCache = myGrab(this, QRect(0, _playerHeight, _dialogsWidth, height() - _playerHeight));
|
||||||
}
|
}
|
||||||
if (peerId || cWideMode()) {
|
if (peerId || cWideMode()) {
|
||||||
animTopBarCache = myGrab(this, QRect(_topBar.x(), _topBar.y(), _topBar.width(), st::topBarHeight));
|
animTopBarCache = myGrab(this, QRect(_topBar.x(), _topBar.y(), _topBar.width(), st::topBarHeight));
|
||||||
|
@ -1909,6 +1958,8 @@ void MainWidget::showPeer(quint64 peerId, qint32 msgId, bool back, bool force) {
|
||||||
history.show();
|
history.show();
|
||||||
if (!animCache.isNull()) {
|
if (!animCache.isNull()) {
|
||||||
history.animShow(animCache, animTopBarCache, back);
|
history.animShow(animCache, animTopBarCache, back);
|
||||||
|
} else {
|
||||||
|
QTimer::singleShot(0, this, SLOT(setInnerFocus()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1958,8 +2009,12 @@ PeerData *MainWidget::profilePeer() {
|
||||||
return profile ? profile->peer() : 0;
|
return profile ? profile->peer() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PeerData *MainWidget::overviewPeer() {
|
||||||
|
return overview ? overview->peer() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool MainWidget::mediaTypeSwitch() {
|
bool MainWidget::mediaTypeSwitch() {
|
||||||
if (!overview) return false;
|
if (!overview || (overview->type() == OverviewAudioDocuments)) return false;
|
||||||
|
|
||||||
for (int32 i = 0; i < OverviewCount; ++i) {
|
for (int32 i = 0; i < OverviewCount; ++i) {
|
||||||
if (!(_mediaTypeMask & ~(1 << i))) {
|
if (!(_mediaTypeMask & ~(1 << i))) {
|
||||||
|
@ -1974,13 +2029,21 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
|
||||||
if (overview && overview->peer() == peer) {
|
if (overview && overview->peer() == peer) {
|
||||||
if (overview->type() != type) {
|
if (overview->type() != type) {
|
||||||
overview->switchType(type);
|
overview->switchType(type);
|
||||||
|
} else if (type == OverviewAudioDocuments) { // hack for player
|
||||||
|
showBackFromStack();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dialogs.enableShadow(false);
|
dialogs.enableShadow(false);
|
||||||
_topBar.enableShadow(false);
|
_topBar.enableShadow(false);
|
||||||
QPixmap animCache = myGrab(this, history.geometry()), animTopBarCache = myGrab(this, QRect(_topBar.x(), _topBar.y(), _topBar.width(), st::topBarHeight));
|
QRect topBarRect = QRect(_topBar.x(), _topBar.y(), _topBar.width(), st::topBarHeight);
|
||||||
|
QRect historyRect = QRect(history.x(), topBarRect.y() + topBarRect.height(), history.width(), history.y() + history.height() - topBarRect.y() - topBarRect.height());
|
||||||
|
QPixmap animCache, animTopBarCache;
|
||||||
|
if (!animating() && (!cWideMode() || profile || overview || history.peer())) {
|
||||||
|
animCache = myGrab(this, historyRect);
|
||||||
|
animTopBarCache = myGrab(this, topBarRect);
|
||||||
|
}
|
||||||
dialogs.enableShadow();
|
dialogs.enableShadow();
|
||||||
_topBar.enableShadow();
|
_topBar.enableShadow();
|
||||||
if (!back) {
|
if (!back) {
|
||||||
|
@ -1988,7 +2051,7 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
|
||||||
_stack.push_back(new StackItemOverview(overview->peer(), overview->type(), overview->lastWidth(), overview->lastScrollTop()));
|
_stack.push_back(new StackItemOverview(overview->peer(), overview->type(), overview->lastWidth(), overview->lastScrollTop()));
|
||||||
} else if (profile) {
|
} else if (profile) {
|
||||||
_stack.push_back(new StackItemProfile(profile->peer(), profile->lastScrollTop(), profile->allMediaShown()));
|
_stack.push_back(new StackItemProfile(profile->peer(), profile->lastScrollTop(), profile->allMediaShown()));
|
||||||
} else {
|
} else if (history.peer()) {
|
||||||
_stack.push_back(new StackItemHistory(history.peer(), history.lastWidth(), history.lastScrollTop(), history.replyReturns(), history.kbWasHidden()));
|
_stack.push_back(new StackItemHistory(history.peer(), history.lastWidth(), history.lastScrollTop(), history.replyReturns(), history.kbWasHidden()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2009,12 +2072,19 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool
|
||||||
_mediaTypeMask = 0;
|
_mediaTypeMask = 0;
|
||||||
_topBar.show();
|
_topBar.show();
|
||||||
resizeEvent(0);
|
resizeEvent(0);
|
||||||
mediaOverviewUpdated(peer);
|
mediaOverviewUpdated(peer, type);
|
||||||
overview->animShow(animCache, animTopBarCache, back, lastScrollTop);
|
if (!animCache.isNull()) {
|
||||||
|
overview->animShow(animCache, animTopBarCache, back, lastScrollTop);
|
||||||
|
} else {
|
||||||
|
overview->show();
|
||||||
|
overview->activate();
|
||||||
|
}
|
||||||
history.animStop();
|
history.animStop();
|
||||||
history.showPeer(0, 0, false, true);
|
history.showPeer(0, 0, false, true);
|
||||||
history.hide();
|
history.hide();
|
||||||
|
if (!cWideMode()) dialogs.hide();
|
||||||
_topBar.raise();
|
_topBar.raise();
|
||||||
|
_player.raise();
|
||||||
dialogs.raise();
|
dialogs.raise();
|
||||||
_mediaType.raise();
|
_mediaType.raise();
|
||||||
if (hider) hider->raise();
|
if (hider) hider->raise();
|
||||||
|
@ -2060,6 +2130,7 @@ void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop,
|
||||||
history.showPeer(0, 0, false, true);
|
history.showPeer(0, 0, false, true);
|
||||||
history.hide();
|
history.hide();
|
||||||
_topBar.raise();
|
_topBar.raise();
|
||||||
|
_player.raise();
|
||||||
dialogs.raise();
|
dialogs.raise();
|
||||||
_mediaType.raise();
|
_mediaType.raise();
|
||||||
if (hider) hider->raise();
|
if (hider) hider->raise();
|
||||||
|
@ -2067,7 +2138,16 @@ void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop,
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::showBackFromStack() {
|
void MainWidget::showBackFromStack() {
|
||||||
if (_stack.isEmpty() || selectingPeer()) return;
|
if (selectingPeer()) return;
|
||||||
|
if (_stack.isEmpty()) {
|
||||||
|
if (cWideMode()) {
|
||||||
|
showPeer(0, 0, false, true);
|
||||||
|
QTimer::singleShot(0, this, SLOT(setInnerFocus()));
|
||||||
|
} else {
|
||||||
|
onShowDialogs();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
StackItem *item = _stack.back();
|
StackItem *item = _stack.back();
|
||||||
_stack.pop_back();
|
_stack.pop_back();
|
||||||
if (item->type() == HistoryStackItem) {
|
if (item->type() == HistoryStackItem) {
|
||||||
|
@ -2313,19 +2393,26 @@ void MainWidget::resizeEvent(QResizeEvent *e) {
|
||||||
if (cWideMode()) {
|
if (cWideMode()) {
|
||||||
_dialogsWidth = snap<int>((width() * 5) / 14, st::dlgMinWidth, st::dlgMaxWidth);
|
_dialogsWidth = snap<int>((width() * 5) / 14, st::dlgMinWidth, st::dlgMaxWidth);
|
||||||
dialogs.setGeometry(0, 0, _dialogsWidth + st::dlgShadow, height());
|
dialogs.setGeometry(0, 0, _dialogsWidth + st::dlgShadow, height());
|
||||||
_topBar.setGeometry(_dialogsWidth, 0, width() - _dialogsWidth, st::topBarHeight + st::titleShadow);
|
_player.setGeometry(_dialogsWidth, 0, width() - _dialogsWidth, _player.height());
|
||||||
history.setGeometry(_dialogsWidth, tbh, width() - _dialogsWidth, height() - tbh);
|
_topBar.setGeometry(_dialogsWidth, _playerHeight, width() - _dialogsWidth, st::topBarHeight + st::titleShadow);
|
||||||
|
history.setGeometry(_dialogsWidth, _playerHeight + tbh, width() - _dialogsWidth, height() - _playerHeight - tbh);
|
||||||
if (hider) hider->setGeometry(QRect(_dialogsWidth, 0, width() - _dialogsWidth, height()));
|
if (hider) hider->setGeometry(QRect(_dialogsWidth, 0, width() - _dialogsWidth, height()));
|
||||||
} else {
|
} else {
|
||||||
_dialogsWidth = width();
|
_dialogsWidth = width();
|
||||||
dialogs.setGeometry(0, 0, _dialogsWidth + st::dlgShadow, height());
|
_player.setGeometry(0, 0, _dialogsWidth, _player.height());
|
||||||
_topBar.setGeometry(0, 0, _dialogsWidth, st::topBarHeight + st::titleShadow);
|
dialogs.setGeometry(0, _playerHeight, _dialogsWidth + st::dlgShadow, height() - _playerHeight);
|
||||||
history.setGeometry(0, tbh, _dialogsWidth, height() - tbh);
|
_topBar.setGeometry(0, _playerHeight, _dialogsWidth, st::topBarHeight + st::titleShadow);
|
||||||
|
history.setGeometry(0, _playerHeight + tbh, _dialogsWidth, height() - _playerHeight - tbh);
|
||||||
if (hider) hider->setGeometry(QRect(0, 0, _dialogsWidth, height()));
|
if (hider) hider->setGeometry(QRect(0, 0, _dialogsWidth, height()));
|
||||||
}
|
}
|
||||||
_mediaType.move(width() - _mediaType.width(), st::topBarHeight);
|
_mediaType.move(width() - _mediaType.width(), _playerHeight + st::topBarHeight);
|
||||||
if (profile) profile->setGeometry(history.geometry());
|
if (profile) profile->setGeometry(history.geometry());
|
||||||
if (overview) overview->setGeometry(history.geometry());
|
if (overview) overview->setGeometry(history.geometry());
|
||||||
|
_contentScrollAddToY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 MainWidget::contentScrollAddToY() const {
|
||||||
|
return _contentScrollAddToY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::keyPressEvent(QKeyEvent *e) {
|
void MainWidget::keyPressEvent(QKeyEvent *e) {
|
||||||
|
@ -2355,8 +2442,14 @@ void MainWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWidget::topBarShadowParams(int32 &x, float64 &o) {
|
void MainWidget::topBarShadowParams(int32 &x, float64 &o) {
|
||||||
if (!profile && !overview && dialogs.isHidden()) {
|
if (!cWideMode() && dialogs.isHidden()) {
|
||||||
history.topBarShadowParams(x, o);
|
if (profile) {
|
||||||
|
if (!history.activePeer()) profile->topBarShadowParams(x, o);
|
||||||
|
} else if (overview) {
|
||||||
|
if (!history.activePeer()) overview->topBarShadowParams(x, o);
|
||||||
|
} else {
|
||||||
|
history.topBarShadowParams(x, o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2384,6 +2477,10 @@ TopBarWidget *MainWidget::topBar() {
|
||||||
return &_topBar;
|
return &_topBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlayerWidget *MainWidget::player() {
|
||||||
|
return &_player;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWidget::onTopBarClick() {
|
void MainWidget::onTopBarClick() {
|
||||||
if (profile) {
|
if (profile) {
|
||||||
profile->topBarClick();
|
profile->topBarClick();
|
||||||
|
@ -3451,7 +3548,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
App::markPeerUpdated(user);
|
App::markPeerUpdated(user);
|
||||||
if (App::wnd()) App::wnd()->mediaOverviewUpdated(user);
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(user, OverviewCount);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||||
#include "historywidget.h"
|
#include "historywidget.h"
|
||||||
#include "profilewidget.h"
|
#include "profilewidget.h"
|
||||||
#include "overviewwidget.h"
|
#include "overviewwidget.h"
|
||||||
|
#include "playerwidget.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
|
||||||
class Window;
|
class Window;
|
||||||
|
@ -189,6 +190,9 @@ public:
|
||||||
void topBarShadowParams(int32 &x, float64 &o);
|
void topBarShadowParams(int32 &x, float64 &o);
|
||||||
TopBarWidget *topBar();
|
TopBarWidget *topBar();
|
||||||
|
|
||||||
|
PlayerWidget *player();
|
||||||
|
int32 contentScrollAddToY() const;
|
||||||
|
|
||||||
void animShow(const QPixmap &bgAnimCache, bool back = false);
|
void animShow(const QPixmap &bgAnimCache, bool back = false);
|
||||||
bool animStep(float64 ms);
|
bool animStep(float64 ms);
|
||||||
|
|
||||||
|
@ -233,6 +237,7 @@ public:
|
||||||
PeerData *activePeer();
|
PeerData *activePeer();
|
||||||
MsgId activeMsgId();
|
MsgId activeMsgId();
|
||||||
PeerData *profilePeer();
|
PeerData *profilePeer();
|
||||||
|
PeerData *overviewPeer();
|
||||||
bool mediaTypeSwitch();
|
bool mediaTypeSwitch();
|
||||||
void showPeerProfile(PeerData *peer, bool back = false, int32 lastScrollTop = -1, bool allMediaShown = false);
|
void showPeerProfile(PeerData *peer, bool back = false, int32 lastScrollTop = -1, bool allMediaShown = false);
|
||||||
void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1);
|
void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1);
|
||||||
|
@ -313,7 +318,7 @@ public:
|
||||||
|
|
||||||
void searchMessages(const QString &query);
|
void searchMessages(const QString &query);
|
||||||
void preloadOverviews(PeerData *peer);
|
void preloadOverviews(PeerData *peer);
|
||||||
void mediaOverviewUpdated(PeerData *peer);
|
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
|
||||||
void changingMsgId(HistoryItem *row, MsgId newId);
|
void changingMsgId(HistoryItem *row, MsgId newId);
|
||||||
void itemRemoved(HistoryItem *item);
|
void itemRemoved(HistoryItem *item);
|
||||||
void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem);
|
void itemReplaced(HistoryItem *oldItem, HistoryItem *newItem);
|
||||||
|
@ -391,6 +396,7 @@ public slots:
|
||||||
void documentLoadFailed(mtpFileLoader *loader, bool started);
|
void documentLoadFailed(mtpFileLoader *loader, bool started);
|
||||||
void documentLoadRetry();
|
void documentLoadRetry();
|
||||||
void documentPlayProgress(const SongMsgId &songId);
|
void documentPlayProgress(const SongMsgId &songId);
|
||||||
|
void hidePlayer();
|
||||||
|
|
||||||
void setInnerFocus();
|
void setInnerFocus();
|
||||||
void dialogsCancelled();
|
void dialogsCancelled();
|
||||||
|
@ -490,12 +496,16 @@ private:
|
||||||
HistoryWidget history;
|
HistoryWidget history;
|
||||||
ProfileWidget *profile;
|
ProfileWidget *profile;
|
||||||
OverviewWidget *overview;
|
OverviewWidget *overview;
|
||||||
|
PlayerWidget _player;
|
||||||
TopBarWidget _topBar;
|
TopBarWidget _topBar;
|
||||||
ConfirmBox *_forwardConfirm; // for narrow mode
|
ConfirmBox *_forwardConfirm; // for narrow mode
|
||||||
HistoryHider *hider;
|
HistoryHider *hider;
|
||||||
StackItems _stack;
|
StackItems _stack;
|
||||||
QPixmap profileAnimCache;
|
QPixmap profileAnimCache;
|
||||||
|
|
||||||
|
int32 _playerHeight;
|
||||||
|
int32 _contentScrollAddToY;
|
||||||
|
|
||||||
Dropdown _mediaType;
|
Dropdown _mediaType;
|
||||||
int32 _mediaTypeMask;
|
int32 _mediaTypeMask;
|
||||||
|
|
||||||
|
|
|
@ -136,19 +136,19 @@ void MediaView::moveToScreen() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 navSkip = 2 * st::mvControlMargin + st::mvControlSize;
|
int32 navSkip = 2 * st::mvControlMargin + st::mvControlSize;
|
||||||
_closeNav = rtlrect(width() - st::mvControlMargin - st::mvControlSize, st::mvControlMargin, st::mvControlSize, st::mvControlSize, width());
|
_closeNav = myrtlrect(width() - st::mvControlMargin - st::mvControlSize, st::mvControlMargin, st::mvControlSize, st::mvControlSize);
|
||||||
_closeNavIcon = centersprite(_closeNav, st::mvClose);
|
_closeNavIcon = centersprite(_closeNav, st::mvClose);
|
||||||
_leftNav = rtlrect(st::mvControlMargin, navSkip, st::mvControlSize, height() - 2 * navSkip, width());
|
_leftNav = myrtlrect(st::mvControlMargin, navSkip, st::mvControlSize, height() - 2 * navSkip);
|
||||||
_leftNavIcon = centersprite(_leftNav, st::mvLeft);
|
_leftNavIcon = centersprite(_leftNav, st::mvLeft);
|
||||||
_rightNav = rtlrect(width() - st::mvControlMargin - st::mvControlSize, navSkip, st::mvControlSize, height() - 2 * navSkip, width());
|
_rightNav = myrtlrect(width() - st::mvControlMargin - st::mvControlSize, navSkip, st::mvControlSize, height() - 2 * navSkip);
|
||||||
_rightNavIcon = centersprite(_rightNav, st::mvRight);
|
_rightNavIcon = centersprite(_rightNav, st::mvRight);
|
||||||
|
|
||||||
_saveMsg.moveTo((width() - _saveMsg.width()) / 2, (height() - _saveMsg.height()) / 2);
|
_saveMsg.moveTo((width() - _saveMsg.width()) / 2, (height() - _saveMsg.height()) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaView::mediaOverviewUpdated(PeerData *peer) {
|
void MediaView::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
|
||||||
if (!_photo && !_doc) return;
|
if (!_photo && !_doc) return;
|
||||||
if (_history && _history->peer == peer) {
|
if (_history && _history->peer == peer && type == _overview) {
|
||||||
_index = -1;
|
_index = -1;
|
||||||
for (int i = 0, l = _history->_overview[_overview].size(); i < l; ++i) {
|
for (int i = 0, l = _history->_overview[_overview].size(); i < l; ++i) {
|
||||||
if (_history->_overview[_overview].at(i) == _msgid) {
|
if (_history->_overview[_overview].at(i) == _msgid) {
|
||||||
|
@ -158,7 +158,7 @@ void MediaView::mediaOverviewUpdated(PeerData *peer) {
|
||||||
}
|
}
|
||||||
updateControls();
|
updateControls();
|
||||||
preloadData(0);
|
preloadData(0);
|
||||||
} else if (_user == peer) {
|
} else if (_user == peer && type == OverviewCount) {
|
||||||
if (!_photo) return;
|
if (!_photo) return;
|
||||||
|
|
||||||
_index = -1;
|
_index = -1;
|
||||||
|
@ -192,7 +192,7 @@ void MediaView::changingMsgId(HistoryItem *row, MsgId newId) {
|
||||||
if (row->id == _msgid) {
|
if (row->id == _msgid) {
|
||||||
_msgid = newId;
|
_msgid = newId;
|
||||||
}
|
}
|
||||||
mediaOverviewUpdated(row->history()->peer);
|
mediaOverviewUpdated(row->history()->peer, _overview);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaView::updateDocSize() {
|
void MediaView::updateDocSize() {
|
||||||
|
@ -258,9 +258,9 @@ void MediaView::updateControls() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_saveVisible = ((_photo && _photo->full->loaded()) || (_doc && (!_doc->already(true).isEmpty() || (_current.isNull() && _currentGif.isNull()))));
|
_saveVisible = ((_photo && _photo->full->loaded()) || (_doc && (!_doc->already(true).isEmpty() || (_current.isNull() && _currentGif.isNull()))));
|
||||||
_saveNav = rtlrect(width() - st::mvIconSize.width() * 2, height() - st::mvIconSize.height(), st::mvIconSize.width(), st::mvIconSize.height(), width());
|
_saveNav = myrtlrect(width() - st::mvIconSize.width() * 2, height() - st::mvIconSize.height(), st::mvIconSize.width(), st::mvIconSize.height());
|
||||||
_saveNavIcon = centersprite(_saveNav, st::mvSave);
|
_saveNavIcon = centersprite(_saveNav, st::mvSave);
|
||||||
_moreNav = rtlrect(width() - st::mvIconSize.width(), height() - st::mvIconSize.height(), st::mvIconSize.width(), st::mvIconSize.height(), width());
|
_moreNav = myrtlrect(width() - st::mvIconSize.width(), height() - st::mvIconSize.height(), st::mvIconSize.width(), st::mvIconSize.height());
|
||||||
_moreNavIcon = centersprite(_moreNav, st::mvMore);
|
_moreNavIcon = centersprite(_moreNav, st::mvMore);
|
||||||
|
|
||||||
QDateTime d(date(_photo ? _photo->date : _doc->date)), dNow(date(unixtime()));
|
QDateTime d(date(_photo ? _photo->date : _doc->date)), dNow(date(unixtime()));
|
||||||
|
@ -273,11 +273,11 @@ void MediaView::updateControls() {
|
||||||
}
|
}
|
||||||
if (_from) {
|
if (_from) {
|
||||||
_fromName.setText(st::mvFont, _from->name);
|
_fromName.setText(st::mvFont, _from->name);
|
||||||
_nameNav = rtlrect(st::mvTextLeft, height() - st::mvTextTop, qMin(_fromName.maxWidth(), width() / 3), st::mvFont->height, width());
|
_nameNav = myrtlrect(st::mvTextLeft, height() - st::mvTextTop, qMin(_fromName.maxWidth(), width() / 3), st::mvFont->height);
|
||||||
_dateNav = rtlrect(st::mvTextLeft + _nameNav.width() + st::mvTextSkip, height() - st::mvTextTop, st::mvFont->m.width(_dateText), st::mvFont->height, width());
|
_dateNav = myrtlrect(st::mvTextLeft + _nameNav.width() + st::mvTextSkip, height() - st::mvTextTop, st::mvFont->m.width(_dateText), st::mvFont->height);
|
||||||
} else {
|
} else {
|
||||||
_nameNav = QRect();
|
_nameNav = QRect();
|
||||||
_dateNav = rtlrect(st::mvTextLeft, height() - st::mvTextTop, st::mvFont->m.width(_dateText), st::mvFont->height, width());
|
_dateNav = myrtlrect(st::mvTextLeft, height() - st::mvTextTop, st::mvFont->m.width(_dateText), st::mvFont->height);
|
||||||
}
|
}
|
||||||
updateHeader();
|
updateHeader();
|
||||||
if (_photo) {
|
if (_photo) {
|
||||||
|
@ -349,7 +349,6 @@ bool MediaView::animStep(float64 msp) {
|
||||||
a_cOpacity.finish();
|
a_cOpacity.finish();
|
||||||
_controlsState = (_controlsState == ControlsShowing ? ControlsShown : ControlsHidden);
|
_controlsState = (_controlsState == ControlsShowing ? ControlsShown : ControlsHidden);
|
||||||
setCursor(_controlsState == ControlsHidden ? Qt::BlankCursor : (_over == OverNone ? style::cur_default : style::cur_pointer));
|
setCursor(_controlsState == ControlsHidden ? Qt::BlankCursor : (_over == OverNone ? style::cur_default : style::cur_pointer));
|
||||||
LOG(("Finished with controls!"));
|
|
||||||
} else {
|
} else {
|
||||||
a_cOpacity.update(dt, anim::linear);
|
a_cOpacity.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
|
@ -410,7 +409,6 @@ void MediaView::close() {
|
||||||
void MediaView::activateControls() {
|
void MediaView::activateControls() {
|
||||||
_controlsHideTimer.start(int(st::mvWaitHide));
|
_controlsHideTimer.start(int(st::mvWaitHide));
|
||||||
if (_controlsState == ControlsHiding || _controlsState == ControlsHidden) {
|
if (_controlsState == ControlsHiding || _controlsState == ControlsHidden) {
|
||||||
LOG(("Showing controls.."));
|
|
||||||
_controlsState = ControlsShowing;
|
_controlsState = ControlsShowing;
|
||||||
_controlsAnimStarted = getms();
|
_controlsAnimStarted = getms();
|
||||||
a_cOpacity.start(1);
|
a_cOpacity.start(1);
|
||||||
|
@ -421,7 +419,6 @@ void MediaView::activateControls() {
|
||||||
void MediaView::onHideControls(bool force) {
|
void MediaView::onHideControls(bool force) {
|
||||||
if (!force && !_dropdown.isHidden()) return;
|
if (!force && !_dropdown.isHidden()) return;
|
||||||
if (_controlsState == ControlsHiding || _controlsState == ControlsHidden) return;
|
if (_controlsState == ControlsHiding || _controlsState == ControlsHidden) return;
|
||||||
LOG(("Hiding controls.."));
|
|
||||||
_controlsState = ControlsHiding;
|
_controlsState = ControlsHiding;
|
||||||
_controlsAnimStarted = getms();
|
_controlsAnimStarted = getms();
|
||||||
a_cOpacity.start(0);
|
a_cOpacity.start(0);
|
||||||
|
@ -906,7 +903,7 @@ void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) {
|
||||||
// _docSize is updated in updateControls()
|
// _docSize is updated in updateControls()
|
||||||
|
|
||||||
_docRect = QRect((width() - st::mvDocSize.width()) / 2, (height() - st::mvDocSize.height()) / 2, st::mvDocSize.width(), st::mvDocSize.height());
|
_docRect = QRect((width() - st::mvDocSize.width()) / 2, (height() - st::mvDocSize.height()) / 2, st::mvDocSize.width(), st::mvDocSize.height());
|
||||||
_docIconRect = rtlrect(_docRect.x() + st::mvDocPadding, _docRect.y() + st::mvDocPadding, st::mvDocBlue.pxWidth(), st::mvDocBlue.pxHeight(), width());
|
_docIconRect = myrtlrect(_docRect.x() + st::mvDocPadding, _docRect.y() + st::mvDocPadding, st::mvDocBlue.pxWidth(), st::mvDocBlue.pxHeight());
|
||||||
} else if (!_current.isNull()) {
|
} else if (!_current.isNull()) {
|
||||||
_current.setDevicePixelRatio(cRetinaFactor());
|
_current.setDevicePixelRatio(cRetinaFactor());
|
||||||
_w = _current.width() / cIntRetinaFactor();
|
_w = _current.width() / cIntRetinaFactor();
|
||||||
|
@ -1264,11 +1261,6 @@ void MediaView::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static uint64 t = getms();
|
|
||||||
// uint64 t2 = getms();
|
|
||||||
// LOG(("paint: %1, wait: %2, name: %3, icon: %4").arg(t2 - ms).arg(t2 - t).arg(logBool(name)).arg(logBool(icon)));
|
|
||||||
// t = t2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaView::keyPressEvent(QKeyEvent *e) {
|
void MediaView::keyPressEvent(QKeyEvent *e) {
|
||||||
|
@ -1828,7 +1820,7 @@ void MediaView::findCurrent() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_history->_overviewCount[_overview] < 0) {
|
if (_history->_overviewCount[_overview] < 0 || (!_index && _history->_overviewCount[_overview] > 0)) {
|
||||||
loadBack();
|
loadBack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1877,7 +1869,7 @@ void MediaView::userPhotosLoaded(UserData *u, const MTPphotos_Photos &photos, mt
|
||||||
photo->thumb->load();
|
photo->thumb->load();
|
||||||
u->photos.push_back(photo);
|
u->photos.push_back(photo);
|
||||||
}
|
}
|
||||||
if (App::wnd()) App::wnd()->mediaOverviewUpdated(u);
|
if (App::wnd()) App::wnd()->mediaOverviewUpdated(u, OverviewCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaView::updateHeader() {
|
void MediaView::updateHeader() {
|
||||||
|
@ -1913,7 +1905,7 @@ void MediaView::updateHeader() {
|
||||||
hwidth = width() / 3;
|
hwidth = width() / 3;
|
||||||
_headerText = st::mvThickFont->m.elidedText(_headerText, Qt::ElideMiddle, hwidth);
|
_headerText = st::mvThickFont->m.elidedText(_headerText, Qt::ElideMiddle, hwidth);
|
||||||
}
|
}
|
||||||
_headerNav = rtlrect(st::mvTextLeft, height() - st::mvHeaderTop, hwidth, st::mvThickFont->height, width());
|
_headerNav = myrtlrect(st::mvTextLeft, height() - st::mvHeaderTop, hwidth, st::mvThickFont->height);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//void MediaView::updatePolaroid() {
|
//void MediaView::updatePolaroid() {
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
updateOver(mapFromGlobal(QCursor::pos()));
|
updateOver(mapFromGlobal(QCursor::pos()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void mediaOverviewUpdated(PeerData *peer);
|
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
|
||||||
void documentUpdated(DocumentData *doc);
|
void documentUpdated(DocumentData *doc);
|
||||||
void changingMsgId(HistoryItem *row, MsgId newId);
|
void changingMsgId(HistoryItem *row, MsgId newId);
|
||||||
void updateDocSize();
|
void updateDocSize();
|
||||||
|
|
|
@ -1681,8 +1681,12 @@ void OverviewWidget::onScroll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverviewWidget::resizeEvent(QResizeEvent *e) {
|
void OverviewWidget::resizeEvent(QResizeEvent *e) {
|
||||||
|
int32 st = _scroll.scrollTop();
|
||||||
_scroll.resize(size());
|
_scroll.resize(size());
|
||||||
int32 newScrollTop = _inner.resizeToWidth(width(), _scroll.scrollTop(), height());
|
int32 newScrollTop = _inner.resizeToWidth(width(), st, height());
|
||||||
|
if (int32 addToY = App::main() ? App::main()->contentScrollAddToY() : 0) {
|
||||||
|
newScrollTop += addToY;
|
||||||
|
}
|
||||||
if (newScrollTop != _scroll.scrollTop()) {
|
if (newScrollTop != _scroll.scrollTop()) {
|
||||||
_noDropResizeIndex = true;
|
_noDropResizeIndex = true;
|
||||||
_scroll.scrollToY(newScrollTop);
|
_scroll.scrollToY(newScrollTop);
|
||||||
|
@ -1700,33 +1704,36 @@ void OverviewWidget::paintEvent(QPaintEvent *e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasTopBar = !App::main()->topBar()->isHidden();
|
|
||||||
QRect r(e->rect());
|
QRect r(e->rect());
|
||||||
if (type() == OverviewPhotos) {
|
if (type() == OverviewPhotos) {
|
||||||
p.fillRect(r, st::white->b);
|
p.fillRect(r, st::white->b);
|
||||||
} else if (cTileBackground()) {
|
|
||||||
int left = r.left(), top = r.top(), right = r.left() + r.width(), bottom = r.top() + r.height();
|
|
||||||
if (right > 0 && bottom > 0) {
|
|
||||||
QRect fill(left, top + (hasTopBar ? st::topBarHeight : 0), right, bottom + (hasTopBar ? st::topBarHeight : 0));
|
|
||||||
|
|
||||||
if (hasTopBar) p.translate(0, -st::topBarHeight);
|
|
||||||
p.fillRect(fill, QBrush(*cChatBackground()));
|
|
||||||
if (hasTopBar) p.translate(0, st::topBarHeight);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
bool hasTopBar = !App::main()->topBar()->isHidden(), hasPlayer = !App::main()->player()->isHidden();
|
||||||
QRect fill(0, 0, width(), App::main()->height());
|
QRect fill(0, 0, width(), App::main()->height());
|
||||||
int fromy = hasTopBar ? (-st::topBarHeight) : 0, x = 0, y = 0;
|
int fromy = (hasTopBar ? (-st::topBarHeight) : 0) + (hasPlayer ? (-st::playerHeight) : 0), x = 0, y = 0;
|
||||||
QPixmap cached = App::main()->cachedBackground(fill, x, y);
|
QPixmap cached = App::main()->cachedBackground(fill, x, y);
|
||||||
if (cached.isNull()) {
|
if (cached.isNull()) {
|
||||||
bool smooth = p.renderHints().testFlag(QPainter::SmoothPixmapTransform);
|
const QPixmap &pix(*cChatBackground());
|
||||||
p.setRenderHint(QPainter::SmoothPixmapTransform);
|
if (cTileBackground()) {
|
||||||
|
int left = r.left(), top = r.top(), right = r.left() + r.width(), bottom = r.top() + r.height();
|
||||||
|
float64 w = pix.width() / cRetinaFactor(), h = pix.height() / cRetinaFactor();
|
||||||
|
int sx = qFloor(left / w), sy = qFloor((top - fromy) / h), cx = qCeil(right / w), cy = qCeil((bottom - fromy) / h);
|
||||||
|
for (int i = sx; i < cx; ++i) {
|
||||||
|
for (int j = sy; j < cy; ++j) {
|
||||||
|
p.drawPixmap(QPointF(i * w, fromy + j * h), pix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bool smooth = p.renderHints().testFlag(QPainter::SmoothPixmapTransform);
|
||||||
|
p.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||||
|
|
||||||
QRect to, from;
|
QRect to, from;
|
||||||
App::main()->backgroundParams(fill, to, from);
|
App::main()->backgroundParams(fill, to, from);
|
||||||
to.moveTop(to.top() + fromy);
|
to.moveTop(to.top() + fromy);
|
||||||
p.drawPixmap(to, *cChatBackground(), from);
|
p.drawPixmap(to, pix, from);
|
||||||
|
|
||||||
if (!smooth) p.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
if (!smooth) p.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
p.drawPixmap(x, fromy + y, cached);
|
p.drawPixmap(x, fromy + y, cached);
|
||||||
}
|
}
|
||||||
|
@ -1760,6 +1767,13 @@ void OverviewWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OverviewWidget::topBarShadowParams(int32 &x, float64 &o) {
|
||||||
|
if (animating() && a_coord.current() >= 0) {
|
||||||
|
x = a_coord.current();
|
||||||
|
o = a_alpha.current();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OverviewWidget::topBarClick() {
|
void OverviewWidget::topBarClick() {
|
||||||
App::main()->showBackFromStack();
|
App::main()->showBackFromStack();
|
||||||
}
|
}
|
||||||
|
@ -1781,6 +1795,7 @@ void OverviewWidget::switchType(MediaOverviewType type) {
|
||||||
case OverviewVideos: _header = lang(lng_profile_videos_header); break;
|
case OverviewVideos: _header = lang(lng_profile_videos_header); break;
|
||||||
case OverviewDocuments: _header = lang(lng_profile_files_header); break;
|
case OverviewDocuments: _header = lang(lng_profile_files_header); break;
|
||||||
case OverviewAudios: _header = lang(lng_profile_audios_header); break;
|
case OverviewAudios: _header = lang(lng_profile_audios_header); break;
|
||||||
|
case OverviewAudioDocuments: _header = lang(lng_profile_audio_files_header); break;
|
||||||
}
|
}
|
||||||
noSelectingScroll();
|
noSelectingScroll();
|
||||||
App::main()->topBar()->showSelected(0);
|
App::main()->topBar()->showSelected(0);
|
||||||
|
@ -1847,10 +1862,7 @@ bool OverviewWidget::animStep(float64 ms) {
|
||||||
a_alpha.finish();
|
a_alpha.finish();
|
||||||
_bgAnimCache = _animCache = _animTopBarCache = _bgAnimTopBarCache = QPixmap();
|
_bgAnimCache = _animCache = _animTopBarCache = _bgAnimTopBarCache = QPixmap();
|
||||||
App::main()->topBar()->stopAnim();
|
App::main()->topBar()->stopAnim();
|
||||||
_scroll.show();
|
doneShow();
|
||||||
_scroll.scrollToY(_scrollSetAfterShow);
|
|
||||||
activate();
|
|
||||||
onScroll();
|
|
||||||
} else {
|
} else {
|
||||||
a_bgCoord.update(dt1, st::introHideFunc);
|
a_bgCoord.update(dt1, st::introHideFunc);
|
||||||
a_bgAlpha.update(dt1, st::introAlphaHideFunc);
|
a_bgAlpha.update(dt1, st::introAlphaHideFunc);
|
||||||
|
@ -1862,8 +1874,15 @@ bool OverviewWidget::animStep(float64 ms) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverviewWidget::mediaOverviewUpdated(PeerData *p) {
|
void OverviewWidget::doneShow() {
|
||||||
if (peer() == p) {
|
_scroll.show();
|
||||||
|
_scroll.scrollToY(_scrollSetAfterShow);
|
||||||
|
activate();
|
||||||
|
onScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OverviewWidget::mediaOverviewUpdated(PeerData *p, MediaOverviewType t) {
|
||||||
|
if (peer() == p && t == type()) {
|
||||||
_inner.mediaOverviewUpdated();
|
_inner.mediaOverviewUpdated();
|
||||||
onScroll();
|
onScroll();
|
||||||
updateTopBarSelection();
|
updateTopBarSelection();
|
||||||
|
|
|
@ -142,6 +142,7 @@ private:
|
||||||
} CachedItem;
|
} CachedItem;
|
||||||
typedef QVector<CachedItem> CachedItems;
|
typedef QVector<CachedItem> CachedItems;
|
||||||
CachedItems _items;
|
CachedItems _items;
|
||||||
|
|
||||||
int32 _width, _height, _minHeight, _addToY;
|
int32 _width, _height, _minHeight, _addToY;
|
||||||
|
|
||||||
// selection support, like in HistoryWidget
|
// selection support, like in HistoryWidget
|
||||||
|
@ -199,6 +200,7 @@ public:
|
||||||
void scrollBy(int32 add);
|
void scrollBy(int32 add);
|
||||||
|
|
||||||
void paintTopBar(QPainter &p, float64 over, int32 decreaseWidth);
|
void paintTopBar(QPainter &p, float64 over, int32 decreaseWidth);
|
||||||
|
void topBarShadowParams(int32 &x, float64 &o);
|
||||||
void topBarClick();
|
void topBarClick();
|
||||||
|
|
||||||
PeerData *peer() const;
|
PeerData *peer() const;
|
||||||
|
@ -212,7 +214,9 @@ public:
|
||||||
void animShow(const QPixmap &oldAnimCache, const QPixmap &bgAnimTopBarCache, bool back = false, int32 lastScrollTop = -1);
|
void animShow(const QPixmap &oldAnimCache, const QPixmap &bgAnimTopBarCache, bool back = false, int32 lastScrollTop = -1);
|
||||||
bool animStep(float64 ms);
|
bool animStep(float64 ms);
|
||||||
|
|
||||||
void mediaOverviewUpdated(PeerData *peer);
|
void doneShow();
|
||||||
|
|
||||||
|
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
|
||||||
void changingMsgId(HistoryItem *row, MsgId newId);
|
void changingMsgId(HistoryItem *row, MsgId newId);
|
||||||
void msgUpdated(PeerId peer, const HistoryItem *msg);
|
void msgUpdated(PeerId peer, const HistoryItem *msg);
|
||||||
void itemRemoved(HistoryItem *item);
|
void itemRemoved(HistoryItem *item);
|
||||||
|
|
|
@ -0,0 +1,548 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "style.h"
|
||||||
|
#include "lang.h"
|
||||||
|
|
||||||
|
#include "boxes/addcontactbox.h"
|
||||||
|
#include "application.h"
|
||||||
|
#include "window.h"
|
||||||
|
#include "playerwidget.h"
|
||||||
|
#include "mainwidget.h"
|
||||||
|
|
||||||
|
#include "localstorage.h"
|
||||||
|
|
||||||
|
#include "audio.h"
|
||||||
|
|
||||||
|
PlayerWidget::PlayerWidget(QWidget *parent) : TWidget(parent),
|
||||||
|
_prevAvailable(false), _nextAvailable(false), _fullAvailable(false),
|
||||||
|
_over(OverNone), _down(OverNone), _downCoord(0), _downProgress(0.), _downFrequency(AudioVoiceMsgFrequency),
|
||||||
|
_stateAnim(animFunc(this, &PlayerWidget::stateStep)),
|
||||||
|
_index(-1), _history(0), _showPause(false), _position(0), _duration(0), _loaded(0),
|
||||||
|
a_progress(0., 0.), a_loadProgress(0., 0.), _progressAnim(animFunc(this, &PlayerWidget::progressStep)) {
|
||||||
|
resize(st::wndMinWidth, st::playerHeight);
|
||||||
|
setMouseTracking(true);
|
||||||
|
memset(_stateHovers, 0, sizeof(_stateHovers));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::paintEvent(QPaintEvent *e) {
|
||||||
|
Painter p(this);
|
||||||
|
|
||||||
|
QRect r(e->rect()), checkr(myrtlrect(r));
|
||||||
|
p.fillRect(r, st::playerBg->b);
|
||||||
|
|
||||||
|
if (!_playbackRect.contains(checkr)) {
|
||||||
|
if (_fullAvailable && checkr.intersects(_prevRect)) {
|
||||||
|
if (_prevAvailable) {
|
||||||
|
float64 o = _stateHovers[OverPrev];
|
||||||
|
p.setOpacity(o * 1. + (1. - o) * st::playerInactiveOpacity);
|
||||||
|
} else {
|
||||||
|
p.setOpacity(st::playerUnavailableOpacity);
|
||||||
|
}
|
||||||
|
p.drawSpriteCenterLeft(_prevRect, width(), st::playerPrev);
|
||||||
|
}
|
||||||
|
if (checkr.intersects(_playRect)) {
|
||||||
|
float64 o = _stateHovers[OverPlay];
|
||||||
|
p.setOpacity(o * 1. + (1. - o) * st::playerInactiveOpacity);
|
||||||
|
p.drawSpriteCenterLeft(_playRect, width(), (_showPause || _down == OverPlayback) ? st::playerPause : st::playerPlay);
|
||||||
|
}
|
||||||
|
if (_fullAvailable && checkr.intersects(_nextRect)) {
|
||||||
|
if (_nextAvailable) {
|
||||||
|
float64 o = _stateHovers[OverNext];
|
||||||
|
p.setOpacity(o * 1. + (1. - o) * st::playerInactiveOpacity);
|
||||||
|
} else {
|
||||||
|
p.setOpacity(st::playerUnavailableOpacity);
|
||||||
|
}
|
||||||
|
p.drawSpriteCenterLeft(_nextRect, width(), st::playerNext);
|
||||||
|
}
|
||||||
|
if (checkr.intersects(_closeRect)) {
|
||||||
|
float64 o = _stateHovers[OverClose];
|
||||||
|
p.setOpacity(o * 1. + (1. - o) * st::playerInactiveOpacity);
|
||||||
|
p.drawSpriteCenterLeft(_closeRect, width(), st::playerClose);
|
||||||
|
}
|
||||||
|
if (checkr.intersects(_volumeRect)) {
|
||||||
|
float64 o = _stateHovers[OverVolume];
|
||||||
|
p.setOpacity(o * 1. + (1. - o) * st::playerInactiveOpacity);
|
||||||
|
int32 top = _volumeRect.y() + (_volumeRect.height() - st::playerVolume.pxHeight()) / 2;
|
||||||
|
int32 left = _volumeRect.x() + (_volumeRect.width() - st::playerVolume.pxWidth()) / 2;
|
||||||
|
int32 mid = left + qRound(st::playerVolume.pxWidth() * cSongVolume());
|
||||||
|
int32 right = left + st::playerVolume.pxWidth();
|
||||||
|
if (rtl()) {
|
||||||
|
left = width() - left;
|
||||||
|
mid = width() - mid;
|
||||||
|
right = width() - right;
|
||||||
|
if (mid < left) {
|
||||||
|
p.drawPixmap(QRect(mid, top, left - mid, st::playerVolume.pxHeight()), App::sprite(), QRect(st::playerVolume.x() + (mid - right) * cIntRetinaFactor(), st::playerVolume.y(), (left - mid) * cIntRetinaFactor(), st::playerVolume.pxHeight() * cIntRetinaFactor()));
|
||||||
|
}
|
||||||
|
if (right < mid) {
|
||||||
|
p.setOpacity(st::playerUnavailableOpacity);
|
||||||
|
p.drawPixmap(QRect(right, top, mid - right, st::playerVolume.pxHeight()), App::sprite(), QRect(st::playerVolume.x(), st::playerVolume.y(), (mid - right) * cIntRetinaFactor(), st::playerVolume.pxHeight() * cIntRetinaFactor()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mid > left) {
|
||||||
|
p.drawPixmap(QRect(left, top, mid - left, st::playerVolume.pxHeight()), App::sprite(), QRect(st::playerVolume.x(), st::playerVolume.y(), (mid - left) * cIntRetinaFactor(), st::playerVolume.pxHeight() * cIntRetinaFactor()));
|
||||||
|
}
|
||||||
|
if (right > mid) {
|
||||||
|
p.setOpacity(st::playerUnavailableOpacity);
|
||||||
|
p.drawPixmap(QRect(mid, top, right - mid, st::playerVolume.pxHeight()), App::sprite(), QRect(st::playerVolume.x() + (mid - left) * cIntRetinaFactor(), st::playerVolume.y(), (right - mid) * cIntRetinaFactor(), st::playerVolume.pxHeight() * cIntRetinaFactor()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_fullAvailable && checkr.intersects(_fullRect)) {
|
||||||
|
float64 o = _stateHovers[OverFull];
|
||||||
|
p.setOpacity(o * 1. + (1. - o) * st::playerInactiveOpacity);
|
||||||
|
p.drawSpriteCenterLeft(_fullRect, width(), st::playerFull);
|
||||||
|
}
|
||||||
|
p.setOpacity(1.);
|
||||||
|
|
||||||
|
p.setPen(st::playerTimeFg->p);
|
||||||
|
p.setFont(st::linkFont->f);
|
||||||
|
p.drawTextLeft(_infoRect.x() + _infoRect.width() - _timeWidth, _infoRect.y() + (_infoRect.height() - st::linkFont->height) / 2, width(), _time, _timeWidth);
|
||||||
|
|
||||||
|
textstyleSet(&st::playerNameStyle);
|
||||||
|
p.setPen(st::playerFg->p);
|
||||||
|
_name.drawElided(p, _infoRect.x() + (rtl() ? (_timeWidth + st::playerSkip) : 0), _infoRect.y() + (_infoRect.height() - st::linkFont->height) / 2, _infoRect.width() - _timeWidth - st::playerSkip);
|
||||||
|
textstyleRestore();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_duration) {
|
||||||
|
float64 prg = (_down == OverPlayback) ? _downProgress : a_progress.current();
|
||||||
|
int32 from = _playbackRect.x(), mid = qRound(_playbackRect.x() + prg * _playbackRect.width()), end = _playbackRect.x() + _playbackRect.width();
|
||||||
|
if (mid > from) {
|
||||||
|
p.fillRect(rtl() ? (width() - mid) : from, height() - st::playerLineHeight, mid - from, _playbackRect.height(), st::playerLineActive->b);
|
||||||
|
}
|
||||||
|
if (end > mid) {
|
||||||
|
p.fillRect(rtl() ? (width() - end) : mid, height() - st::playerLineHeight, end - mid, st::playerLineHeight, st::playerLineInactive->b);
|
||||||
|
}
|
||||||
|
if (_stateHovers[OverPlayback] > 0) {
|
||||||
|
p.setOpacity(_stateHovers[OverPlayback]);
|
||||||
|
|
||||||
|
int32 x = mid - (st::playerMoverSize.width() / 2);
|
||||||
|
p.fillRect(rtl() ? (width() - x - st::playerMoverSize.width()) : x, height() - st::playerMoverSize.height(), st::playerMoverSize.width(), st::playerMoverSize.height(), st::playerLineActive->b);
|
||||||
|
}
|
||||||
|
} else if (a_loadProgress.current() > 0) {
|
||||||
|
int32 from = _playbackRect.x(), mid = qRound(_playbackRect.x() + a_loadProgress.current() * _playbackRect.width());
|
||||||
|
if (mid > from) {
|
||||||
|
p.fillRect(rtl() ? (width() - mid) : from, height() - st::playerLineHeight, mid - from, _playbackRect.height(), st::playerLineInactive->b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::mousePressEvent(QMouseEvent *e) {
|
||||||
|
QPoint pos(myrtlpoint(e->pos()));
|
||||||
|
|
||||||
|
if (e->button() == Qt::LeftButton) {
|
||||||
|
_down = OverNone;
|
||||||
|
if (_song && _over == OverPlay) {
|
||||||
|
SongMsgId playing;
|
||||||
|
AudioPlayerState playingState = AudioPlayerStopped;
|
||||||
|
audioPlayer()->currentState(&playing, &playingState);
|
||||||
|
if (playing == _song && !(playingState & AudioPlayerStoppedMask)) {
|
||||||
|
audioPlayer()->pauseresume(OverviewDocuments);
|
||||||
|
} else {
|
||||||
|
audioPlayer()->play(_song);
|
||||||
|
if (App::main()) App::main()->documentPlayProgress(_song);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (_over == OverPrev) {
|
||||||
|
const History::MediaOverview *o = _history ? &_history->_overview[OverviewAudioDocuments] : 0;
|
||||||
|
if (audioPlayer() && o && _index > 0 && _index <= o->size() && !o->isEmpty()) {
|
||||||
|
startPlay(o->at(_index - 1));
|
||||||
|
}
|
||||||
|
} else if (_over == OverNext) {
|
||||||
|
const History::MediaOverview *o = _history ? &_history->_overview[OverviewAudioDocuments] : 0;
|
||||||
|
if (audioPlayer() && o && _index >= 0 && _index < o->size() - 1) {
|
||||||
|
startPlay(o->at(_index + 1));
|
||||||
|
}
|
||||||
|
} else if (_over == OverClose) {
|
||||||
|
_down = OverClose;
|
||||||
|
} else if (_over == OverVolume) {
|
||||||
|
_down = OverVolume;
|
||||||
|
_downCoord = pos.x() - _volumeRect.x();
|
||||||
|
cSetSongVolume(snap((_downCoord - ((_volumeRect.width() - st::playerVolume.pxWidth()) / 2)) / float64(st::playerVolume.pxWidth()), 0., 1.));
|
||||||
|
emit audioPlayer()->songVolumeChanged();
|
||||||
|
rtlupdate(_volumeRect);
|
||||||
|
} else if (_over == OverPlayback) {
|
||||||
|
SongMsgId playing;
|
||||||
|
AudioPlayerState playingState = AudioPlayerStopped;
|
||||||
|
int64 playingPosition = 0, playingDuration = 0;
|
||||||
|
int32 playingFrequency = 0;
|
||||||
|
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
|
||||||
|
if (playing == _song && playingDuration) {
|
||||||
|
if (playingState == AudioPlayerPlaying || playingState == AudioPlayerStarting || playingState == AudioPlayerResuming) {
|
||||||
|
audioPlayer()->pauseresume(OverviewDocuments);
|
||||||
|
}
|
||||||
|
_down = OverPlayback;
|
||||||
|
_downProgress = snap((pos.x() - _playbackRect.x()) / float64(_playbackRect.width()), 0., 1.);
|
||||||
|
_downDuration = playingDuration;
|
||||||
|
_downFrequency = (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency);
|
||||||
|
|
||||||
|
rtlupdate(_playbackRect);
|
||||||
|
updateDownTime();
|
||||||
|
}
|
||||||
|
} else if (_over == OverFull && _song) {
|
||||||
|
if (HistoryItem *item = App::histItemById(_song.msgId)) {
|
||||||
|
App::main()->showMediaOverview(item->history()->peer, OverviewAudioDocuments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::updateDownTime() {
|
||||||
|
QString time = formatDurationText(qRound(_downDuration * _downProgress) / _downFrequency);
|
||||||
|
if (time != _time) {
|
||||||
|
_time = time;
|
||||||
|
_timeWidth = st::linkFont->m.width(_time);
|
||||||
|
rtlupdate(_infoRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::updateOverState(OverState newState) {
|
||||||
|
bool result = true;
|
||||||
|
if (_over != newState) {
|
||||||
|
updateOverRect(_over);
|
||||||
|
updateOverRect(newState);
|
||||||
|
if (_over != OverNone) {
|
||||||
|
_stateAnimations.remove(_over);
|
||||||
|
_stateAnimations[-_over] = getms() - ((1. - _stateHovers[_over]) * st::playerDuration);
|
||||||
|
if (!_stateAnim.animating()) _stateAnim.start();
|
||||||
|
} else {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
_over = newState;
|
||||||
|
if (newState != OverNone) {
|
||||||
|
_stateAnimations.remove(-_over);
|
||||||
|
_stateAnimations[_over] = getms() - (_stateHovers[_over] * st::playerDuration);
|
||||||
|
if (!_stateAnim.animating()) _stateAnim.start();
|
||||||
|
setCursor(style::cur_pointer);
|
||||||
|
} else {
|
||||||
|
setCursor(style::cur_default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::updateOverRect(OverState state) {
|
||||||
|
switch (state) {
|
||||||
|
case OverPrev: rtlupdate(_prevRect); break;
|
||||||
|
case OverPlay: rtlupdate(_playRect); break;
|
||||||
|
case OverNext: rtlupdate(_nextRect); break;
|
||||||
|
case OverClose: rtlupdate(_closeRect); break;
|
||||||
|
case OverVolume: rtlupdate(_volumeRect); break;
|
||||||
|
case OverFull: rtlupdate(_fullRect); break;
|
||||||
|
case OverPlayback: rtlupdate(_playbackRect); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::updateControls() {
|
||||||
|
_fullAvailable = (_index >= 0);
|
||||||
|
_prevAvailable = _fullAvailable && (_index > 0);
|
||||||
|
_nextAvailable = _fullAvailable && (_index < _history->_overview[OverviewAudioDocuments].size() - 1);
|
||||||
|
resizeEvent(0);
|
||||||
|
update();
|
||||||
|
|
||||||
|
if (_index >= 0 && _index < MediaOverviewStartPerPage) {
|
||||||
|
if (_history->_overviewCount[OverviewAudioDocuments] < 0 || _history->_overviewCount[OverviewAudioDocuments] > 0) {
|
||||||
|
if (App::main()) App::main()->loadMediaBack(_history->peer, OverviewAudioDocuments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::findCurrent() {
|
||||||
|
_index = -1;
|
||||||
|
if (!_history) return;
|
||||||
|
|
||||||
|
const History::MediaOverview *o = &_history->_overview[OverviewAudioDocuments];
|
||||||
|
for (int i = 0, l = o->size(); i < l; ++i) {
|
||||||
|
if (o->at(i) == _song.msgId) {
|
||||||
|
_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_index < 0) return;
|
||||||
|
|
||||||
|
if (_index < o->size() - 1) {
|
||||||
|
if (HistoryItem *next = App::histItemById(o->at(_index + 1))) {
|
||||||
|
if (HistoryDocument *document = static_cast<HistoryDocument*>(next->getMedia())) {
|
||||||
|
if (document->document()->already(true).isEmpty() && document->document()->data.isEmpty()) {
|
||||||
|
if (!document->document()->loader) {
|
||||||
|
DocumentOpenLink::doOpen(document->document());
|
||||||
|
document->document()->openOnSave = document->document()->openOnSaveMsgId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::startPlay(MsgId msgId) {
|
||||||
|
if (HistoryItem *item = App::histItemById(msgId)) {
|
||||||
|
if (HistoryDocument *doc = static_cast<HistoryDocument*>(item->getMedia())) {
|
||||||
|
audioPlayer()->play(SongMsgId(doc->document(), item->id));
|
||||||
|
updateState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::clearSelection() {
|
||||||
|
for (StateAnimations::const_iterator i = _stateAnimations.cbegin(); i != _stateAnimations.cend(); ++i) {
|
||||||
|
_stateHovers[qAbs(i.key())] = 0;
|
||||||
|
}
|
||||||
|
_stateAnimations.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
|
||||||
|
if (_history && _history->peer == peer && type == OverviewAudioDocuments) {
|
||||||
|
_index = -1;
|
||||||
|
for (int i = 0, l = _history->_overview[OverviewAudioDocuments].size(); i < l; ++i) {
|
||||||
|
if (_history->_overview[OverviewAudioDocuments].at(i) == _song.msgId) {
|
||||||
|
_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateControls();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayerWidget::seekingSong(const SongMsgId &song) const {
|
||||||
|
return (_down == OverPlayback) && (song == _song);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayerWidget::stateStep(float64 msñ) {
|
||||||
|
bool result = false;
|
||||||
|
uint64 ms = getms();
|
||||||
|
for (StateAnimations::iterator i = _stateAnimations.begin(); i != _stateAnimations.cend();) {
|
||||||
|
int32 over = qAbs(i.key());
|
||||||
|
updateOverRect(OverState(over));
|
||||||
|
|
||||||
|
float64 dt = float64(ms - i.value()) / st::playerDuration;
|
||||||
|
if (dt >= 1) {
|
||||||
|
_stateHovers[over] = (i.key() > 0) ? 1 : 0;
|
||||||
|
i = _stateAnimations.erase(i);
|
||||||
|
} else {
|
||||||
|
_stateHovers[over] = (i.key() > 0) ? dt : (1 - dt);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !_stateAnimations.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::mouseMoveEvent(QMouseEvent *e) {
|
||||||
|
_lastMousePos = e->globalPos();
|
||||||
|
updateSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::leaveEvent(QEvent *e) {
|
||||||
|
_lastMousePos = QCursor::pos();
|
||||||
|
updateSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::updateSelected() {
|
||||||
|
QPoint pos(myrtlpoint(mapFromGlobal(_lastMousePos)));
|
||||||
|
|
||||||
|
if (_down == OverVolume) {
|
||||||
|
int32 delta = (pos.x() - _volumeRect.x()) - _downCoord;
|
||||||
|
float64 startFrom = snap((_downCoord - ((_volumeRect.width() - st::playerVolume.pxWidth()) / 2)) / float64(st::playerVolume.pxWidth()), 0., 1.);
|
||||||
|
float64 add = delta / float64(4 * st::playerVolume.pxWidth()), result = snap(startFrom + add, 0., 1.);
|
||||||
|
if (result != cSongVolume()) {
|
||||||
|
cSetSongVolume(result);
|
||||||
|
emit audioPlayer()->songVolumeChanged();
|
||||||
|
rtlupdate(_volumeRect);
|
||||||
|
}
|
||||||
|
} else if (_down == OverPlayback) {
|
||||||
|
_downProgress = snap((pos.x() - _playbackRect.x()) / float64(_playbackRect.width()), 0., 1.);
|
||||||
|
rtlupdate(_playbackRect);
|
||||||
|
updateDownTime();
|
||||||
|
} else if (_down == OverNone) {
|
||||||
|
bool inInfo = ((pos.x() >= _infoRect.x()) && (pos.x() < _fullRect.x() + _fullRect.width()) && (pos.y() >= _playRect.y()) && (pos.y() <= _playRect.y() + _playRect.height()));
|
||||||
|
if (_prevAvailable && _prevRect.contains(pos)) {
|
||||||
|
updateOverState(OverPrev);
|
||||||
|
} else if (_nextAvailable && _nextRect.contains(pos)) {
|
||||||
|
updateOverState(OverNext);
|
||||||
|
} else if (_playRect.contains(pos)) {
|
||||||
|
updateOverState(OverPlay);
|
||||||
|
} else if (_closeRect.contains(pos)) {
|
||||||
|
updateOverState(OverClose);
|
||||||
|
} else if (_volumeRect.contains(pos)) {
|
||||||
|
updateOverState(OverVolume);
|
||||||
|
} else if (_duration && _playbackRect.contains(pos)) {
|
||||||
|
updateOverState(OverPlayback);
|
||||||
|
} else if (_fullAvailable && inInfo) {
|
||||||
|
updateOverState(OverFull);
|
||||||
|
} else if (_over != OverNone) {
|
||||||
|
updateOverState(OverNone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
if (_down == OverVolume) {
|
||||||
|
mouseMoveEvent(e);
|
||||||
|
Local::writeUserSettings();
|
||||||
|
} else if (_down == OverPlayback) {
|
||||||
|
mouseMoveEvent(e);
|
||||||
|
SongMsgId playing;
|
||||||
|
AudioPlayerState playingState = AudioPlayerStopped;
|
||||||
|
int64 playingPosition = 0, playingDuration = 0;
|
||||||
|
int32 playingFrequency = 0;
|
||||||
|
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
|
||||||
|
if (playing == _song && playingDuration) {
|
||||||
|
_downDuration = playingDuration;
|
||||||
|
audioPlayer()->seek(qRound(_downProgress * _downDuration));
|
||||||
|
|
||||||
|
_showPause = true;
|
||||||
|
|
||||||
|
a_progress = anim::fvalue(_downProgress, _downProgress);
|
||||||
|
_progressAnim.stop();
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
} else if (_down == OverClose && _over == OverClose) {
|
||||||
|
if (_song) {
|
||||||
|
audioPlayer()->stop(OverviewDocuments);
|
||||||
|
if (App::main()) App::main()->hidePlayer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_down = OverNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::resizeEvent(QResizeEvent *e) {
|
||||||
|
int32 availh = (height() - st::playerLineHeight);
|
||||||
|
int32 ch = st::playerPlay.pxHeight() + st::playerSkip, ct = (availh - ch) / 2;
|
||||||
|
_playbackRect = QRect(cWideMode() ? st::dlgShadow : 0, height() - st::playerMoverSize.height(), width() - (cWideMode() ? st::dlgShadow : 0), st::playerMoverSize.height());
|
||||||
|
_prevRect = _fullAvailable ? QRect(st::playerSkip / 2, ct, st::playerPrev.pxWidth() + st::playerSkip, ch) : QRect();
|
||||||
|
_playRect = QRect(_fullAvailable ? (_prevRect.x() + _prevRect.width()) : (st::playerSkip / 2), ct, st::playerPlay.pxWidth() + st::playerSkip, ch);
|
||||||
|
_nextRect = _fullAvailable ? QRect(_playRect.x() + _playRect.width(), ct, st::playerNext.pxWidth() + st::playerSkip, ch) : QRect();
|
||||||
|
|
||||||
|
_closeRect = QRect(width() - st::playerSkip / 2 - st::playerClose.pxWidth() - st::playerSkip, ct, st::playerClose.pxWidth() + st::playerSkip, ch);
|
||||||
|
_volumeRect = QRect(_closeRect.x() - st::playerVolume.pxWidth() - st::playerSkip, ct, st::playerVolume.pxWidth() + st::playerSkip, ch);
|
||||||
|
_fullRect = _fullAvailable ? QRect(_volumeRect.x() - st::playerFull.pxWidth() - st::playerSkip, ct, st::playerFull.pxWidth() + st::playerSkip, ch) : QRect();
|
||||||
|
|
||||||
|
int32 infoLeft = (_fullAvailable ? (_nextRect.x() + _nextRect.width()) : (_playRect.x() + _playRect.width()));
|
||||||
|
_infoRect = QRect(infoLeft + st::playerSkip / 2, 0, (_fullAvailable ? _fullRect.x() : _volumeRect.x()) - infoLeft - st::playerSkip, availh);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayerWidget::progressStep(float64 ms) {
|
||||||
|
float64 dt = ms / (2 * AudioVoiceMsgUpdateView);
|
||||||
|
bool res = true;
|
||||||
|
if (_duration && dt >= 1) {
|
||||||
|
a_progress.finish();
|
||||||
|
a_loadProgress.finish();
|
||||||
|
res = false;
|
||||||
|
} else {
|
||||||
|
a_progress.update(qMin(dt, 1.), anim::linear);
|
||||||
|
a_loadProgress.update(1. - (st::radialDuration / (st::radialDuration + ms)), anim::linear);
|
||||||
|
}
|
||||||
|
rtlupdate(_playbackRect);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::updateState() {
|
||||||
|
updateState(SongMsgId(), AudioPlayerStopped, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerWidget::updateState(SongMsgId playing, AudioPlayerState playingState, int64 playingPosition, int64 playingDuration, int32 playingFrequency) {
|
||||||
|
if (!playing) {
|
||||||
|
audioPlayer()->currentState(&playing, &playingState, &playingPosition, &playingDuration, &playingFrequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool songChanged = false;
|
||||||
|
if (playing && _song != playing) {
|
||||||
|
songChanged = true;
|
||||||
|
_song = playing;
|
||||||
|
if (HistoryItem *item = App::histItemById(_song.msgId)) {
|
||||||
|
_history = item->history();
|
||||||
|
findCurrent();
|
||||||
|
} else {
|
||||||
|
_history = 0;
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
SongData *song = _song.song->song();
|
||||||
|
if (song->performer.isEmpty()) {
|
||||||
|
_name.setText(st::linkFont, song->title.isEmpty() ? (_song.song->name.isEmpty() ? qsl("Unknown Track") : _song.song->name) : song->title, _textNameOptions);
|
||||||
|
} else {
|
||||||
|
TextCustomTagsMap custom;
|
||||||
|
custom.insert(QChar('c'), qMakePair(textcmdStartLink(1), textcmdStopLink()));
|
||||||
|
_name.setRichText(st::linkFont, QString::fromUtf8("[c]%1[/c] \xe2\x80\x93 %2").arg(textRichPrepare(song->performer)).arg(song->title.isEmpty() ? qsl("Unknown Track") : textRichPrepare(song->title)), _textNameOptions, custom);
|
||||||
|
}
|
||||||
|
updateControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 position = 0, duration = 0, display = 0;
|
||||||
|
if (playing == _song) {
|
||||||
|
if (!(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||||
|
display = position = playingPosition;
|
||||||
|
duration = playingDuration;
|
||||||
|
} else {
|
||||||
|
display = playingDuration;
|
||||||
|
}
|
||||||
|
display = display / (playingFrequency ? playingFrequency : AudioVoiceMsgFrequency);
|
||||||
|
} else if (_song) {
|
||||||
|
display = _song.song->song()->duration;
|
||||||
|
}
|
||||||
|
QString time = (_down == OverPlayback) ? _time : formatDurationText(display);
|
||||||
|
bool showPause = false, stopped = ((playingState & AudioPlayerStoppedMask) || playingState == AudioPlayerFinishing);
|
||||||
|
bool wasPlaying = !!_duration;
|
||||||
|
if (!stopped) {
|
||||||
|
showPause = (playingState == AudioPlayerPlaying || playingState == AudioPlayerResuming || playingState == AudioPlayerStarting);
|
||||||
|
}
|
||||||
|
float64 progress = duration ? snap(float64(position) / duration, 0., 1.) : 0.;
|
||||||
|
int32 loaded = duration ? _song.song->size : (_song.song->loader ? _song.song->loader->currentOffset() : 0);
|
||||||
|
float64 loadProgress = (duration || !_song.song->loader) ? 1. : snap(float64(loaded) / qMax(_song.song->size, 1), 0., 1.);
|
||||||
|
if (time != _time || showPause != _showPause) {
|
||||||
|
if (_time != time) {
|
||||||
|
_time = time;
|
||||||
|
_timeWidth = st::linkFont->m.width(_time);
|
||||||
|
}
|
||||||
|
_showPause = showPause;
|
||||||
|
if (duration != _duration || position != _position || loaded != _loaded) {
|
||||||
|
if (!songChanged && ((!stopped && duration && _duration) || (!duration && _loaded != loaded))) {
|
||||||
|
a_progress.start(progress);
|
||||||
|
a_loadProgress.start(loadProgress);
|
||||||
|
_progressAnim.start();
|
||||||
|
} else {
|
||||||
|
a_progress = anim::fvalue(progress, progress);
|
||||||
|
a_loadProgress = anim::fvalue(loadProgress, loadProgress);
|
||||||
|
_progressAnim.stop();
|
||||||
|
}
|
||||||
|
_position = position;
|
||||||
|
_duration = duration;
|
||||||
|
_loaded = loaded;
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
} else if (duration != _duration || position != _position || loaded != _loaded) {
|
||||||
|
if (!songChanged && ((!stopped && duration && _duration) || (!duration && _loaded != loaded))) {
|
||||||
|
a_progress.start(progress);
|
||||||
|
a_loadProgress.start(loadProgress);
|
||||||
|
_progressAnim.start();
|
||||||
|
} else {
|
||||||
|
a_progress = anim::fvalue(progress, progress);
|
||||||
|
a_loadProgress = anim::fvalue(loadProgress, loadProgress);
|
||||||
|
_progressAnim.stop();
|
||||||
|
}
|
||||||
|
_position = position;
|
||||||
|
_duration = duration;
|
||||||
|
_loaded = loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wasPlaying && playingState == AudioPlayerStoppedAtEnd) {
|
||||||
|
const History::MediaOverview *o = _history ? &_history->_overview[OverviewAudioDocuments] : 0;
|
||||||
|
if (audioPlayer() && o && _index >= 0 && _index < o->size() - 1) {
|
||||||
|
startPlay(o->at(_index + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||||||
|
|
||||||
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
It is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||||||
|
Copyright (c) 2014 John Preston, https://desktop.telegram.org
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "audio.h"
|
||||||
|
|
||||||
|
class PlayerWidget : public TWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
PlayerWidget(QWidget *parent);
|
||||||
|
|
||||||
|
void paintEvent(QPaintEvent *e);
|
||||||
|
void mousePressEvent(QMouseEvent *e);
|
||||||
|
void mouseMoveEvent(QMouseEvent *e);
|
||||||
|
void leaveEvent(QEvent *e);
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e);
|
||||||
|
void resizeEvent(QResizeEvent *e);
|
||||||
|
|
||||||
|
bool progressStep(float64 ms);
|
||||||
|
bool stateStep(float64 ms);
|
||||||
|
|
||||||
|
void updateState(SongMsgId playing, AudioPlayerState playingState, int64 playingPosition, int64 playingDuration, int32 playingFrequency);
|
||||||
|
void updateState();
|
||||||
|
void clearSelection();
|
||||||
|
|
||||||
|
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
|
||||||
|
|
||||||
|
bool seekingSong(const SongMsgId &song) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
enum OverState {
|
||||||
|
OverNone = 0,
|
||||||
|
OverPrev,
|
||||||
|
OverPlay,
|
||||||
|
OverNext,
|
||||||
|
OverClose,
|
||||||
|
OverVolume,
|
||||||
|
OverFull,
|
||||||
|
OverPlayback,
|
||||||
|
|
||||||
|
OverStateCount
|
||||||
|
};
|
||||||
|
void updateDownTime();
|
||||||
|
void updateOverState(OverState newState);
|
||||||
|
void updateOverRect(OverState state);
|
||||||
|
|
||||||
|
void updateControls();
|
||||||
|
void findCurrent();
|
||||||
|
|
||||||
|
void startPlay(MsgId msgId);
|
||||||
|
|
||||||
|
QPoint _lastMousePos;
|
||||||
|
void updateSelected();
|
||||||
|
|
||||||
|
bool _prevAvailable, _nextAvailable, _fullAvailable;
|
||||||
|
OverState _over, _down;
|
||||||
|
int32 _downCoord;
|
||||||
|
int64 _downDuration;
|
||||||
|
int32 _downFrequency;
|
||||||
|
float64 _downProgress;
|
||||||
|
|
||||||
|
float64 _stateHovers[OverStateCount];
|
||||||
|
typedef QMap<int32, uint64> StateAnimations;
|
||||||
|
StateAnimations _stateAnimations;
|
||||||
|
Animation _stateAnim;
|
||||||
|
|
||||||
|
SongMsgId _song;
|
||||||
|
int32 _index;
|
||||||
|
History *_history;
|
||||||
|
QRect _playRect, _prevRect, _nextRect, _playbackRect;
|
||||||
|
QRect _closeRect, _volumeRect, _fullRect, _infoRect;
|
||||||
|
int32 _timeWidth;
|
||||||
|
QString _time;
|
||||||
|
Text _name;
|
||||||
|
bool _showPause;
|
||||||
|
int64 _position, _duration;
|
||||||
|
int32 _loaded;
|
||||||
|
|
||||||
|
anim::fvalue a_progress, a_loadProgress;
|
||||||
|
Animation _progressAnim;
|
||||||
|
|
||||||
|
};
|
|
@ -579,6 +579,8 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
|
||||||
p.setPen(st::black->p);
|
p.setPen(st::black->p);
|
||||||
int oneState = 0; // < 0 - loading, 0 - no media, > 0 - link shown
|
int oneState = 0; // < 0 - loading, 0 - no media, > 0 - link shown
|
||||||
for (int i = 0; i < OverviewCount; ++i) {
|
for (int i = 0; i < OverviewCount; ++i) {
|
||||||
|
if (i == OverviewAudioDocuments) continue;
|
||||||
|
|
||||||
int32 count = (_hist->_overviewCount[i] > 0) ? _hist->_overviewCount[i] : (_hist->_overviewCount[i] == 0 ? _hist->_overview[i].size() : -1);
|
int32 count = (_hist->_overviewCount[i] > 0) ? _hist->_overviewCount[i] : (_hist->_overviewCount[i] == 0 ? _hist->_overview[i].size() : -1);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
if (!oneState) oneState = count;
|
if (!oneState) oneState = count;
|
||||||
|
@ -859,6 +861,8 @@ void ProfileInner::resizeEvent(QResizeEvent *e) {
|
||||||
_mediaShowAll.move(_left + _width - _mediaShowAll.width(), top);
|
_mediaShowAll.move(_left + _width - _mediaShowAll.width(), top);
|
||||||
int wasCount = 0; // < 0 - loading, 0 - no media, > 0 - link shown
|
int wasCount = 0; // < 0 - loading, 0 - no media, > 0 - link shown
|
||||||
for (int i = 0; i < OverviewCount; ++i) {
|
for (int i = 0; i < OverviewCount; ++i) {
|
||||||
|
if (i == OverviewAudioDocuments) continue;
|
||||||
|
|
||||||
if (_allMediaTypes) {
|
if (_allMediaTypes) {
|
||||||
int32 count = (_hist->_overviewCount[i] > 0) ? _hist->_overviewCount[i] : (_hist->_overviewCount[i] == 0 ? _hist->_overview[i].size() : -1);
|
int32 count = (_hist->_overviewCount[i] > 0) ? _hist->_overviewCount[i] : (_hist->_overviewCount[i] == 0 ? _hist->_overview[i].size() : -1);
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
|
@ -957,7 +961,7 @@ void ProfileInner::updateNotifySettings() {
|
||||||
_enableNotifications.setChecked(_peer->notify == EmptyNotifySettings || _peer->notify == UnknownNotifySettings || _peer->notify->mute < unixtime());
|
_enableNotifications.setChecked(_peer->notify == EmptyNotifySettings || _peer->notify == UnknownNotifySettings || _peer->notify->mute < unixtime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileInner::mediaOverviewUpdated(PeerData *peer) {
|
void ProfileInner::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
|
||||||
if (peer == _peer) {
|
if (peer == _peer) {
|
||||||
resizeEvent(0);
|
resizeEvent(0);
|
||||||
showAll();
|
showAll();
|
||||||
|
@ -1029,6 +1033,8 @@ void ProfileInner::showAll() {
|
||||||
// shared media
|
// shared media
|
||||||
bool first = false, wasCount = false, manyCounts = false;
|
bool first = false, wasCount = false, manyCounts = false;
|
||||||
for (int i = 0; i < OverviewCount; ++i) {
|
for (int i = 0; i < OverviewCount; ++i) {
|
||||||
|
if (i == OverviewAudioDocuments) continue;
|
||||||
|
|
||||||
int32 count = (_hist->_overviewCount[i] > 0) ? _hist->_overviewCount[i] : (_hist->_overviewCount[i] == 0 ? _hist->_overview[i].size() : -1);
|
int32 count = (_hist->_overviewCount[i] > 0) ? _hist->_overviewCount[i] : (_hist->_overviewCount[i] == 0 ? _hist->_overview[i].size() : -1);
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
if (wasCount) {
|
if (wasCount) {
|
||||||
|
@ -1136,8 +1142,13 @@ void ProfileWidget::onScroll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileWidget::resizeEvent(QResizeEvent *e) {
|
void ProfileWidget::resizeEvent(QResizeEvent *e) {
|
||||||
|
int32 addToY = App::main() ? App::main()->contentScrollAddToY() : 0;
|
||||||
|
int32 newScrollY = _scroll.scrollTop() + addToY;
|
||||||
_scroll.resize(size());
|
_scroll.resize(size());
|
||||||
_inner.resize(width(), _inner.height());
|
_inner.resize(width(), _inner.height());
|
||||||
|
if (addToY) {
|
||||||
|
_scroll.scrollToY(newScrollY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileWidget::mousePressEvent(QMouseEvent *e) {
|
void ProfileWidget::mousePressEvent(QMouseEvent *e) {
|
||||||
|
@ -1176,6 +1187,13 @@ void ProfileWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProfileWidget::topBarShadowParams(int32 &x, float64 &o) {
|
||||||
|
if (animating() && a_coord.current() >= 0) {
|
||||||
|
x = a_coord.current();
|
||||||
|
o = a_alpha.current();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ProfileWidget::topBarClick() {
|
void ProfileWidget::topBarClick() {
|
||||||
App::main()->showBackFromStack();
|
App::main()->showBackFromStack();
|
||||||
}
|
}
|
||||||
|
@ -1253,8 +1271,8 @@ void ProfileWidget::updateNotifySettings() {
|
||||||
_inner.updateNotifySettings();
|
_inner.updateNotifySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileWidget::mediaOverviewUpdated(PeerData *peer) {
|
void ProfileWidget::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
|
||||||
_inner.mediaOverviewUpdated(peer);
|
_inner.mediaOverviewUpdated(peer, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileWidget::clear() {
|
void ProfileWidget::clear() {
|
||||||
|
|
|
@ -53,7 +53,7 @@ public:
|
||||||
void loadProfilePhotos(int32 yFrom);
|
void loadProfilePhotos(int32 yFrom);
|
||||||
|
|
||||||
void updateNotifySettings();
|
void updateNotifySettings();
|
||||||
void mediaOverviewUpdated(PeerData *peer);
|
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
|
||||||
|
|
||||||
~ProfileInner();
|
~ProfileInner();
|
||||||
|
|
||||||
|
@ -187,6 +187,7 @@ public:
|
||||||
void dropEvent(QDropEvent *e);
|
void dropEvent(QDropEvent *e);
|
||||||
|
|
||||||
void paintTopBar(QPainter &p, float64 over, int32 decreaseWidth);
|
void paintTopBar(QPainter &p, float64 over, int32 decreaseWidth);
|
||||||
|
void topBarShadowParams(int32 &x, float64 &o);
|
||||||
void topBarClick();
|
void topBarClick();
|
||||||
|
|
||||||
PeerData *peer() const;
|
PeerData *peer() const;
|
||||||
|
@ -200,7 +201,7 @@ public:
|
||||||
void updateOnlineDisplayTimer();
|
void updateOnlineDisplayTimer();
|
||||||
|
|
||||||
void updateNotifySettings();
|
void updateNotifySettings();
|
||||||
void mediaOverviewUpdated(PeerData *peer);
|
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
~ProfileWidget();
|
~ProfileWidget();
|
||||||
|
|
|
@ -156,6 +156,8 @@ int gNotifyDefaultDelay = 1500;
|
||||||
|
|
||||||
int gOtherOnline = 0;
|
int gOtherOnline = 0;
|
||||||
|
|
||||||
|
float64 gSongVolume = 0.9;
|
||||||
|
|
||||||
void settingsParseArgs(int argc, char *argv[]) {
|
void settingsParseArgs(int argc, char *argv[]) {
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
gCustomNotifies = (QSysInfo::macVersion() < QSysInfo::MV_10_8);
|
gCustomNotifies = (QSysInfo::macVersion() < QSysInfo::MV_10_8);
|
||||||
|
|
|
@ -304,4 +304,6 @@ DeclareSetting(int, NotifyDefaultDelay);
|
||||||
|
|
||||||
DeclareSetting(int, OtherOnline);
|
DeclareSetting(int, OtherOnline);
|
||||||
|
|
||||||
|
DeclareSetting(float64, SongVolume);
|
||||||
|
|
||||||
void settingsParseArgs(int argc, char *argv[]);
|
void settingsParseArgs(int argc, char *argv[]);
|
||||||
|
|
|
@ -448,7 +448,7 @@ void AudioOpenLink::onClick(Qt::MouseButton button) const {
|
||||||
AudioMsgId playing;
|
AudioMsgId playing;
|
||||||
AudioPlayerState playingState = AudioPlayerStopped;
|
AudioPlayerState playingState = AudioPlayerStopped;
|
||||||
audioPlayer()->currentState(&playing, &playingState);
|
audioPlayer()->currentState(&playing, &playingState);
|
||||||
if (playing.msgId == App::hoveredLinkItem()->id && playingState != AudioPlayerStopped) {
|
if (playing.msgId == App::hoveredLinkItem()->id && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||||
audioPlayer()->pauseresume(OverviewAudios);
|
audioPlayer()->pauseresume(OverviewAudios);
|
||||||
} else {
|
} else {
|
||||||
audioPlayer()->play(AudioMsgId(data, App::hoveredLinkItem()->id));
|
audioPlayer()->play(AudioMsgId(data, App::hoveredLinkItem()->id));
|
||||||
|
@ -545,9 +545,8 @@ QString AudioData::already(bool check) {
|
||||||
return location.name;
|
return location.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DocumentOpenLink::onClick(Qt::MouseButton button) const {
|
void DocumentOpenLink::doOpen(DocumentData *data) {
|
||||||
DocumentData *data = document();
|
if (!data->date) return;
|
||||||
if (!data->date || button != Qt::LeftButton) return;
|
|
||||||
|
|
||||||
bool play = data->song() && App::hoveredLinkItem() && audioPlayer();
|
bool play = data->song() && App::hoveredLinkItem() && audioPlayer();
|
||||||
QString already = data->already(true);
|
QString already = data->already(true);
|
||||||
|
@ -556,10 +555,12 @@ void DocumentOpenLink::onClick(Qt::MouseButton button) const {
|
||||||
SongMsgId playing;
|
SongMsgId playing;
|
||||||
AudioPlayerState playingState = AudioPlayerStopped;
|
AudioPlayerState playingState = AudioPlayerStopped;
|
||||||
audioPlayer()->currentState(&playing, &playingState);
|
audioPlayer()->currentState(&playing, &playingState);
|
||||||
if (playing.msgId == App::hoveredLinkItem()->id && playingState != AudioPlayerStopped) {
|
if (playing.msgId == App::hoveredLinkItem()->id && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) {
|
||||||
audioPlayer()->pauseresume(OverviewDocuments);
|
audioPlayer()->pauseresume(OverviewDocuments);
|
||||||
} else {
|
} else {
|
||||||
audioPlayer()->play(SongMsgId(data, App::hoveredLinkItem()->id));
|
SongMsgId song(data, App::hoveredLinkItem()->id);
|
||||||
|
audioPlayer()->play(song);
|
||||||
|
if (App::main()) App::main()->documentPlayProgress(song);
|
||||||
}
|
}
|
||||||
} else if (data->size < MediaViewImageSizeLimit) {
|
} else if (data->size < MediaViewImageSizeLimit) {
|
||||||
QImageReader reader(already);
|
QImageReader reader(already);
|
||||||
|
@ -604,6 +605,11 @@ void DocumentOpenLink::onClick(Qt::MouseButton button) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DocumentOpenLink::onClick(Qt::MouseButton button) const {
|
||||||
|
if (button != Qt::LeftButton) return;
|
||||||
|
doOpen(document());
|
||||||
|
}
|
||||||
|
|
||||||
void DocumentSaveLink::doSave(DocumentData *data, bool forceSavingAs) {
|
void DocumentSaveLink::doSave(DocumentData *data, bool forceSavingAs) {
|
||||||
if (!data->date) return;
|
if (!data->date) return;
|
||||||
|
|
||||||
|
|
|
@ -627,6 +627,7 @@ class DocumentOpenLink : public DocumentLink {
|
||||||
public:
|
public:
|
||||||
DocumentOpenLink(DocumentData *document) : DocumentLink(document) {
|
DocumentOpenLink(DocumentData *document) : DocumentLink(document) {
|
||||||
}
|
}
|
||||||
|
static void doOpen(DocumentData *document);
|
||||||
void onClick(Qt::MouseButton button) const;
|
void onClick(Qt::MouseButton button) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -273,6 +273,7 @@ enum DataBlockId {
|
||||||
dbiRecentStickers = 0x26,
|
dbiRecentStickers = 0x26,
|
||||||
dbiDcOption = 0x27,
|
dbiDcOption = 0x27,
|
||||||
dbiTryIPv6 = 0x28,
|
dbiTryIPv6 = 0x28,
|
||||||
|
dbiSongVolume = 0x29,
|
||||||
|
|
||||||
dbiEncryptedWithSalt = 333,
|
dbiEncryptedWithSalt = 333,
|
||||||
dbiEncrypted = 444,
|
dbiEncrypted = 444,
|
||||||
|
|
|
@ -1712,10 +1712,10 @@ void Window::sendPaths() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::mediaOverviewUpdated(PeerData *peer) {
|
void Window::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
|
||||||
if (main) main->mediaOverviewUpdated(peer);
|
if (main) main->mediaOverviewUpdated(peer, type);
|
||||||
if (!_mediaView || _mediaView->isHidden()) return;
|
if (!_mediaView || _mediaView->isHidden()) return;
|
||||||
_mediaView->mediaOverviewUpdated(peer);
|
_mediaView->mediaOverviewUpdated(peer, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::documentUpdated(DocumentData *doc) {
|
void Window::documentUpdated(DocumentData *doc) {
|
||||||
|
|
|
@ -226,7 +226,7 @@ public:
|
||||||
|
|
||||||
void sendPaths();
|
void sendPaths();
|
||||||
|
|
||||||
void mediaOverviewUpdated(PeerData *peer);
|
void mediaOverviewUpdated(PeerData *peer, MediaOverviewType type);
|
||||||
void documentUpdated(DocumentData *doc);
|
void documentUpdated(DocumentData *doc);
|
||||||
void changingMsgId(HistoryItem *row, MsgId newId);
|
void changingMsgId(HistoryItem *row, MsgId newId);
|
||||||
|
|
||||||
|
|
|
@ -352,6 +352,10 @@
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="GeneratedFiles\Debug\moc_playerwidget.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="GeneratedFiles\Debug\moc_profilewidget.cpp">
|
<ClCompile Include="GeneratedFiles\Debug\moc_profilewidget.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
@ -618,6 +622,10 @@
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="GeneratedFiles\Deploy\moc_playerwidget.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="GeneratedFiles\Deploy\moc_profilewidget.cpp">
|
<ClCompile Include="GeneratedFiles\Deploy\moc_profilewidget.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
@ -909,6 +917,10 @@
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="GeneratedFiles\Release\moc_playerwidget.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="GeneratedFiles\Release\moc_profilewidget.cpp">
|
<ClCompile Include="GeneratedFiles\Release\moc_profilewidget.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
@ -1044,6 +1056,7 @@
|
||||||
<ClCompile Include="SourceFiles\mtproto\mtpSession.cpp" />
|
<ClCompile Include="SourceFiles\mtproto\mtpSession.cpp" />
|
||||||
<ClCompile Include="SourceFiles\overviewwidget.cpp" />
|
<ClCompile Include="SourceFiles\overviewwidget.cpp" />
|
||||||
<ClCompile Include="SourceFiles\passcodewidget.cpp" />
|
<ClCompile Include="SourceFiles\passcodewidget.cpp" />
|
||||||
|
<ClCompile Include="SourceFiles\playerwidget.cpp" />
|
||||||
<ClCompile Include="SourceFiles\profilewidget.cpp" />
|
<ClCompile Include="SourceFiles\profilewidget.cpp" />
|
||||||
<ClCompile Include="SourceFiles\pspecific_linux.cpp">
|
<ClCompile Include="SourceFiles\pspecific_linux.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
@ -1993,6 +2006,20 @@
|
||||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\mpg123-1.22.1\ports\MSVC++" "-I.\..\..\Libraries\mpg123-1.22.1\src\libmpg123" "-I.\..\..\Libraries\faad2-2.7\include" "-I.\..\..\Libraries\faad2-2.7\common\mp4ff" "-I.\..\..\Libraries\ffmpeg-2.6.3" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/passcodewidget.h"</Command>
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\mpg123-1.22.1\ports\MSVC++" "-I.\..\..\Libraries\mpg123-1.22.1\src\libmpg123" "-I.\..\..\Libraries\faad2-2.7\include" "-I.\..\..\Libraries\faad2-2.7\common\mp4ff" "-I.\..\..\Libraries\ffmpeg-2.6.3" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/passcodewidget.h"</Command>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="SourceFiles\playerwidget.h">
|
||||||
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">Moc%27ing playerwidget.h...</Message>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||||
|
<Command Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/playerwidget.h" -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\ffmpeg-2.6.3" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui"</Command>
|
||||||
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing playerwidget.h...</Message>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||||
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/playerwidget.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\ffmpeg-2.6.3" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui"</Command>
|
||||||
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Moc%27ing playerwidget.h...</Message>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||||
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/playerwidget.h" -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\mpg123-1.22.1\ports\MSVC++" "-I.\..\..\Libraries\mpg123-1.22.1\src\libmpg123" "-I.\..\..\Libraries\faad2-2.7\include" "-I.\..\..\Libraries\faad2-2.7\common\mp4ff" "-I.\..\..\Libraries\ffmpeg-2.6.3" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui"</Command>
|
||||||
|
</CustomBuild>
|
||||||
<ClInclude Include="SourceFiles\pspecific.h" />
|
<ClInclude Include="SourceFiles\pspecific.h" />
|
||||||
<CustomBuild Include="SourceFiles\pspecific_linux.h">
|
<CustomBuild Include="SourceFiles\pspecific_linux.h">
|
||||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
|
|
|
@ -903,6 +903,18 @@
|
||||||
<ClCompile Include="GeneratedFiles\Release\moc_autoupdater.cpp">
|
<ClCompile Include="GeneratedFiles\Release\moc_autoupdater.cpp">
|
||||||
<Filter>Generated Files\Release</Filter>
|
<Filter>Generated Files\Release</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="SourceFiles\playerwidget.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="GeneratedFiles\Deploy\moc_playerwidget.cpp">
|
||||||
|
<Filter>Generated Files\Deploy</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="GeneratedFiles\Debug\moc_playerwidget.cpp">
|
||||||
|
<Filter>Generated Files\Debug</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="GeneratedFiles\Release\moc_playerwidget.cpp">
|
||||||
|
<Filter>Generated Files\Release</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="SourceFiles\stdafx.h">
|
<ClInclude Include="SourceFiles\stdafx.h">
|
||||||
|
@ -1198,6 +1210,9 @@
|
||||||
<CustomBuild Include="SourceFiles\autoupdater.h">
|
<CustomBuild Include="SourceFiles\autoupdater.h">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="SourceFiles\playerwidget.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</CustomBuild>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="SourceFiles\art\icon256.ico" />
|
<Image Include="SourceFiles\art\icon256.ico" />
|
||||||
|
|
Loading…
Reference in New Issue