Start meines kleinen Projekts

Der Player läuft. Presets lassen sich erstellen, verschieben, bearbeiten und löschen. Ebenfalls gibt es bereits eine Funktion für Export und Import. Einige Sender sind bereits angelegt.
This commit is contained in:
simonpipe 2024-12-19 18:50:27 +00:00
parent b0a195f3cd
commit e9615937db
3 changed files with 326 additions and 0 deletions

36
index.php Normal file
View file

@ -0,0 +1,36 @@
<?php
$senderIstAusgewaehlt = false;
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Internetradio Presets</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Internetradio Presets</h1>
<div class="current-station">
<span id="aktueller-sender">Aktueller Sender: <span id="current-station-name">
<?php
if ($senderIstAusgewaehlt) {
echo "Aktueller Sender: " . $senderName;
} else {
echo "Kein Sender ausgewählt";
}
?>
</span> </span>
<button class="stop-button">Stop</button>
</div>
<div class="preset-container" id="preset-container">
</div>
<div class="new-preset-container">
<input type="text" id="new-preset-name" placeholder="Sendername">
<input type="text" id="new-preset-url" placeholder="Stream-URL">
<button id="add-new-preset">Neuen Sender hinzufügen</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js"></script>
<script src="script.js"></script>
</body>
</html>

215
script.js Normal file
View file

@ -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 = `
<h3>${name}</h3>
<div class="button-container">
<button class="edit-button">Bearbeiten</button>
<button class="delete-button">Löschen</button>
</div>
`;
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.';
}
});
});

75
style.css Normal file
View file

@ -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 */
}