<title>Gelişmiş Tam Ekran MP3 Oynatıcı</title>
<style>
/* Genel Stiller */
:root {
--bg-dark: #1a1a2e;
--player-dark: #2a2a4a;
--primary-color: #0077b6;
--accent-color: #28a745;
--text-color: #fff;
--inactive-color: #555;
--bar-color: #b3cde0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
background-color: var(--bg-dark);
color: var(--text-color);
transition: background-color 0.5s;
}
/* Tam Ekran Modu */
.fullscreen-active body {
overflow: hidden; /* Tam ekranda kaydırmayı engelle */
}
.player-container {
background-color: var(--player-dark);
padding: 25px;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.7);
width: 380px;
max-width: 90%;
text-align: center;
transition: all 0.5s ease;
}
/* Tam ekran stilini uygula */
.player-container.is-fullscreen {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
max-width: none;
border-radius: 0;
padding: 50px;
z-index: 9999;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
/* Dosya Seçim Alanı */
.file-selection-area {
display: flex;
gap: 10px;
justify-content: center;
margin-bottom: 20px;
flex-wrap: wrap;
}
#fileInputSingle, #fileInputMultiple, #directoryInput {
display: none;
}
.file-label {
display: inline-flex;
align-items: center;
background-color: var(--primary-color);
color: var(--text-color);
padding: 10px 15px;
border-radius: 8px;
cursor: pointer;
font-weight: bold;
font-size: 14px;
transition: background-color 0.3s;
}
.file-label i {
margin-right: 8px;
}
.file-label:hover {
background-color: #0096c7;
}
/* Şarkı Bilgileri */
#current-track-name {
font-size: 1.5em;
margin: 10px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.time-info {
display: flex;
justify-content: space-between;
font-size: 0.8em;
color: var(--bar-color);
margin-bottom: 5px;
}
.progress-bar-container {
height: 8px;
background-color: #555577;
border-radius: 4px;
margin-bottom: 20px;
cursor: pointer;
}
.progress-bar {
height: 100%;
width: 0%;
background-color: var(--accent-color);
border-radius: 4px;
transition: width 0.1s linear;
}
/* Kontrol Butonları ve Oynatma Modları */
.main-controls {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
margin-bottom: 20px;
}
.mode-controls {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: 15px;
}
.control-btn, .mode-btn {
background: none;
border: none;
color: var(--text-color);
cursor: pointer;
font-size: 1.2em;
padding: 10px;
transition: color 0.2s, transform 0.1s;
}
.control-btn:hover, .mode-btn:hover {
color: var(--primary-color);
}
.control-btn:disabled, .mode-btn:disabled {
color: var(--inactive-color);
cursor: not-allowed;
}
.main-control-btn {
font-size: 2.5em;
}
/* Aktif Mod Butonları */
.mode-btn.active {
color: var(--accent-color);
}
/* Görselleştirici (Işıklar) */
.visualizer-container {
width: 100%;
display: flex;
justify-content: space-between;
align-items: flex-end;
height: 80px;
border-radius: 5px;
overflow: hidden;
background-color: #111;
padding: 0 5px;
}
.bar {
width: 6px;
background-color: #ff0000;
height: 2px;
transition: all 0.05s ease-out;
display: inline-block;
}
</style>
<div class="player-container" id="player-container">
<div class="file-selection-area">
<input type="file" id="fileInputSingle" accept="audio/*">
<label for="fileInputSingle" class="file-label"><i class="fas fa-file-audio"></i> Tek Şarkı Ekle</label>
<input type="file" id="fileInputMultiple" accept="audio/*" multiple>
<label for="fileInputMultiple" class="file-label"><i class="fas fa-list-ul"></i> Tümünü Seç & Ekle</label>
<input type="file" id="directoryInput" webkitdirectory directory multiple accept="audio/*">
<label for="directoryInput" class="file-label"><i class="fas fa-folder-open"></i> Tüm Klasörü Oku</label>
</div>
<div class="track-info">
<h3 id="current-track-name">Lütfen Şarkı Seçiniz</h3>
<p id="playlist-status">Oynatma listesi boş.</p>
</div>
<div class="time-info">
<span id="currentTime">0:00</span>
<span id="duration">0:00</span>
</div>
<div class="progress-bar-container" id="progress-container">
<div class="progress-bar" id="progress-bar"></div>
</div>
<div class="mode-controls">
<button id="shuffle-btn" class="mode-btn" title="Karıştır">
<i class="fas fa-random"></i>
</button>
<button id="repeat-btn" class="mode-btn" data-mode="none" title="Tekrarlama Modu (Kapalı)">
<i class="fas fa-redo"></i>
</button>
<button id="fullscreen-btn" class="mode-btn" title="Tam Ekran">
<i class="fas fa-expand"></i>
</button>
</div>
<div class="main-controls">
<button id="prev-btn" class="control-btn" disabled title="Geri"><i class="fas fa-backward"></i></button>
<button id="play-pause-btn" class="control-btn main-control-btn" disabled title="Oynat"><i class="fas fa-play"></i></button>
<button id="next-btn" class="control-btn" disabled title="İleri"><i class="fas fa-forward"></i></button>
</div>
<div class="visualizer-container" id="visualizer-container">
</div>
</div>
<script>
// HTML Elementleri
const playerContainer = document.getElementById('player-container');
const fileInputSingle = document.getElementById('fileInputSingle');
const fileInputMultiple = document.getElementById('fileInputMultiple');
const directoryInput = document.getElementById('directoryInput'); // Yeni klasör seçme butonu
const playPauseBtn = document.getElementById('play-pause-btn');
const prevBtn = document.getElementById('prev-btn');
const nextBtn = document.getElementById('next-btn');
const shuffleBtn = document.getElementById('shuffle-btn');
const repeatBtn = document.getElementById('repeat-btn');
const fullscreenBtn = document.getElementById('fullscreen-btn');
const currentTrackName = document.getElementById('current-track-name');
const playlistStatus = document.getElementById('playlist-status');
const progressBar = document.getElementById('progress-bar');
const progressContainer = document.getElementById('progress-container');
const currentTimeEl = document.getElementById('currentTime');
const durationEl = document.getElementById('duration');
const visualizerContainer = document.getElementById('visualizer-container');
// Oynatıcı Durumu
let playlist = []; // Ana oynatma listesi
let playOrder = []; // Karıştırma için kullanılan sıra
let currentTrackIndex = 0; // playOrder'daki mevcut indis
let isPlaying = false;
let shuffleMode = false;
let repeatMode = 'none'; // 'none', 'one', 'all'
// Ses ve Web Audio API
const audio = new Audio();
let audioContext = null;
let analyser;
const barCount = 40;
const bars = [];
const frequencyData = new Uint8Array(barCount);
// Görselleştirici Çubuklarını Oluştur
for (let i = 0; i < barCount; i++) {
const bar = document.createElement('div');
bar.classList.add('bar');
visualizerContainer.appendChild(bar);
bars.push(bar);
}
// ---------- Olay Dinleyicileri ----------
fileInputSingle.addEventListener('change', (event) => addFilesToPlaylist(event.target.files, false));
fileInputMultiple.addEventListener('change', (event) => addFilesToPlaylist(event.target.files, true));
directoryInput.addEventListener('change', (event) => addFilesToPlaylist(event.target.files, true));
playPauseBtn.addEventListener('click', () => isPlaying ? pauseTrack() : playTrack());
nextBtn.addEventListener('click', nextTrack);
prevBtn.addEventListener('click', prevTrack);
shuffleBtn.addEventListener('click', toggleShuffle);
repeatBtn.addEventListener('click', toggleRepeat);
fullscreenBtn.addEventListener('click', toggleFullscreen);
audio.addEventListener('loadedmetadata', updateDuration);
audio.addEventListener('ended', handleTrackEnded);
audio.addEventListener('timeupdate', updateProgress);
progressContainer.addEventListener('click', setProgress);
// ---------- Oynatma Modu Kontrolleri ----------
function toggleShuffle() {
shuffleMode = !shuffleMode;
shuffleBtn.classList.toggle('active', shuffleMode);
shuffleBtn.title = shuffleMode ? "Karıştır (Açık)" : "Karıştır (Kapalı)";
// Oynatma listesini yeniden oluştur
updatePlayOrder();
// Yeni sırada mevcut şarkının konumunu bul
const currentTrackFile = playlist[playOrder[currentTrackIndex]];
const newIndex = playOrder.findIndex(index => playlist[index] === currentTrackFile);
if (newIndex !== -1) {
currentTrackIndex = newIndex;
}
updateStatus();
}
function toggleRepeat() {
const modes = ['none', 'one', 'all'];
let nextIndex = (modes.indexOf(repeatMode) + 1) % modes.length;
repeatMode = modes[nextIndex];
repeatBtn.dataset.mode = repeatMode;
repeatBtn.classList.toggle('active', repeatMode !== 'none');
const icon = repeatBtn.querySelector('i');
icon.className = 'fas';
switch (repeatMode) {
case 'none':
icon.classList.add('fa-redo');
repeatBtn.title = "Tekrarlama Modu (Kapalı)";
break;
case 'one':
icon.classList.add('fa-redo-alt', 'fa-border'); // Tekrar simgesine özel stil
repeatBtn.title = "Tekrarlama Modu (Tek Şarkı)";
break;
case 'all':
icon.classList.add('fa-redo');
repeatBtn.title = "Tekrarlama Modu (Tüm Liste)";
break;
}
updateStatus();
}
function toggleFullscreen() {
if (document.fullscreenElement) {
document.exitFullscreen();
playerContainer.classList.remove('is-fullscreen');
} else {
playerContainer.requestFullscreen().catch(err => {
alert(`Tam ekran moduna geçilemedi: ${err.message}`);
});
playerContainer.classList.add('is-fullscreen');
}
}
// ---------- Şarkı Yönetimi Fonksiyonları ----------
function addFilesToPlaylist(fileList, shouldReplace) {
const newFiles = Array.from(fileList).filter(file => file.type.startsWith('audio/'));
if (newFiles.length === 0) return;
if (shouldReplace) {
playlist = newFiles;
currentTrackIndex = 0;
} else {
playlist.push(...newFiles);
}
updatePlayOrder();
if (playlist.length > 0) {
if (!isPlaying && audio.src === "") {
loadTrack(currentTrackIndex);
}
playPauseBtn.disabled = false;
}
// Inputları temizle
fileInputSingle.value = null;
fileInputMultiple.value = null;
directoryInput.value = null;
updateStatus();
}
function updatePlayOrder() {
playOrder = Array.from({ length: playlist.length }, (_, i) => i);
if (shuffleMode) {
shuffleArray(playOrder);
}
}
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
function loadTrack(playListIndex) {
const track = playlist[playOrder[playListIndex]];
currentTrackName.textContent = track ? track.name : "Şarkı Yüklenemedi";
audio.src = track ? URL.createObjectURL(track) : "";
updateControls();
}
function playTrack() {
if (playlist.length === 0) return;
if (!audioContext) {
initAudioVisualizer();
}
if (audioContext.state === 'suspended') {
audioContext.resume();
}
audio.play().then(() => {
isPlaying = true;
playPauseBtn.innerHTML = '<i class="fas fa-pause"></i>';
requestAnimationFrame(drawVisualizer);
}).catch(error => {
console.error("Oynatma hatası:", error);
isPlaying = false;
playPauseBtn.innerHTML = '<i class="fas fa-play"></i>';
});
}
function pauseTrack() {
audio.pause();
isPlaying = false;
playPauseBtn.innerHTML = '<i class="fas fa-play"></i>';
}
function nextTrack() {
if (playlist.length <= 1) return;
currentTrackIndex = (currentTrackIndex + 1) % playlist.length;
loadTrack(currentTrackIndex);
playTrack();
}
function prevTrack() {
if (playlist.length <= 1) return;
currentTrackIndex = (currentTrackIndex - 1 + playlist.length) % playlist.length;
loadTrack(currentTrackIndex);
playTrack();
}
function handleTrackEnded() {
if (repeatMode === 'one') {
loadTrack(currentTrackIndex);
playTrack();
} else if (repeatMode === 'all') {
nextTrack();
} else { // repeatMode === 'none'
if (currentTrackIndex < playlist.length - 1) {
nextTrack();
} else {
pauseTrack();
currentTrackIndex = 0;
updatePlayOrder(); // Bitince karıştırma sırasını yenile
loadTrack(currentTrackIndex);
updateControls();
}
}
}
// ---------- Süre ve İlerleme Fonksiyonları ----------
function formatTime(seconds) {
if (!isFinite(seconds) || seconds < 0) return "0:00";
const minutes = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${minutes}:${secs < 10 ? '0' : ''}${secs}`;
}
function updateDuration() {
durationEl.textContent = formatTime(audio.duration);
}
function updateProgress() {
if (!isFinite(audio.duration)) return;
const progressPercent = (audio.currentTime / audio.duration) * 100;
progressBar.style.width = `${progressPercent}%`;
currentTimeEl.textContent = formatTime(audio.currentTime);
}
function setProgress(e) {
const width = progressContainer.clientWidth;
const clickX = e.offsetX;
const duration = audio.duration;
if (isFinite(duration) && duration > 0) {
audio.currentTime = (clickX / width) * duration;
}
}
function updateStatus() {
playlistStatus.textContent = `Toplam ${playlist.length} şarkı. Şu an: ${currentTrackIndex + 1} / ${playlist.length}`;
updateControls();
}
function updateControls() {
const disable = playlist.length === 0;
prevBtn.disabled = disable || playlist.length <= 1;
nextBtn.disabled = disable || playlist.length <= 1;
playPauseBtn.disabled = disable;
}
// ---------- Görselleştirici Fonksiyonları ----------
function initAudioVisualizer() {
audioContext = new (window.AudioContext || window.webkitAudioContext)();
const source = audioContext.createMediaElementSource(audio);
analyser = audioContext.createAnalyser();
analyser.fftSize = 64;
analyser.smoothingTimeConstant = 0.8;
source.connect(analyser);
analyser.connect(audioContext.destination);
}
function drawVisualizer() {
if (!isPlaying || !analyser) return;
analyser.getByteFrequencyData(frequencyData);
for (let i = 0; i < barCount; i++) {
let value = frequencyData[i];
const percent = value / 255;
const height = percent * 75 + 2;
const bar = bars[i];
bar.style.height = `${height}px`;
// Ritim ve konuma göre renk değiştirme
const hue = i * (360 / barCount) + percent * 100;
bar.style.backgroundColor = `hsl(${hue}, 100%, ${50 + percent * 30}%)`;
}
requestAnimationFrame(drawVisualizer);
}
// Başlangıçta kontrolleri güncelle
updateControls();
</script>