updated music player, added native controls

This commit is contained in:
Alexander Karpov 2023-09-30 16:43:58 +03:00
parent b02a77ec5e
commit 3405b76897
6 changed files with 1519 additions and 1581 deletions

View File

@ -0,0 +1,22 @@
# Generated by Django 4.2.5 on 2023-09-30 11:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("music", "0008_song_meta"),
]
operations = [
migrations.AlterField(
model_name="songinque",
name="name",
field=models.CharField(blank=True, max_length=500),
),
migrations.AlterField(
model_name="songinque",
name="status",
field=models.CharField(blank=True, max_length=500, null=True),
),
]

View File

@ -4,6 +4,7 @@
from akarpov.common.models import BaseImageModel
from akarpov.tools.shortener.models import ShortLinkModel
from akarpov.users.services.history import UserHistoryModel
from akarpov.utils.cache import cache_model_property
class Author(BaseImageModel, ShortLinkModel):
@ -47,17 +48,35 @@ def get_absolute_url(self):
return reverse("music:song", kwargs={"slug": self.slug})
@property
def full_props(self) -> str:
if self.album and self.authors:
return f"{self.album.name} - " + ", ".join(
self.authors.values_list("name", flat=True)
)
elif self.album:
return f"{self.album.name}"
elif self.album:
def full_props(self):
if self.album_name and self.artists_names:
return f"{self.album_name} - {self.artists_names}"
elif self.album_name:
return self.album_name
elif self.artists_names:
return self.artists_names
return ""
@property
def _album_name(self):
if self.album and self.album.name:
return self.album.name
return ""
@property
def _authors_names(self):
if self.authors:
return ", ".join(self.authors.values_list("name", flat=True))
return ""
@property
def album_name(self):
return cache_model_property(self, "_album_name")
@property
def artists_names(self):
return cache_model_property(self, "_authors_names")
def __str__(self):
return self.name

View File

