document.body.style.paddingRight = `${window.innerWidth - document.body.clientWidth}px`; document.body.style.overflow = 'hidden'; const internalConfig = { 'network': { 'userAgent': { 'chromeWindows': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36', 'curl': 'curl/8.4.0', 'curlUnity': 'UnityPlayer/2021.3.14f1 (UnityWebRequest/1.0, libcurl/7.84.0-DEV)' }, 'timeout': 15000 } }; const apiConnectDefaultHeader = { 'Access-Controll-Allow-Origin': '*' } const appSettingsStorageName = '018d2fc7-d0bb-7393-9ebc-6f6ec26b03ce_appSettings'; let appSettingsSaveData = new Object(); const appSettingsSaveDataDefault = { 'ui': { 'uiThemeMode': 'light' } }; let apiDataMasterDB = new Object(); let apiDataConfig = new Object(); let bootstrapTooltipList = null; //!========== ページ読み込み時に実行する処理 ========== window.addEventListener('load', async function(){ if (checkAppSettingsExistsOnStorage() === true) { loadAppSettingsFromLocalStorage(); } else { loadAppSettingsFromLocalStorage(); if (window.matchMedia('(prefers-color-scheme:dark)').matches === true) { console.warn(`prefers-color-scheme:dark detected`); if (appSettingsSaveData.ui.uiThemeMode !== 'dark') { appSettingsSaveData.ui.uiThemeMode = 'dark'; writeAppSettingsToLocalStorage(); } } else { appSettingsSaveData.ui.uiThemeMode = 'light'; writeAppSettingsToLocalStorage(); } } appSettingsCheckedUiUpdate(); appSettingsApply(); await loadRequiredDatabase(); await decryptConfig(); pushToTrackListGroupUi(); pushToAlbumListGroupUi(); fsOverlayLoadingScrControl(); }); document.querySelector('#loadDatabaseTestButton').addEventListener('click', async function() { console.log('loadDatabaseTestButton clicked!'); await loadRequiredDatabase(); await decryptConfig(); }); document.querySelector('#trackListingTestButton').addEventListener('click', () => { console.log('trackListingTestButton clicked!'); pushToTrackListGroupUi(); }); // ========== fsOverlayLoadingScr制御 ========== function fsOverlayLoadingScrControl () { document.getElementById('fsOverlayLoadingScr').style.backgroundColor = 'rgba(0,0,0,0)'; document.getElementById('fsOverlayLoadingScr').style.visibility = 'hidden'; document.getElementById('fsOverlayLoadingScr').style.backdropFilter = 'blur(0)'; document.getElementById('fsOverlayLoadingScr_loadingSpinner').style.opacity = 0; document.body.style.paddingRight = 0; document.body.style.overflow = 'auto'; } // ========== 全てのトラックのリストをTrack Listing TestのListGroupに表示 ========== function pushToTrackListGroupUi () { const trackAllListGroup = document.querySelector('#trackAllListGroup'); while(trackAllListGroup.firstChild) { trackAllListGroup.removeChild(trackAllListGroup.firstChild); } let headerElObj = new Object(); headerElObj.buttonNodeEl = document.createElement('button'); headerElObj.divArtistNodeEl = document.createElement('div'); headerElObj.divAlbumNodeEl = document.createElement('div'); headerElObj.divTrackNodeEl = document.createElement('div'); headerElObj.buttonNodeEl.classList.add('list-group-item', 'list-group-item-action', 'd-flex'); headerElObj.buttonNodeEl.setAttribute('type', 'button'); headerElObj.buttonNodeEl.disabled = true; headerElObj.divArtistNodeEl.classList.add('flex-fill', 'w-100'); headerElObj.divAlbumNodeEl.classList.add('flex-fill', 'w-100'); headerElObj.divTrackNodeEl.classList.add('flex-fill', 'w-100'); headerElObj.divArtistNodeEl.innerHTML = 'Artist'; headerElObj.divAlbumNodeEl.innerHTML = 'Album'; headerElObj.divTrackNodeEl.innerHTML = 'Track'; headerElObj.buttonNodeEl.appendChild(headerElObj.divArtistNodeEl); headerElObj.buttonNodeEl.appendChild(headerElObj.divAlbumNodeEl); headerElObj.buttonNodeEl.appendChild(headerElObj.divTrackNodeEl); trackAllListGroup.appendChild(headerElObj.buttonNodeEl); apiDataMasterDB.response.data.albums.forEach((albumObject) => { albumObject.tracks.forEach((trackObject) => { let buttonNodeEl = document.createElement('button'); let divArtistNodeEl = document.createElement('div'); let divAlbumNodeEl = document.createElement('div'); let divTrackNodeEl = document.createElement('div'); buttonNodeEl.classList.add('list-group-item', 'list-group-item-action', 'd-flex'); buttonNodeEl.setAttribute('type', 'button'); buttonNodeEl.setAttribute('data-track-uuid', trackObject.uuid); divArtistNodeEl.classList.add('flex-fill', 'w-100'); divAlbumNodeEl.classList.add('flex-fill', 'w-100'); divTrackNodeEl.classList.add('flex-fill', 'w-100'); let albumArtistFilteredList = new Array(); albumObject.artist.forEach((str) => { albumArtistFilteredList.push(apiDataMasterDB.response.data.artists.filter((obj) => obj.uuid === str)[0].name); }); divArtistNodeEl.innerHTML = albumArtistFilteredList.join(', '); divAlbumNodeEl.innerHTML = albumObject.title; divTrackNodeEl.innerHTML = trackObject.title; buttonNodeEl.appendChild(divArtistNodeEl); buttonNodeEl.appendChild(divAlbumNodeEl); buttonNodeEl.appendChild(divTrackNodeEl); buttonNodeEl.addEventListener('click', () => { loadTrackInfoModal(trackObject.uuid); }); trackAllListGroup.appendChild(buttonNodeEl); }); }); } // ========== Album Listをビルド ========== function pushToAlbumListGroupUi () { const albumAllCardGroup = document.getElementById('albumAllCardGroup'); while(albumAllCardGroup.firstChild) { albumAllCardGroup.removeChild(albumAllCardGroup.firstChild); } apiDataMasterDB.response.data.albums.forEach((albumObject) => { let albumParsedObject = getParsedAlbumObjectFromAlbumUuid(albumObject.uuid); let elementObj = new Object(); elementObj.colDiv = document.createElement('div'); elementObj.cardDiv = document.createElement('div'); elementObj.cardBodyDiv = document.createElement('div'); elementObj.cardImgDiv = document.createElement('div'); elementObj.cardImg = document.createElement('img'); elementObj.cardTitle = document.createElement('h5'); elementObj.cardText = document.createElement('p'); elementObj.colDiv.classList.add('col'); elementObj.cardDiv.classList.add('card', 'h-100'); elementObj.cardBodyDiv.classList.add('card-body'); elementObj.cardImgDiv.classList.add('object-fit-cover', 'cs_card-img-wrapper') elementObj.cardImg.classList.add('card-img-top', 'object-fit-cover', 'lazyload', 'customlazyload-blur', 'user-select-none', 'user-drag-none', 'pe-none'); elementObj.cardTitle.classList.add('card-title'); elementObj.cardText.classList.add('card-text'); elementObj.cardImg.src = `data:image/webp;base64,${albumObject.coverArtPotatoWebp16pxBase64}`; // elementObj.cardImg.src = `data:image/bmp;base64,${albumObject.coverArtPotatoBmp8pxBase64}`; elementObj.cardImg.setAttribute('data-src', `${apiDataConfig.response.config.decrypted.rawMediaUrlBase64}/media/${albumParsedObject.uuid}/${albumParsedObject.coverArts.slice(-1)[0].fileName}.${albumParsedObject.coverArts.slice(-1)[0].format[0].extension}`); // elementObj.cardImg.setAttribute('loading', 'lazy'); elementObj.cardTitle.innerHTML = albumParsedObject.title; elementObj.cardText.innerHTML = albumParsedObject.artist.map((obj) => obj.name).join(', '); elementObj.cardBodyDiv.appendChild(elementObj.cardTitle); elementObj.cardBodyDiv.appendChild(elementObj.cardText); elementObj.cardImgDiv.appendChild(elementObj.cardImg); elementObj.cardDiv.appendChild(elementObj.cardImgDiv); elementObj.cardDiv.appendChild(elementObj.cardBodyDiv); elementObj.cardDiv.addEventListener('click', () => {loadAlbumInfoModal(albumParsedObject.uuid)}); elementObj.colDiv.appendChild(elementObj.cardDiv); albumAllCardGroup.appendChild(elementObj.colDiv); }); } // ========== trackInfoModalの処理 ========== function loadTrackInfoModal (trackUuid) { const albumParsedObject = getParsedAlbumObjectFromAlbumUuid(getAlbumUuidFromTrackUuid(trackUuid)); const trackParsedObject = albumParsedObject.tracks.find((obj) => obj.uuid === trackUuid); if (bootstrapTooltipList !== null) {bootstrapTooltipList.forEach(el => el.dispose())} document.getElementById('trackInfoModal-metadataTable-trackTitle').innerHTML = trackParsedObject.title; if (trackParsedObject.titleLatin === null) { document.getElementById('trackInfoModal-metadataTable-trackTitle').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal-metadataTable-trackTitle').removeAttribute('data-bs-title'); } else { document.getElementById('trackInfoModal-metadataTable-trackTitle').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal-metadataTable-trackTitle').setAttribute('data-bs-title', trackParsedObject.titleLatin); } document.getElementById('trackInfoModal-metadataTable-artists').innerHTML = trackParsedObject.artist.map((obj) => obj.name).join(', '); if (trackParsedObject.artist.some((obj) => obj.nameLatin !== null)) { document.getElementById('trackInfoModal-metadataTable-artists').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal-metadataTable-artists').setAttribute('data-bs-title', trackParsedObject.artist.map((obj) => {if (obj.nameLatin !== null) {return obj.nameLatin} else {return obj.name}}).join(', ')); } else { document.getElementById('trackInfoModal-metadataTable-artists').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal-metadataTable-artists').removeAttribute('data-bs-title'); } if (trackParsedObject.lyricist === null) { document.getElementById('trackInfoModal-metadataTable-lyricist').parentNode.classList.add('d-none'); document.getElementById('trackInfoModal-metadataTable-lyricist').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal-metadataTable-lyricist').removeAttribute('data-bs-title'); } else { document.getElementById('trackInfoModal-metadataTable-lyricist').parentNode.classList.remove('d-none'); document.getElementById('trackInfoModal-metadataTable-lyricist').innerHTML = trackParsedObject.lyricist.map((obj) => obj.name).join(', '); if (trackParsedObject.lyricist.some((obj) => obj.nameLatin !== null)) { document.getElementById('trackInfoModal-metadataTable-lyricist').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal-metadataTable-lyricist').setAttribute('data-bs-title', trackParsedObject.lyricist.map((obj) => {if (obj.nameLatin !== null) {return obj.nameLatin} else {return obj.name}}).join(', ')); } else { document.getElementById('trackInfoModal-metadataTable-lyricist').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal-metadataTable-lyricist').removeAttribute('data-bs-title'); } } if (trackParsedObject.composer === null) { document.getElementById('trackInfoModal-metadataTable-composer').parentNode.classList.add('d-none'); document.getElementById('trackInfoModal-metadataTable-composer').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal-metadataTable-composer').removeAttribute('data-bs-title'); } else { document.getElementById('trackInfoModal-metadataTable-composer').parentNode.classList.remove('d-none'); document.getElementById('trackInfoModal-metadataTable-composer').innerHTML = trackParsedObject.composer.map((obj) => obj.name).join(', '); if (trackParsedObject.composer.some((obj) => obj.nameLatin !== null)) { document.getElementById('trackInfoModal-metadataTable-composer').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal-metadataTable-composer').setAttribute('data-bs-title', trackParsedObject.composer.map((obj) => {if (obj.nameLatin !== null) {return obj.nameLatin} else {return obj.name}}).join(', ')); } else { document.getElementById('trackInfoModal-metadataTable-composer').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal-metadataTable-composer').removeAttribute('data-bs-title'); } } if (trackParsedObject.arranger === null) { document.getElementById('trackInfoModal-metadataTable-arranger').parentNode.classList.add('d-none'); document.getElementById('trackInfoModal-metadataTable-arranger').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal-metadataTable-arranger').removeAttribute('data-bs-title'); } else { document.getElementById('trackInfoModal-metadataTable-arranger').parentNode.classList.remove('d-none'); document.getElementById('trackInfoModal-metadataTable-arranger').innerHTML = trackParsedObject.arranger.map((obj) => obj.name).join(', '); if (trackParsedObject.arranger.some((obj) => obj.nameLatin !== null)) { document.getElementById('trackInfoModal-metadataTable-arranger').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal-metadataTable-arranger').setAttribute('data-bs-title', trackParsedObject.arranger.map((obj) => {if (obj.nameLatin !== null) {return obj.nameLatin} else {return obj.name}}).join(', ')); } else { document.getElementById('trackInfoModal-metadataTable-arranger').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal-metadataTable-arranger').removeAttribute('data-bs-title'); } } document.getElementById('trackInfoModal-metadataTable-trackDurationReadable').innerHTML = msecToReadableTime(trackParsedObject.durationMsecs); document.getElementById('trackInfoModal-metadataTable-trackDurationMsec').innerHTML = `${Math.ceil(trackParsedObject.durationMsecs)} ms`; document.getElementById('trackInfoModal-metadataTable-trackDurationSamples').innerHTML = `${trackParsedObject.durationSamples} samples`; document.getElementById('trackInfoModal-metadataTable-albumTitle').innerHTML = albumParsedObject.title; if (albumParsedObject.titleLatin === null) { document.getElementById('trackInfoModal-metadataTable-albumTitle').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal-metadataTable-albumTitle').removeAttribute('data-bs-title'); } else { document.getElementById('trackInfoModal-metadataTable-albumTitle').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal-metadataTable-albumTitle').setAttribute('data-bs-title', albumParsedObject.titleLatin); } document.getElementById('trackInfoModal-metadataTable-albumArtist').innerHTML = albumParsedObject.artist.map((obj) => obj.name).join(', '); if (albumParsedObject.artist.some((obj) => obj.nameLatin !== null)) { document.getElementById('trackInfoModal-metadataTable-albumArtist').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal-metadataTable-albumArtist').setAttribute('data-bs-title', albumParsedObject.artist.map((obj) => {if (obj.nameLatin !== null) {return obj.nameLatin} else {return obj.name}}).join(', ')); } else { document.getElementById('trackInfoModal-metadataTable-albumArtist').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal-metadataTable-albumArtist').removeAttribute('data-bs-title'); } document.getElementById('trackInfoModal-metadataTable-albumReleaseDate').innerHTML = moment(albumParsedObject.releaseDate).format('YYYY/MM/DD'); document.getElementById('trackInfoModal-metadataTable-albumBarcode').innerHTML = albumParsedObject.barCode; document.getElementById('trackInfoModal-metadataTable-albumCopyright').innerHTML = albumParsedObject.copyright; while(document.getElementById('trackInfoModal-externalLinkTable').firstChild) { document.getElementById('trackInfoModal-externalLinkTable').removeChild(document.getElementById('trackInfoModal-externalLinkTable').firstChild); } while(document.getElementById('trackInfoModal-coverArtLinkDiv').firstChild) { document.getElementById('trackInfoModal-coverArtLinkDiv').removeChild(document.getElementById('trackInfoModal-coverArtLinkDiv').firstChild); } while(document.getElementById('trackInfoModal-downloadTable').firstChild) { document.getElementById('trackInfoModal-downloadTable').removeChild(document.getElementById('trackInfoModal-downloadTable').firstChild); } if (albumParsedObject.link.itunes !== null || albumParsedObject.link.spotify !== null) { let temp_extLinkAlbumTrEl = document.createElement('tr'); let temp_extLinkAlbumTdKeyEl = document.createElement('td'); let temp_extLinkAlbumTdValueEl = document.createElement('td'); let temp_extLinkAlbumA1El = document.createElement('a'); let temp_extLinkAlbumA2El = document.createElement('a'); temp_extLinkAlbumTdKeyEl.innerHTML = 'Album Link'; if (albumParsedObject.link.itunes !== null) { temp_extLinkAlbumA1El.classList.add('btn','btn-outline-primary','btn-sm','me-2'); temp_extLinkAlbumA1El.setAttribute('href', `https://music.apple.com/album/${albumParsedObject.link.itunes}`); temp_extLinkAlbumA1El.setAttribute('role', 'button'); temp_extLinkAlbumA1El.setAttribute('target', '_blank'); temp_extLinkAlbumA1El.setAttribute('rel', 'noopener noreferrer'); temp_extLinkAlbumA1El.innerHTML = 'Apple Music'; temp_extLinkAlbumTdValueEl.appendChild(temp_extLinkAlbumA1El); } if (albumParsedObject.link.spotify !== null) { temp_extLinkAlbumA2El.classList.add('btn','btn-outline-primary','btn-sm','me-2'); temp_extLinkAlbumA2El.setAttribute('href', `https://open.spotify.com/album/${albumParsedObject.link.spotify}`); temp_extLinkAlbumA2El.setAttribute('role', 'button'); temp_extLinkAlbumA2El.setAttribute('target', '_blank'); temp_extLinkAlbumA2El.setAttribute('rel', 'noopener noreferrer'); temp_extLinkAlbumA2El.innerHTML = 'Spotify'; temp_extLinkAlbumTdValueEl.appendChild(temp_extLinkAlbumA2El); } temp_extLinkAlbumTrEl.appendChild(temp_extLinkAlbumTdKeyEl); temp_extLinkAlbumTrEl.appendChild(temp_extLinkAlbumTdValueEl); document.getElementById('trackInfoModal-externalLinkTable').appendChild(temp_extLinkAlbumTrEl); } albumParsedObject.coverArts.forEach((obj1) => { obj1.format.forEach((obj2) => { let temp_coverArtAEl = document.createElement('a'); temp_coverArtAEl.classList.add('btn','btn-primary','btn-sm','me-2','mb-2'); temp_coverArtAEl.setAttribute('href', `${apiDataConfig.response.config.decrypted.rawMediaUrlBase64}/media/${albumParsedObject.uuid}/${obj1.fileName}.${obj2.extension}`); temp_coverArtAEl.setAttribute('role', 'button'); temp_coverArtAEl.setAttribute('target', '_blank'); temp_coverArtAEl.setAttribute('rel', 'noopener noreferrer'); temp_coverArtAEl.innerHTML = `${obj2.name} ${obj1.height}px`; document.getElementById('trackInfoModal-coverArtLinkDiv').appendChild(temp_coverArtAEl); }); }); let temp_codecListImported = new Array(); if (albumParsedObject.isAllTrackSameCodecs === false) {temp_codecListImported = trackParsedObject.codecs} else {temp_codecListImported = albumParsedObject.codecs} temp_codecListImported.forEach((obj) => { let temp_dlTrEl = document.createElement('tr'); let temp_dlTdCodecEl = document.createElement('td'); let temp_dlTdInfoEl = document.createElement('td'); let temp_dlTdBtnEl = document.createElement('td'); let temp_dlButtonGroupEl = document.createElement('div'); let temp_dlButtonEl = document.createElement('button'); let temp_dlButtonExtEl = document.createElement('a'); let temp_dlButtonIconEl = document.createElement('i'); let temp_dlButtonExtIconEl = document.createElement('i'); let temp_codecBitrateTemporal = null; temp_dlTdCodecEl.innerHTML = obj.nameBasic; temp_dlTdCodecEl.setAttribute('data-bs-toggle', 'tooltip'); temp_dlTdCodecEl.setAttribute('data-bs-title', obj.nameLong); if ((obj.bitRateAvg !== null && obj.bitRateMax !== null) || (obj.bitRateAvg !== null && obj.bitRateMax === null)) { temp_codecBitrateTemporal = obj.bitRateAvg; } else { temp_codecBitrateTemporal = obj.bitRateMax; } if (obj.bitDepth === null) { temp_dlTdInfoEl.innerHTML = `${obj.sampleRate / 1000}kHz ${obj.channelCount}ch ${temp_codecBitrateTemporal / 1000}kbps`; } else { temp_dlTdInfoEl.innerHTML = `${obj.bitDepth}bit ${obj.sampleRate / 1000}kHz ${obj.channelCount}ch ${temp_codecBitrateTemporal / 1000}kbps`; } if (obj.isOriginal === true) { temp_dlButtonEl.classList.add('btn', 'btn-primary'); temp_dlButtonExtEl.classList.add('btn', 'btn-primary', 'text-center'); } else { temp_dlButtonEl.classList.add('btn', 'btn-secondary'); temp_dlButtonExtEl.classList.add('btn', 'btn-secondary', 'text-center'); } temp_dlButtonEl.setAttribute('type', 'button'); // temp_dlButtonEl.addEventListener('click', async () => { // await downloadAudioDataToBlob (trackParsedObject.uuid, obj.uuid) // }) temp_dlButtonExtEl.setAttribute('href', `${apiDataConfig.response.config.decrypted.rawMediaUrlBase64}/media/${albumParsedObject.uuid}/${obj.path}/${trackParsedObject.uuid}.${obj.extension}`); temp_dlButtonExtEl.setAttribute('download', determineDownloadFileName(trackParsedObject.uuid, obj.uuid)); temp_dlButtonExtEl.setAttribute('role', 'button'); temp_dlButtonExtEl.setAttribute('target', '_blank'); temp_dlButtonExtEl.setAttribute('rel', 'noopener noreferrer'); temp_dlButtonGroupEl.setAttribute('role', 'group'); temp_dlButtonGroupEl.classList.add('btn-group'); temp_dlButtonIconEl.classList.add('bi', 'bi-download'); temp_dlButtonExtIconEl.classList.add('bi', 'bi-box-arrow-up-right'); temp_dlTdBtnEl.classList.add('text-end'); temp_dlButtonEl.appendChild(temp_dlButtonIconEl); temp_dlButtonExtEl.appendChild(temp_dlButtonExtIconEl); // temp_dlButtonGroupEl.appendChild(temp_dlButtonEl); temp_dlButtonGroupEl.appendChild(temp_dlButtonExtEl); temp_dlTdBtnEl.appendChild(temp_dlButtonGroupEl); temp_dlTrEl.appendChild(temp_dlTdCodecEl); temp_dlTrEl.appendChild(temp_dlTdInfoEl); temp_dlTrEl.appendChild(temp_dlTdBtnEl); document.getElementById('trackInfoModal-downloadTable').appendChild(temp_dlTrEl); }); document.getElementById('trackInfoModal-previewAudio').src = `${apiDataConfig.response.config.decrypted.rawMediaUrlBase64}/media/${albumParsedObject.uuid}/${temp_codecListImported.slice(-1)[0].path}/${trackParsedObject.uuid}.${temp_codecListImported.slice(-1)[0].extension}`; const bootstrapTooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]'); bootstrapTooltipList = [...bootstrapTooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl)); document.getElementById('trackInfoModal-DebugAcdOutputEl').innerHTML = JSON.stringify(albumParsedObject, '', ' '); document.getElementById('trackInfoModal-ModalCloseButton').addEventListener('click', () => {allAudioElementStop()}); document.getElementById('trackInfoModal-ModalCloseIconButton').addEventListener('click', () => {allAudioElementStop()}); const trackInfoModal = new bootstrap.Modal(document.getElementById('trackInfoModal')); trackInfoModal.show(); } function loadTrackInfoModal2 (trackUuid) { const albumParsedObject = getParsedAlbumObjectFromAlbumUuid(getAlbumUuidFromTrackUuid(trackUuid)); const trackParsedObject = albumParsedObject.tracks.find((obj) => obj.uuid === trackUuid); if (bootstrapTooltipList !== null) {bootstrapTooltipList.forEach(el => el.dispose())} document.getElementById('trackInfoModal2-metadataTable-trackTitle').innerHTML = trackParsedObject.title; if (trackParsedObject.titleLatin === null) { document.getElementById('trackInfoModal2-metadataTable-trackTitle').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal2-metadataTable-trackTitle').removeAttribute('data-bs-title'); } else { document.getElementById('trackInfoModal2-metadataTable-trackTitle').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal2-metadataTable-trackTitle').setAttribute('data-bs-title', trackParsedObject.titleLatin); } document.getElementById('trackInfoModal2-metadataTable-artists').innerHTML = trackParsedObject.artist.map((obj) => obj.name).join(', '); if (trackParsedObject.artist.some((obj) => obj.nameLatin !== null)) { document.getElementById('trackInfoModal2-metadataTable-artists').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal2-metadataTable-artists').setAttribute('data-bs-title', trackParsedObject.artist.map((obj) => {if (obj.nameLatin !== null) {return obj.nameLatin} else {return obj.name}}).join(', ')); } else { document.getElementById('trackInfoModal2-metadataTable-artists').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal2-metadataTable-artists').removeAttribute('data-bs-title'); } if (trackParsedObject.lyricist === null) { document.getElementById('trackInfoModal2-metadataTable-lyricist').parentNode.classList.add('d-none'); document.getElementById('trackInfoModal2-metadataTable-lyricist').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal2-metadataTable-lyricist').removeAttribute('data-bs-title'); } else { document.getElementById('trackInfoModal2-metadataTable-lyricist').parentNode.classList.remove('d-none'); document.getElementById('trackInfoModal2-metadataTable-lyricist').innerHTML = trackParsedObject.lyricist.map((obj) => obj.name).join(', '); if (trackParsedObject.lyricist.some((obj) => obj.nameLatin !== null)) { document.getElementById('trackInfoModal2-metadataTable-lyricist').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal2-metadataTable-lyricist').setAttribute('data-bs-title', trackParsedObject.lyricist.map((obj) => {if (obj.nameLatin !== null) {return obj.nameLatin} else {return obj.name}}).join(', ')); } else { document.getElementById('trackInfoModal2-metadataTable-lyricist').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal2-metadataTable-lyricist').removeAttribute('data-bs-title'); } } if (trackParsedObject.composer === null) { document.getElementById('trackInfoModal2-metadataTable-composer').parentNode.classList.add('d-none'); document.getElementById('trackInfoModal2-metadataTable-composer').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal2-metadataTable-composer').removeAttribute('data-bs-title'); } else { document.getElementById('trackInfoModal2-metadataTable-composer').parentNode.classList.remove('d-none'); document.getElementById('trackInfoModal2-metadataTable-composer').innerHTML = trackParsedObject.composer.map((obj) => obj.name).join(', '); if (trackParsedObject.composer.some((obj) => obj.nameLatin !== null)) { document.getElementById('trackInfoModal2-metadataTable-composer').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal2-metadataTable-composer').setAttribute('data-bs-title', trackParsedObject.composer.map((obj) => {if (obj.nameLatin !== null) {return obj.nameLatin} else {return obj.name}}).join(', ')); } else { document.getElementById('trackInfoModal2-metadataTable-composer').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal2-metadataTable-composer').removeAttribute('data-bs-title'); } } if (trackParsedObject.arranger === null) { document.getElementById('trackInfoModal2-metadataTable-arranger').parentNode.classList.add('d-none'); document.getElementById('trackInfoModal2-metadataTable-arranger').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal2-metadataTable-arranger').removeAttribute('data-bs-title'); } else { document.getElementById('trackInfoModal2-metadataTable-arranger').parentNode.classList.remove('d-none'); document.getElementById('trackInfoModal2-metadataTable-arranger').innerHTML = trackParsedObject.arranger.map((obj) => obj.name).join(', '); if (trackParsedObject.arranger.some((obj) => obj.nameLatin !== null)) { document.getElementById('trackInfoModal2-metadataTable-arranger').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal2-metadataTable-arranger').setAttribute('data-bs-title', trackParsedObject.arranger.map((obj) => {if (obj.nameLatin !== null) {return obj.nameLatin} else {return obj.name}}).join(', ')); } else { document.getElementById('trackInfoModal2-metadataTable-arranger').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal2-metadataTable-arranger').removeAttribute('data-bs-title'); } } document.getElementById('trackInfoModal2-metadataTable-trackDurationReadable').innerHTML = msecToReadableTime(trackParsedObject.durationMsecs); document.getElementById('trackInfoModal2-metadataTable-trackDurationMsec').innerHTML = `${Math.ceil(trackParsedObject.durationMsecs)} ms`; document.getElementById('trackInfoModal2-metadataTable-trackDurationSamples').innerHTML = `${trackParsedObject.durationSamples} samples`; document.getElementById('trackInfoModal2-metadataTable-albumTitle').innerHTML = albumParsedObject.title; if (albumParsedObject.titleLatin === null) { document.getElementById('trackInfoModal2-metadataTable-albumTitle').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal2-metadataTable-albumTitle').removeAttribute('data-bs-title'); } else { document.getElementById('trackInfoModal2-metadataTable-albumTitle').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal2-metadataTable-albumTitle').setAttribute('data-bs-title', albumParsedObject.titleLatin); } document.getElementById('trackInfoModal2-metadataTable-albumArtist').innerHTML = albumParsedObject.artist.map((obj) => obj.name).join(', '); if (albumParsedObject.artist.some((obj) => obj.nameLatin !== null)) { document.getElementById('trackInfoModal2-metadataTable-albumArtist').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('trackInfoModal2-metadataTable-albumArtist').setAttribute('data-bs-title', albumParsedObject.artist.map((obj) => {if (obj.nameLatin !== null) {return obj.nameLatin} else {return obj.name}}).join(', ')); } else { document.getElementById('trackInfoModal2-metadataTable-albumArtist').removeAttribute('data-bs-toggle'); document.getElementById('trackInfoModal2-metadataTable-albumArtist').removeAttribute('data-bs-title'); } document.getElementById('trackInfoModal2-metadataTable-albumReleaseDate').innerHTML = moment(albumParsedObject.releaseDate).format('YYYY/MM/DD'); document.getElementById('trackInfoModal2-metadataTable-albumBarcode').innerHTML = albumParsedObject.barCode; document.getElementById('trackInfoModal2-metadataTable-albumCopyright').innerHTML = albumParsedObject.copyright; while(document.getElementById('trackInfoModal2-externalLinkTable').firstChild) { document.getElementById('trackInfoModal2-externalLinkTable').removeChild(document.getElementById('trackInfoModal2-externalLinkTable').firstChild); } while(document.getElementById('trackInfoModal2-coverArtLinkDiv').firstChild) { document.getElementById('trackInfoModal2-coverArtLinkDiv').removeChild(document.getElementById('trackInfoModal2-coverArtLinkDiv').firstChild); } while(document.getElementById('trackInfoModal2-downloadTable').firstChild) { document.getElementById('trackInfoModal2-downloadTable').removeChild(document.getElementById('trackInfoModal2-downloadTable').firstChild); } if (albumParsedObject.link.itunes !== null || albumParsedObject.link.spotify !== null) { let temp_extLinkAlbumTrEl = document.createElement('tr'); let temp_extLinkAlbumTdKeyEl = document.createElement('td'); let temp_extLinkAlbumTdValueEl = document.createElement('td'); let temp_extLinkAlbumA1El = document.createElement('a'); let temp_extLinkAlbumA2El = document.createElement('a'); temp_extLinkAlbumTdKeyEl.innerHTML = 'Album Link'; if (albumParsedObject.link.itunes !== null) { temp_extLinkAlbumA1El.classList.add('btn','btn-outline-primary','btn-sm','me-2'); temp_extLinkAlbumA1El.setAttribute('href', `https://music.apple.com/album/${albumParsedObject.link.itunes}`); temp_extLinkAlbumA1El.setAttribute('role', 'button'); temp_extLinkAlbumA1El.setAttribute('target', '_blank'); temp_extLinkAlbumA1El.setAttribute('rel', 'noopener noreferrer'); temp_extLinkAlbumA1El.innerHTML = 'Apple Music'; temp_extLinkAlbumTdValueEl.appendChild(temp_extLinkAlbumA1El); } if (albumParsedObject.link.spotify !== null) { temp_extLinkAlbumA2El.classList.add('btn','btn-outline-primary','btn-sm','me-2'); temp_extLinkAlbumA2El.setAttribute('href', `https://open.spotify.com/album/${albumParsedObject.link.spotify}`); temp_extLinkAlbumA2El.setAttribute('role', 'button'); temp_extLinkAlbumA2El.setAttribute('target', '_blank'); temp_extLinkAlbumA2El.setAttribute('rel', 'noopener noreferrer'); temp_extLinkAlbumA2El.innerHTML = 'Spotify'; temp_extLinkAlbumTdValueEl.appendChild(temp_extLinkAlbumA2El); } temp_extLinkAlbumTrEl.appendChild(temp_extLinkAlbumTdKeyEl); temp_extLinkAlbumTrEl.appendChild(temp_extLinkAlbumTdValueEl); document.getElementById('trackInfoModal2-externalLinkTable').appendChild(temp_extLinkAlbumTrEl); } albumParsedObject.coverArts.forEach((obj1) => { obj1.format.forEach((obj2) => { let temp_coverArtAEl = document.createElement('a'); temp_coverArtAEl.classList.add('btn','btn-primary','btn-sm','me-2','mb-2'); temp_coverArtAEl.setAttribute('href', `${apiDataConfig.response.config.decrypted.rawMediaUrlBase64}/media/${albumParsedObject.uuid}/${obj1.fileName}.${obj2.extension}`); temp_coverArtAEl.setAttribute('role', 'button'); temp_coverArtAEl.setAttribute('target', '_blank'); temp_coverArtAEl.setAttribute('rel', 'noopener noreferrer'); temp_coverArtAEl.innerHTML = `${obj2.name} ${obj1.height}px`; document.getElementById('trackInfoModal2-coverArtLinkDiv').appendChild(temp_coverArtAEl); }); }); let temp_codecListImported = new Array(); if (albumParsedObject.isAllTrackSameCodecs === false) {temp_codecListImported = trackParsedObject.codecs} else {temp_codecListImported = albumParsedObject.codecs} temp_codecListImported.forEach((obj) => { let temp_dlTrEl = document.createElement('tr'); let temp_dlTdCodecEl = document.createElement('td'); let temp_dlTdInfoEl = document.createElement('td'); let temp_dlTdBtnEl = document.createElement('td'); let temp_dlButtonGroupEl = document.createElement('div'); let temp_dlButtonEl = document.createElement('button'); let temp_dlButtonExtEl = document.createElement('a'); let temp_dlButtonIconEl = document.createElement('i'); let temp_dlButtonExtIconEl = document.createElement('i'); let temp_codecBitrateTemporal = null; temp_dlTdCodecEl.innerHTML = obj.nameBasic; temp_dlTdCodecEl.setAttribute('data-bs-toggle', 'tooltip'); temp_dlTdCodecEl.setAttribute('data-bs-title', obj.nameLong); if ((obj.bitRateAvg !== null && obj.bitRateMax !== null) || (obj.bitRateAvg !== null && obj.bitRateMax === null)) { temp_codecBitrateTemporal = obj.bitRateAvg; } else { temp_codecBitrateTemporal = obj.bitRateMax; } if (obj.bitDepth === null) { temp_dlTdInfoEl.innerHTML = `${obj.sampleRate / 1000}kHz ${obj.channelCount}ch ${temp_codecBitrateTemporal / 1000}kbps`; } else { temp_dlTdInfoEl.innerHTML = `${obj.bitDepth}bit ${obj.sampleRate / 1000}kHz ${obj.channelCount}ch ${temp_codecBitrateTemporal / 1000}kbps`; } if (obj.isOriginal === true) { temp_dlButtonEl.classList.add('btn', 'btn-primary'); temp_dlButtonExtEl.classList.add('btn', 'btn-primary', 'text-center'); } else { temp_dlButtonEl.classList.add('btn', 'btn-secondary'); temp_dlButtonExtEl.classList.add('btn', 'btn-secondary', 'text-center'); } temp_dlButtonEl.setAttribute('type', 'button'); // temp_dlButtonEl.addEventListener('click', async () => { // await downloadAudioDataToBlob (trackParsedObject.uuid, obj.uuid) // }) temp_dlButtonExtEl.setAttribute('href', `${apiDataConfig.response.config.decrypted.rawMediaUrlBase64}/media/${albumParsedObject.uuid}/${obj.path}/${trackParsedObject.uuid}.${obj.extension}`); temp_dlButtonExtEl.setAttribute('download', determineDownloadFileName(trackParsedObject.uuid, obj.uuid)); temp_dlButtonExtEl.setAttribute('role', 'button'); temp_dlButtonExtEl.setAttribute('target', '_blank'); temp_dlButtonExtEl.setAttribute('rel', 'noopener noreferrer'); temp_dlButtonGroupEl.setAttribute('role', 'group'); temp_dlButtonGroupEl.classList.add('btn-group'); temp_dlButtonIconEl.classList.add('bi', 'bi-download'); temp_dlButtonExtIconEl.classList.add('bi', 'bi-box-arrow-up-right'); temp_dlTdBtnEl.classList.add('text-end'); temp_dlButtonEl.appendChild(temp_dlButtonIconEl); temp_dlButtonExtEl.appendChild(temp_dlButtonExtIconEl); // temp_dlButtonGroupEl.appendChild(temp_dlButtonEl); temp_dlButtonGroupEl.appendChild(temp_dlButtonExtEl); temp_dlTdBtnEl.appendChild(temp_dlButtonGroupEl); temp_dlTrEl.appendChild(temp_dlTdCodecEl); temp_dlTrEl.appendChild(temp_dlTdInfoEl); temp_dlTrEl.appendChild(temp_dlTdBtnEl); document.getElementById('trackInfoModal2-downloadTable').appendChild(temp_dlTrEl); }); document.getElementById('trackInfoModal2-previewAudio').src = `${apiDataConfig.response.config.decrypted.rawMediaUrlBase64}/media/${albumParsedObject.uuid}/${temp_codecListImported.slice(-1)[0].path}/${trackParsedObject.uuid}.${temp_codecListImported.slice(-1)[0].extension}`; const bootstrapTooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]'); bootstrapTooltipList = [...bootstrapTooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl)); document.getElementById('trackInfoModal2-DebugAcdOutputEl').innerHTML = JSON.stringify(albumParsedObject, '', ' '); document.getElementById('trackInfoModal2-ModalCloseButton').addEventListener('click', () => {allAudioElementStop()}); document.getElementById('trackInfoModal2-ModalCloseIconButton').addEventListener('click', () => {allAudioElementStop()}); const trackInfoModal2 = new bootstrap.Modal(document.getElementById('trackInfoModal2')); trackInfoModal2.show(); } // ========== albumInfoModalの処理 ========== function loadAlbumInfoModal (albumUuid) { // Parse Album from DB const albumParsedObject = getParsedAlbumObjectFromAlbumUuid(albumUuid); // Metadata label build if (bootstrapTooltipList !== null) {bootstrapTooltipList.forEach(el => el.dispose())}; document.getElementById('albumInfoModal-metadataTable-albumTitle').innerHTML = albumParsedObject.title; if (albumParsedObject.titleLatin === null) { document.getElementById('albumInfoModal-metadataTable-albumTitle').removeAttribute('data-bs-toggle'); document.getElementById('albumInfoModal-metadataTable-albumTitle').removeAttribute('data-bs-title'); } else { document.getElementById('albumInfoModal-metadataTable-albumTitle').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('albumInfoModal-metadataTable-albumTitle').setAttribute('data-bs-title', albumParsedObject.titleLatin); } document.getElementById('albumInfoModal-metadataTable-albumArtist').innerHTML = albumParsedObject.artist.map((obj) => obj.name).join(', '); if (albumParsedObject.artist.some((obj) => obj.nameLatin !== null)) { document.getElementById('albumInfoModal-metadataTable-albumArtist').setAttribute('data-bs-toggle', 'tooltip'); document.getElementById('albumInfoModal-metadataTable-albumArtist').setAttribute('data-bs-title', albumParsedObject.artist.map((obj) => {if (obj.nameLatin !== null) {return obj.nameLatin} else {return obj.name}}).join(', ')); } else { document.getElementById('albumInfoModal-metadataTable-albumArtist').removeAttribute('data-bs-toggle'); document.getElementById('albumInfoModal-metadataTable-albumArtist').removeAttribute('data-bs-title'); } document.getElementById('albumInfoModal-metadataTable-albumReleaseDate').innerHTML = moment(albumParsedObject.releaseDate).format('YYYY/MM/DD'); document.getElementById('albumInfoModal-metadataTable-albumBarcode').innerHTML = albumParsedObject.barCode; document.getElementById('albumInfoModal-metadataTable-albumCopyright').innerHTML = albumParsedObject.copyright; // Table clear el while(document.getElementById('albumInfoModal-externalLinkTable').firstChild) { document.getElementById('albumInfoModal-externalLinkTable').removeChild(document.getElementById('albumInfoModal-externalLinkTable').firstChild); } while(document.getElementById('albumInfoModal-coverArtLinkDiv').firstChild) { document.getElementById('albumInfoModal-coverArtLinkDiv').removeChild(document.getElementById('albumInfoModal-coverArtLinkDiv').firstChild); } // External link table build if (albumParsedObject.link.itunes !== null || albumParsedObject.link.spotify !== null) { let temp_extLinkAlbumTrEl = document.createElement('tr'); let temp_extLinkAlbumTdKeyEl = document.createElement('td'); let temp_extLinkAlbumTdValueEl = document.createElement('td'); let temp_extLinkAlbumA1El = document.createElement('a'); let temp_extLinkAlbumA2El = document.createElement('a'); temp_extLinkAlbumTdKeyEl.innerHTML = 'Album Link'; if (albumParsedObject.link.itunes !== null) { temp_extLinkAlbumA1El.classList.add('btn','btn-outline-primary','btn-sm','me-2'); temp_extLinkAlbumA1El.setAttribute('href', `https://music.apple.com/album/${albumParsedObject.link.itunes}`); temp_extLinkAlbumA1El.setAttribute('role', 'button'); temp_extLinkAlbumA1El.setAttribute('target', '_blank'); temp_extLinkAlbumA1El.setAttribute('rel', 'noopener noreferrer'); temp_extLinkAlbumA1El.innerHTML = 'Apple Music'; temp_extLinkAlbumTdValueEl.appendChild(temp_extLinkAlbumA1El); } if (albumParsedObject.link.spotify !== null) { temp_extLinkAlbumA2El.classList.add('btn','btn-outline-primary','btn-sm','me-2'); temp_extLinkAlbumA2El.setAttribute('href', `https://open.spotify.com/album/${albumParsedObject.link.spotify}`); temp_extLinkAlbumA2El.setAttribute('role', 'button'); temp_extLinkAlbumA2El.setAttribute('target', '_blank'); temp_extLinkAlbumA2El.setAttribute('rel', 'noopener noreferrer'); temp_extLinkAlbumA2El.innerHTML = 'Spotify'; temp_extLinkAlbumTdValueEl.appendChild(temp_extLinkAlbumA2El); } temp_extLinkAlbumTrEl.appendChild(temp_extLinkAlbumTdKeyEl); temp_extLinkAlbumTrEl.appendChild(temp_extLinkAlbumTdValueEl); document.getElementById('albumInfoModal-externalLinkTable').appendChild(temp_extLinkAlbumTrEl); } // Cover art button build albumParsedObject.coverArts.forEach((obj1) => { obj1.format.forEach((obj2) => { let temp_coverArtAEl = document.createElement('a'); temp_coverArtAEl.classList.add('btn','btn-primary','btn-sm','me-2','mb-2'); temp_coverArtAEl.setAttribute('href', `${apiDataConfig.response.config.decrypted.rawMediaUrlBase64}/media/${albumParsedObject.uuid}/${obj1.fileName}.${obj2.extension}`); temp_coverArtAEl.setAttribute('role', 'button'); temp_coverArtAEl.setAttribute('target', '_blank'); temp_coverArtAEl.setAttribute('rel', 'noopener noreferrer'); temp_coverArtAEl.innerHTML = `${obj2.name} ${obj1.height}px`; document.getElementById('albumInfoModal-coverArtLinkDiv').appendChild(temp_coverArtAEl); }); }); // Tooltip initialize const bootstrapTooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]'); bootstrapTooltipList = [...bootstrapTooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl)); // Modal Initialize const albumInfoModal = new bootstrap.Modal(document.getElementById('albumInfoModal')); // Track List build const albumTrackAllListGroup = document.querySelector('#albumInfoModal-trackAllListGroup'); while(albumTrackAllListGroup.firstChild) { albumTrackAllListGroup.removeChild(albumTrackAllListGroup.firstChild); } let headerElObj = new Object(); headerElObj.buttonNodeEl = document.createElement('button'); headerElObj.divArtistNodeEl = document.createElement('div'); headerElObj.divTrackNodeEl = document.createElement('div'); headerElObj.buttonNodeEl.classList.add('list-group-item', 'list-group-item-action', 'd-flex'); headerElObj.buttonNodeEl.setAttribute('type', 'button'); headerElObj.buttonNodeEl.disabled = true; headerElObj.divArtistNodeEl.classList.add('flex-fill', 'w-100'); headerElObj.divTrackNodeEl.classList.add('flex-fill', 'w-100'); headerElObj.divArtistNodeEl.innerHTML = 'Artist'; headerElObj.divTrackNodeEl.innerHTML = 'Track'; headerElObj.buttonNodeEl.appendChild(headerElObj.divArtistNodeEl); headerElObj.buttonNodeEl.appendChild(headerElObj.divTrackNodeEl); albumTrackAllListGroup.appendChild(headerElObj.buttonNodeEl); albumParsedObject.tracks.forEach((trackParsedObject) => { let buttonNodeEl = document.createElement('button'); let divArtistNodeEl = document.createElement('div'); let divTrackNodeEl = document.createElement('div'); buttonNodeEl.classList.add('list-group-item', 'list-group-item-action', 'd-flex'); buttonNodeEl.setAttribute('type', 'button'); buttonNodeEl.setAttribute('data-track-uuid', trackParsedObject.uuid); divArtistNodeEl.classList.add('flex-fill', 'w-100'); divTrackNodeEl.classList.add('flex-fill', 'w-100'); divArtistNodeEl.innerHTML = trackParsedObject.artist.map((obj) => obj.name).join(', '); divTrackNodeEl.innerHTML = trackParsedObject.title; buttonNodeEl.appendChild(divArtistNodeEl); buttonNodeEl.appendChild(divTrackNodeEl); buttonNodeEl.addEventListener('click', () => { albumInfoModal.hide(); loadTrackInfoModal2(trackParsedObject.uuid) }); albumTrackAllListGroup.appendChild(buttonNodeEl); }); // Show modal albumInfoModal.show(); } // ========== 設定画面のイベントリスナー登録など ========== document.querySelector('#settingsApplyButton').addEventListener('click', () => {appSettingsApply()}); document.querySelector('#settingsUiSwitchUiModeDiv').addEventListener('click', function () { appSettingsSaveData.ui.uiThemeMode = document.querySelector('#settingsUiSwitchUiMode').elements['settingsUiSwitchUiMode'].value; console.log('settingsUiSwitchUiMode div clicked!'); }); // ========== 設定を変更後に保存、反映させる(ボタン押したときの動作) ========== function appSettingsApply () { writeAppSettingsToLocalStorage(); switch (appSettingsSaveData.ui.uiThemeMode) { case 'light': document.querySelector('html').setAttribute('data-bs-theme', 'light'); document.querySelector('html').setAttribute('data-mdb-theme', 'light'); break; case 'dark': document.querySelector('html').setAttribute('data-bs-theme', 'dark'); document.querySelector('html').setAttribute('data-mdb-theme', 'dark'); } } // ========== appSettingsを元に設定画面の選択状態を更新 ========== function appSettingsCheckedUiUpdate () { const settingsUiSwitchUiModeElements = document.querySelector('#settingsUiSwitchUiMode').elements; for (let i = 0; i < settingsUiSwitchUiModeElements.length; i++) { if (settingsUiSwitchUiModeElements[i].value === appSettingsSaveData.ui.uiThemeMode) { settingsUiSwitchUiModeElements[i].checked = true; } else { settingsUiSwitchUiModeElements[i].checked = false; } } } // ========== API関連の関数など ========== async function apiConnect (axiosObj) { let connectionTimerStart = performance.now(); try { const response = await axios(axiosObj); let connectionTimerEnd = performance.now(); return { 'apiConnectionTime': connectionTimerEnd - connectionTimerStart, 'response': response.data }; } catch (error) { let connectionTimerEnd = performance.now(); console.error(`API request failed: ${error.code}`); alert(`API request failed: ${error.code}`); throw error; } } async function loadRequiredDatabase () { document.querySelectorAll('.fetchingDataNowLabel').forEach((el) => { el.classList.remove('d-none'); }); apiDataMasterDB = await apiConnect({ 'method': 'get', 'url': `./db/master.json`, 'headers': apiConnectDefaultHeader, 'timeout': internalConfig.network.timeout }); apiDataConfig = await apiConnect({ 'method': 'get', 'url': `./config.json`, 'headers': apiConnectDefaultHeader, 'timeout': internalConfig.network.timeout }); if (apiDataMasterDB) { document.querySelector('#databaseTestInfoCodeEl').innerHTML = `OK (Time: ${Math.ceil(apiDataMasterDB.apiConnectionTime)} ms)`; document.querySelector('#databaseTestOutputCodeEl').innerHTML = JSON.stringify(apiDataMasterDB.response, '', ' '); } else { document.querySelector('#databaseTestInfoCodeEl').innerHTML = `Failed`; } document.querySelectorAll('.fetchingDataNowLabel').forEach((el) => { el.classList.add('d-none'); }); } // ========== データベース内部検索などの処理 ========== function getAlbumUuidFromTrackUuid (trackUuid) { let albumUuid = null; apiDataMasterDB.response.data.albums.forEach((albumObject) => { if (albumObject.tracks.some((trackObject) => trackObject.uuid === trackUuid)) { albumUuid = albumObject.uuid; } }); return albumUuid; } function getDbObjectFromUuid (uuid, type) { switch (type) { case 'album': if (apiDataMasterDB.response.data.albums.some((albumObject) => albumObject.uuid === uuid)) { return apiDataMasterDB.response.data.albums.filter((albumObject) => albumObject.uuid === uuid)[0]; } else { return null; } case 'track': apiDataMasterDB.response.data.albums.forEach((albumObject) => { if (albumObject.tracks.some((trackObject) => trackObject.uuid === uuid)) { return albumObject.tracks.filter((trackObject) => trackObject.uuid === uuid)[0]; } }); return null; case 'artist': if (apiDataMasterDB.response.data.artists.some((artistObject) => artistObject.uuid === uuid)) { return apiDataMasterDB.response.data.artists.filter((artistObject) => artistObject.uuid === uuid)[0]; } else { return null; } case 'codec': if (apiDataMasterDB.response.data.codecs.some((codecObject) => codecObject.uuid === uuid)) { return apiDataMasterDB.response.data.codecs.filter((codecObject) => codecObject.uuid === uuid)[0]; } else { return null; } default: throw new Error ('unexpected type'); } } function getParsedAlbumObjectFromAlbumUuid (uuid) { const rawAlbumObject = getDbObjectFromUuid(uuid, 'album'); let outputObject = JSON.parse(JSON.stringify(rawAlbumObject)); outputObject.artist = new Array(); rawAlbumObject.artist.forEach((artistUuidStr) => { outputObject.artist.push(getDbObjectFromUuid(artistUuidStr, 'artist')); }); if (rawAlbumObject.isAllTrackSameCodecs === true) { outputObject.codecs = new Array(); rawAlbumObject.codecs.forEach((codecObj) => { let temp_searchedCodecObj = new Object(); temp_searchedCodecObj = getDbObjectFromUuid(codecObj.uuid, 'codec'); temp_searchedCodecObj.isOriginal = codecObj.isOriginal; temp_searchedCodecObj.path = codecObj.path; outputObject.codecs.push(temp_searchedCodecObj); }); } if (rawAlbumObject.isCoverArtsUseDefault === true) { outputObject.coverArts = apiDataMasterDB.response.data.coverArtDefaults; } outputObject.tracks = new Array(); rawAlbumObject.tracks.forEach((rawTrackObj) => { let temp_outputTrackObj = new Object(); temp_outputTrackObj = JSON.parse(JSON.stringify(rawTrackObj)); temp_outputTrackObj.artist = new Array(); rawTrackObj.artist.forEach((artistUuidStr) => { temp_outputTrackObj.artist.push(getDbObjectFromUuid(artistUuidStr, 'artist')); }); if (rawTrackObj.lyricist !== null) { temp_outputTrackObj.lyricist = new Array(); rawTrackObj.lyricist.forEach((artistUuidStr) => { temp_outputTrackObj.lyricist.push(getDbObjectFromUuid(artistUuidStr, 'artist')); }); } if (rawTrackObj.composer !== null) { temp_outputTrackObj.composer = new Array(); rawTrackObj.composer.forEach((artistUuidStr) => { temp_outputTrackObj.composer.push(getDbObjectFromUuid(artistUuidStr, 'artist')); }); } if (rawTrackObj.arranger !== null) { temp_outputTrackObj.arranger = new Array(); rawTrackObj.arranger.forEach((artistUuidStr) => { temp_outputTrackObj.arranger.push(getDbObjectFromUuid(artistUuidStr, 'artist')); }); } if (rawAlbumObject.isAllTrackSameCodecs === false || rawTrackObj.codecs !== null) { temp_outputTrackObj.codecs = new Array(); rawTrackObj.codecs.forEach((codecObj) => { let temp_searchedCodecObj2 = new Object(); temp_searchedCodecObj2 = getDbObjectFromUuid(codecObj.uuid, 'codec'); temp_searchedCodecObj2.isOriginal = codecObj.isOriginal; temp_searchedCodecObj2.path = codecObj.path; temp_outputTrackObj.codecs.push(temp_searchedCodecObj2); }); temp_outputTrackObj.durationMsecs = (rawTrackObj.durationSamples / temp_outputTrackObj.codecs.filter((t) => t.isOriginal === true)[0].sampleRate) * 1000; } else { temp_outputTrackObj.durationMsecs = (rawTrackObj.durationSamples / outputObject.codecs.filter((t) => t.isOriginal === true)[0].sampleRate) * 1000; } outputObject.tracks.push(temp_outputTrackObj); }); let temp_albumTotalDurationSamples = 0; let temp_albumTotalDurationMsecs = 0; for (let i = 0; i < rawAlbumObject.tracks.length; i++) { temp_albumTotalDurationSamples += outputObject.tracks[i].durationSamples; temp_albumTotalDurationMsecs += outputObject.tracks[i].durationMsecs; } outputObject.durationSamples = temp_albumTotalDurationSamples; outputObject.durationMsecs = temp_albumTotalDurationMsecs; return outputObject; } // ========== ファイルをDLしてBlob化、ブラウザに開かせる ========== async function downloadAudioDataToBlob (trackUuid, codecUuid) { const albumParsedObject = getParsedAlbumObjectFromAlbumUuid(getAlbumUuidFromTrackUuid(trackUuid)); const trackParsedObject = albumParsedObject.tracks.find((obj) => obj.uuid === trackUuid); let codecParsedObject = null; if (albumParsedObject.isAllTrackSameCodecs === false) { codecParsedObject = trackParsedObject.codecs.find((obj) => obj.uuid === codecUuid); } else { codecParsedObject = albumParsedObject.codecs.find((obj) => obj.uuid === codecUuid); } const axiosRes = await apiConnect ({ 'method': 'get', 'url': `${apiDataConfig.response.config.decrypted.rawMediaUrlBase64}/media/${albumParsedObject.uuid}/${codecParsedObject.path}/${trackParsedObject.uuid}.${codecParsedObject.extension}`, 'headers': apiConnectDefaultHeader, 'timeout': internalConfig.network.timeout, 'responseType': 'blob' }); console.log(`File downloaded to Blob\nDownload time: ${axiosRes.apiConnectionTime} ms`); const blobUrl = window.URL.createObjectURL(response.data); const link = document.createElement('a'); let saveFileName = null; if (trackParsedObject.titleFileName !== null) { saveFileName = `${trackParsedObject.disc}_${('00' + trackParsedObject.index).slice(-2)}_${trackParsedObject.titleFileName}.${codecParsedObject.extension}`; } else { saveFileName = `${trackParsedObject.disc}_${('00' + trackParsedObject.index).slice(-2)}_${trackParsedObject.title}.${codecParsedObject.extension}`; } link.href = blobUrl; link.setAttribute('download', saveFileName); link.classList.add('d-none'); document.body.appendChild(link); link.click(); document.body.removeChild(link); } function determineDownloadFileName (trackUuid, codecUuid) { const albumParsedObject = getParsedAlbumObjectFromAlbumUuid(getAlbumUuidFromTrackUuid(trackUuid)); const trackParsedObject = albumParsedObject.tracks.find((obj) => obj.uuid === trackUuid); let codecParsedObject = null; if (albumParsedObject.isAllTrackSameCodecs === false) { codecParsedObject = trackParsedObject.codecs.find((obj) => obj.uuid === codecUuid); } else { codecParsedObject = albumParsedObject.codecs.find((obj) => obj.uuid === codecUuid); } let saveFileName = null; if (trackParsedObject.titleFileName !== null) { saveFileName = `${trackParsedObject.disc}_${('00' + trackParsedObject.index).slice(-2)}_${trackParsedObject.titleFileName}.${codecParsedObject.extension}`; } else { saveFileName = `${trackParsedObject.disc}_${('00' + trackParsedObject.index).slice(-2)}_${trackParsedObject.title}.${codecParsedObject.extension}`; } return saveFileName; } // ========== MasterDB/Configの暗号化を解く ========== async function decryptConfig () { apiDataConfig.response.config.decrypted = new Object(); console.log(`Decrypting config data using AES 128-bit CBC ...`) const encryptKey = await CryptoJS.enc.Hex.parse(CryptoJS.enc.Base64.parse(apiDataConfig.response.config.encryption.key.split('').reverse().join('')).toString(CryptoJS.enc.Utf8)); const encryptIv = await CryptoJS.enc.Hex.parse(CryptoJS.enc.Base64.parse(apiDataConfig.response.config.encryption.iv.split('').reverse().join('')).toString(CryptoJS.enc.Utf8)); Object.keys(apiDataConfig.response.config.encrypted).forEach(async function (keyName) { apiDataConfig.response.config.decrypted[keyName] = await CryptoJS.AES.decrypt({ 'ciphertext': CryptoJS.enc.Base64.parse(apiDataConfig.response.config.encrypted[keyName]) }, encryptKey, { 'iv': encryptIv, 'mode': CryptoJS.mode.CBC, 'padding': CryptoJS.pad.Pkcs7 }).toString(CryptoJS.enc.Utf8); }); console.log(`All config data has been decrypted`); } // ========== ブラウザのLocalStorageにあるAppSettingsを読み書きする ========== function loadAppSettingsFromLocalStorage () { if (localStorage.hasOwnProperty(appSettingsStorageName)) { appSettingsSaveData = JSON.parse(CryptoJS.enc.Base64.parse(localStorage.getItem(appSettingsStorageName)).toString(CryptoJS.enc.Utf8)); console.warn(`LocalStorage key detected`); console.log(`Loaded appSettings:\n${JSON.stringify(appSettingsSaveData)}`); } else { appSettingsSaveData = appSettingsSaveDataDefault; console.warn(`LocalStorage key not found\nUsing default settings`); writeAppSettingsToLocalStorage(); } } function checkAppSettingsExistsOnStorage () { if (localStorage.hasOwnProperty(appSettingsStorageName)) { return true } else { return false } } function writeAppSettingsToLocalStorage () { // CryptoJS.enc.Utf8.parseを使うことでCryptoJS内部形式を強制 localStorage.setItem(appSettingsStorageName, CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(JSON.stringify(appSettingsSaveData)))); console.log(`Wrote appSettings:\n${JSON.stringify(appSettingsSaveData)}`); } // ========== 全てのAudio要素をStop ========== function allAudioElementStop () { let audioElements = document.getElementsByTagName('audio'); for (let i = 0; i < audioElements.length; i++) { audioElements[i].pause(); } } // ========== その他使い回す汎用関数など ========== function msecToReadableTime (msec) { let msecCeiled = Math.ceil(msec); let sec = msec / 1000; let min = ('00' + Math.floor(sec / 60)).slice(-2); let secPart = ('00' + Math.floor(sec % 60)).slice(-2); return `${min}:${secPart}.${('000' + msecCeiled % 1000).slice(-3)}`; }