diff --git a/index.php b/index.php new file mode 100644 index 0000000..96c7050 --- /dev/null +++ b/index.php @@ -0,0 +1,36 @@ + + + + + + + Internetradio Presets + + + +

Internetradio Presets

+
+ Aktueller Sender: + + + +
+
+
+
+ + + +
+ + + + diff --git a/script.js b/script.js new file mode 100644 index 0000000..5e5d36b --- /dev/null +++ b/script.js @@ -0,0 +1,215 @@ +const presets = [ + { name: "Radio SRF 1 AG/SO", url: "https://stream.srg-ssr.ch/regi_ag_so/aacp_96.m3u" }, + { name: "Radio SRF 2 Kultur", url: "https://stream.srg-ssr.ch/drs2/aacp_96.m3u" }, + { name: "Radio SRF 3", url: "https://stream.srg-ssr.ch/drs3/aacp_96.m3u" }, + { name: "Radio SRF 4 News", url: "https://stream.srg-ssr.ch/drs4news/aacp_96.m3u" }, + { name: "Radio SRF Virus", url: "https://stream.srg-ssr.ch/drsvirus/aacp_96.m3u" }, + { name: "Radio SRF Musikwelle", url: "https://stream.srg-ssr.ch/drsmw/aacp_96.m3u" }, + { name: "Radio Swiss Pop", url: "https://stream.srg-ssr.ch/rsp/aacp_96.m3u" }, + { name: "Radio Swiss Jazz", url: "https://stream.srg-ssr.ch/rsj/aacp_96.m3u" }, + { name: "Radio Swiss Classic", url: "https://stream.srg-ssr.ch/rsc_de/aacp_96.m3u" }, +]; + +document.addEventListener('DOMContentLoaded', function() { + const presetContainer = document.getElementById('preset-container'); + const addNewPresetButton = document.getElementById('add-new-preset'); + const newPresetNameInput = document.getElementById('new-preset-name'); + const newPresetUrlInput = document.getElementById('new-preset-url'); + let currentPlayingItem = null; // Variable zum Speichern des aktuell spielenden Elements + + const exportButton = document.createElement('button'); + exportButton.textContent = 'Presets exportieren'; + exportButton.addEventListener('click', exportPresets); + document.body.appendChild(exportButton); + + const importButton = document.createElement('button'); + importButton.textContent = 'Presets importieren'; + importButton.addEventListener('click', importPresets); + document.body.appendChild(importButton); + + presets.forEach(preset => { + addNewPreset(preset.name, preset.url); + }); + + loadExistingPresets(); + + new Sortable(presetContainer, { + animation: 150, + ghostClass: 'ghost', + onEnd: () => { + savePresetOrder(); + } + }); + + addNewPresetButton.addEventListener('click', () => { + const presetName = newPresetNameInput.value.trim(); + const presetUrl = newPresetUrlInput.value.trim(); + + if (presetName && presetUrl) { + addNewPreset(presetName, presetUrl); + savePresetToLocalStorage(presetName, presetUrl); + newPresetNameInput.value = ''; + newPresetUrlInput.value = ''; + } else { + alert("Bitte geben Sie einen Namen und eine URL ein."); + } + }); + + function loadExistingPresets() { + const presets = JSON.parse(localStorage.getItem('presets')) || []; + presets.forEach(preset => { + addNewPreset(preset.name, preset.url); + }); + } + + function addNewPreset(name, url) { + const presetItem = document.createElement('div'); + presetItem.classList.add('preset-item'); + presetItem.dataset.streamUrl = url; + + presetItem.innerHTML = ` +

${name}

+
+ + +
+ `; + + presetItem.querySelector('.edit-button').addEventListener('click', (event) => { + event.stopPropagation(); + editPreset(presetItem, name, url); + }); + + presetItem.querySelector('.delete-button').addEventListener('click', (event) => { + event.stopPropagation(); + deletePreset(presetItem); + }); + + presetItem.addEventListener('click', (event) => { + if (event.target !== presetItem.querySelector('.edit-button') && event.target !== presetItem.querySelector('.delete-button')) { + playStream(url, presetItem); // Übergabe des presetItem + } + }); + + presetContainer.appendChild(presetItem); + } + + function editPreset(item, currentName, currentUrl) { + const newName = prompt("Neuer Name:", currentName); + const newUrl = prompt("Neue URL:", currentUrl); + + if (newName !== null && newUrl !== null) { + item.querySelector('h3').textContent = newName; + item.dataset.streamUrl = newUrl; + savePresetOrder(); + } + } + + function deletePreset(item) { + if (confirm("Möchten Sie diesen Sender wirklich löschen?")) { + presetContainer.removeChild(item); + savePresetOrder(); + } + } + + function savePresetToLocalStorage(name, url) { + const presets = JSON.parse(localStorage.getItem('presets')) || []; + presets.push({ name, url }); + localStorage.setItem('presets', JSON.stringify(presets)); + } + + function savePresetOrder() { + const presetItems = Array.from(presetContainer.children); + const presets = presetItems.map(item => ({ + name: item.querySelector('h3').textContent, + url: item.dataset.streamUrl + })); + localStorage.setItem('presets', JSON.stringify(presets)); + } + + function playStream(url, item) { + // Stoppe den aktuell laufenden Stream (falls vorhanden) + if (currentPlayingItem) { + const currentAudio = currentPlayingItem.querySelector('audio'); + if (currentAudio) { + currentAudio.pause(); + currentAudio.remove(); + } + currentPlayingItem.classList.remove('playing'); + } + + const audioElement = new Audio(url); + audioElement.autoplay = true; + audioElement.loop = true; + audioElement.volume = 0.5; + audioElement.onerror = function() { + alert('Fehler beim Laden des Streams: ' + url); + }; + item.appendChild(audioElement); // Füge das Audio-Element zum Preset-Item hinzu + item.classList.add('playing'); + + currentPlayingItem = item; // Aktualisiere das aktuell spielende Element + currentStationName.textContent = item.querySelector('h3').textContent; + } + + function exportPresets() { + const presets = JSON.parse(localStorage.getItem('presets')) || []; + const json = JSON.stringify(presets, null, 2); + + const blob = new Blob([json], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + + const a = document.createElement('a'); + a.href = url; + a.download = 'webradio_presets.json'; + a.click(); + + URL.revokeObjectURL(url); + } + + function importPresets() { + const input = document.createElement('input'); + input.type = 'file'; + input.accept = '.json'; + input.onchange = (event) => { + const file = event.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = (e) => { + try { + const importedPresets = JSON.parse(e.target.result); + if (Array.isArray(importedPresets)) { + localStorage.setItem('presets', JSON.stringify(importedPresets)); + presetContainer.innerHTML = ''; + importedPresets.forEach(preset => addNewPreset(preset.name, preset.url)); + alert("Presets erfolgreich importiert."); + } else { + alert("Ungültiges Dateiformat. Bitte eine JSON-Datei importieren."); + } + } catch (error) { + alert("Fehler beim Importieren der Presets: " + error); + } + }; + reader.readAsText(file); + } + }; + input.click(); + } + + const stopButton = document.querySelector('.stop-button'); + const progressBar = document.getElementById('progress-bar'); + const currentStationName = document.getElementById('current-station-name'); + + stopButton.addEventListener('click', () => { + // Stoppe den aktuellen Stream und setze currentPlayingItem zurück + if (currentPlayingItem) { + const audioElement = currentPlayingItem.querySelector('audio'); + audioElement.pause(); + audioElement.currentTime = 0; + currentPlayingItem.classList.remove('playing'); + currentPlayingItem = null; + currentStationName.textContent = 'Kein Sender ausgewählt.'; + } + }); + +}); \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000..0f3d424 --- /dev/null +++ b/style.css @@ -0,0 +1,75 @@ +body { + font-family: Arial, sans-serif; + text-align: center; + margin: 0; + padding: 20px; +} + +.preset-container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + grid-gap: 20px; + margin-top: 30px; + margin-bottom: 30px; +} + +.preset-item { + background-color: #f1f1f1; + padding: 15px; + border-radius: 5px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + cursor: pointer; + transition: background-color 0.3s ease; + display: flex; + align-items: center; + justify-content: space-between; +} + +.preset-item:hover { + background-color: #e0e0e0; +} + +.preset-item h3 { + margin: 0; + flex-grow: 1; +} + +.preset-item button { + margin-left: 5px; + cursor: pointer; +} + +.new-preset-container { + margin-bottom: 15px; +} + +.current-station { + font-weight: bold; + font-size: 16px; + margin-left: 20px; +} + +#aktueller-sender { + background-color: #FFFF00; + border-radius: 5px; + padding: 10px 20px; +} + +.stop-button { + background-color: #ff9999; + color: #fff; /* Weißer Text auf rotem Hintergrund */ + font-weight: bold; + border: none; + border-radius: 5px; + padding: 10px 20px; + text-align: center; + display: inline-block; + font-size: 16px; + margin: 4px 2px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.stop-button:hover { + background-color: #ff4d4d; /* Dunklerer Farbton beim Hovern */ +} \ No newline at end of file