@ -1,5 +1,5 @@
function addEventListener_multi(element, eventNames, handler) {
var events = eventNames.split(' ');
const events = eventNames.split(' ');
events.forEach(e => element.addEventListener(e, handler, false));
}
@ -12,9 +12,9 @@ function getRandom(min, max) {
// Position element inside element
function getRelativePos(elm) {
var pPos = elm.parentNode.getBoundingClientRect(); // parent pos
var cPos = elm.getBoundingClientRect(); // target pos
var pos = {};
const pPos = elm.parentNode.getBoundingClientRect(); // parent pos
const cPos = elm.getBoundingClientRect(); // target pos
const pos = {};
pos.top = cPos.top - pPos.top + elm.parentNode.scrollTop,
pos.right = cPos.right - pPos.right,
@ -25,7 +25,7 @@ function getRelativePos(elm) {
}
function formatTime(val) {
var h = 0, m = 0, s;
let h = 0, m = 0, s;
val = parseInt(val, 10);
if (val > 60 * 60) {
h = parseInt(val / (60 * 60), 10);
@ -56,7 +56,7 @@ function simp_initTime() {
simp_audio.removeEventListener('timeupdate', simp_initTime);
if (simp_isNext) { //auto load next audio
var elem;
let elem;
simp_a_index++;
if (simp_a_index == simp_a_url.length) { //repeat all audio
simp_a_index = 0;
@ -144,7 +144,7 @@ function simp_changeAudio(elem) {
elem = simp_isRandom && simp_isNext ? simp_a_url[getRandom(0, simp_a_url.length-1)] : elem;
// playlist, audio is running
for (var i = 0; i < simp_a_url.length; i++) {
for (let i = 0; i < simp_a_url.length; i++) {
simp_a_url[i].parentNode.classList.remove('simp-active');
if (simp_a_url[i] == elem) {
simp_a_index = i;
@ -153,7 +153,7 @@ function simp_changeAudio(elem) {
}
// scrolling to element inside element
var simp_active = getRelativePos(simp_source[simp_a_index]);
const simp_active = getRelativePos(simp_source[simp_a_index]);
simp_source[simp_a_index].parentNode.scrollTop = simp_active.top;
if (simp_auto_load || simp_isPlaying) simp_loadAudio(elem);
@ -162,6 +162,95 @@ function simp_changeAudio(elem) {
simp_controls.querySelector('.simp-plause').classList.remove('fa-play');
simp_controls.querySelector('.simp-plause').classList.add('fa-pause');
}
// set native audio properties
if('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: elem.textContent,
artist: elem.dataset.artists,
album: elem.dataset.album,
artwork: [
{ src: elem.dataset.cover, sizes: '96x96', type: 'image/png' },
{ src: elem.dataset.cover, sizes: '128x128', type: 'image/png' },
{ src: elem.dataset.cover, sizes: '192x192', type: 'image/png' },
{ src: elem.dataset.cover, sizes: '256x256', type: 'image/png' },
{ src: elem.dataset.cover, sizes: '384x384', type: 'image/png' },
{ src: elem.dataset.cover, sizes: '512x512', type: 'image/png' }
]
});
navigator.mediaSession.setActionHandler('play', () => {
let eles = document.getElementById("simp-plause").classList
if (simp_audio.paused) {
if (!simp_isLoaded) simp_loadAudio(simp_a_url[simp_a_index]);
simp_audio.play();
simp_isPlaying = true;
eles.remove('fa-play');
eles.add('fa-pause');
} else {
simp_audio.pause();
simp_isPlaying = false;
eles.remove('fa-pause');
eles.add('fa-play');
}
});
navigator.mediaSession.setActionHandler('pause', () => {
let eles = document.getElementById("simp-plause").classList
if (simp_audio.paused) {
if (!simp_isLoaded) simp_loadAudio(simp_a_url[simp_a_index]);
simp_audio.play();
simp_isPlaying = true;
eles.remove('fa-play');
eles.add('fa-pause');
} else {
simp_audio.pause();
simp_isPlaying = false;
eles.remove('fa-pause');
eles.add('fa-play');
}
});
navigator.mediaSession.setActionHandler("previoustrack", () => {
let eles = document.getElementById("simp-previoustrack")
if (simp_a_index !== 0) {
simp_a_index = simp_a_index-1;
eles.disabled = simp_a_index == 0 ? true : false;
}
simp_audio.removeEventListener('timeupdate', simp_initTime);
simp_changeAudio(simp_a_url[simp_a_index]);
simp_setAlbum(simp_a_index);
});
navigator.mediaSession.setActionHandler("nexttrack", () => {
let eles = document.getElementById("simp-nexttrack")
if (simp_a_index !== simp_a_url.length-1) {
simp_a_index = simp_a_index+1;
eles.disabled = simp_a_index == simp_a_url.length-1 ? true : false;
}
simp_audio.removeEventListener('timeupdate', simp_initTime);
simp_changeAudio(simp_a_url[simp_a_index]);
simp_setAlbum(simp_a_index);
});
navigator.mediaSession.setActionHandler('seekbackward', (details) => {
simp_audio.currentTime = simp_audio.currentTime - (details.seekOffset || 10);
});
navigator.mediaSession.setActionHandler('seekforward', (details) => {
simp_audio.currentTime = simp_audio.currentTime + (details.seekOffset || 10);
});
navigator.mediaSession.setActionHandler('seekto', (details) => {
if (details.fastSeek && 'fastSeek' in simp_audio) {
simp_audio.fastSeek(details.seekTime);
return;
}
simp_audio.currentTime = details.seekTime;
});
navigator.mediaSession.setActionHandler('stop', () => {
let eles = document.getElementById("simp-plause").classList
simp_audio.currentTime = 0;
simp_controls.querySelector('.start-time').innerHTML = '00:00';
if (!simp_isLoaded) simp_loadAudio(simp_a_url[simp_a_index]);
simp_audio.play();
simp_isPlaying = true;
eles.remove('fa-play');
eles.add('fa-pause');
});
}
}
function simp_startScript() {
@ -210,7 +299,7 @@ function simp_startScript() {
// Controls listeners
simp_controls.querySelector('.simp-plauseward').addEventListener('click', function(e) {
var eles = e.target.classList;
const eles = e.target.classList;
if (eles.contains('simp-plause')) {
if (simp_audio.paused) {
if (!simp_isLoaded) simp_loadAudio(simp_a_url[simp_a_index]);
@ -240,7 +329,7 @@ function simp_startScript() {
// Audio volume
simp_volume.addEventListener('click', function(e) {
var eles = e.target.classList;
const eles = e.target.classList;
if (eles.contains('simp-mute')) {
if (eles.contains('fa-volume-up')) {
eles.remove('fa-volume-up');
@ -263,7 +352,7 @@ function simp_startScript() {
// Others
simp_others.addEventListener('click', function(e) {
var eles = e.target.classList;
const eles = e.target.classList;
if (eles.contains('simp-plext')) {
simp_isNext = simp_isNext && !simp_isRandom ? false : true;
if (!simp_isRandom) simp_isRanext = simp_isRanext ? false : true;
@ -296,7 +385,7 @@ if (document.querySelector('#simp')) {
var simp_a_url = simp_playlist.querySelectorAll('[data-src]');
var simp_a_index = 0;
var simp_isPlaying = false;
var simp_isNext = false; //auto play
var simp_isNext = true; //auto play
var simp_isRandom = false; //play random
var simp_isRanext = false; //check if before random starts, simp_isNext value is true
var simp_isStream = false; //radio streaming
@ -307,18 +396,18 @@ if (document.querySelector('#simp')) {
auto_load: false //auto load audio file
};
var simp_elem = '';
let simp_elem = '';
simp_elem += '<audio id="audio" preload><source src="" type="audio/mpeg"></audio>';
simp_elem += '<div class="simp-display"><div class="simp-album w-full flex-wrap"><div class="simp-cover"><i class="fa fa-music fa-5x"></i></div><div class="simp-info"><div class="simp-title">Title</div><div class="simp-artist">Artist</div></div></div></div>';
simp_elem += '<div class="simp-controls flex-wrap flex-align">';
simp_elem += '<div class="simp-plauseward flex flex-align"><button type="button" class="simp-prev fa fa-backward" disabled></button><button type="button" class="simp-plause fa fa-play" disabled></button><button type="button" class="simp-next fa fa-forward" disabled></button></div>';
simp_elem += '<div class="simp-plauseward flex flex-align"><button type="button" class="simp-prev fa fa-backward" id="simp-previoustrack" disabled></button><button id="simp-plause" type="button" class="simp-plause fa fa-play" disabled></button><button id="simp-nexttrack" type="button" class="simp-next fa fa-forward" disabled></button></div>';
simp_elem += '<div class="simp-tracker simp-load"><input class="simp-progress" type="range" min="0" max="100" value="0" disabled/><div class="simp-buffer"></div></div>';
simp_elem += '<div class="simp-time flex flex-align"><span class="start-time">00:00</span><span class="simp-slash">&#160;/&#160;</span><span class="end-time">00:00</span></div>';
simp_elem += '<div class="simp-volume flex flex-align"><button type="button" class="simp-mute fa fa-volume-up"></button><input class="simp-v-slider" type="range" min="0" max="100" value="100"/></div>';
simp_elem += '<div class="simp-others flex flex-align"><button type="button" class="simp-plext fa fa-play-circle" title="Auto Play"></button><button type="button" class="simp-random fa fa-random" title="Random"></button><div class="simp-shide"><button type="button" class="simp-shide-top fa fa-caret-up" title="Show/Hide Album"></button><button type="button" class="simp-shide-bottom fa fa-caret-down" title="Show/Hide Playlist"></button></div></div>';
simp_elem += '<div class="simp-others flex flex-align"><button type="button" class="simp-plext fa fa-play-circle simp-active" title="Auto Play" ></button><button type="button" class="simp-random fa fa-random" title="Random"></button><div class="simp-shide"><button type="button" class="simp-shide-top fa fa-caret-up" title="Show/Hide Album"></button><button type="button" class="simp-shide-bottom fa fa-caret-down" title="Show/Hide Playlist"></button></div></div>';
simp_elem += '</div>'; //simp-controls
var simp_player = document.createElement('div');
const simp_player = document.createElement('div');
simp_player.classList.add('simp-player');
simp_player.innerHTML = simp_elem;
ap_simp.insertBefore(simp_player, simp_playlist);

View File

@ -5,11 +5,11 @@
{% endblock %}
{% block content %}
<div class="d-flex align-items-center justify-content-center">
<div class="simple-audio-player flex-column" id="simp" data-config='{"shide_top":false,"shide_btm":false,"auto_load":false}'>
<div class="simple-audio-player flex-column" id="simp" data-config='{"shide_top":false,"shide_btm":false,"auto_load":true}'>
<div class="simp-playlist">
<ul>
{% for song in song_list %}
<li><span class="simp-source" {% if song.image %}data-cover="{{ song.image.url }}"{% endif %} data-src="{{ song.file.url }}">{{ song.name }}</span><span class="simp-desc">{{ song.full_props }}</span></li>
<li><span class="simp-source" {% if song.image %}data-cover="{{ song.image.url }}"{% endif %} data-artists="{{ song.artists_names }}" data-albumn="{{ song.album_name }}" data-src="{{ song.file.url }}">{{ song.name }}</span><span class="simp-desc">{{ song.full_props }}</span></li>
{% endfor %}
</ul>
</div>

2894
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -82,7 +82,6 @@ xvfbwrapper = "^0.2.9"
vtk = "^9.2.6"
ffmpeg-python = "^0.2.0"
cairosvg = "^2.7.0"
textract = "^1.6.5"
spotipy = "2.16.1"
django-robots = "^5.0"
django-tables2 = "^2.5.3"
@ -109,6 +108,7 @@ pytest-asyncio = "^0.21.1"
pytest-lambda = "^2.2.0"
pgvector = "^0.2.2"
pycld2 = "^0.41"
textract = "^1.6.5"
[build-system]