323 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			323 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html>
 | |
| <html>
 | |
| <head>
 | |
| 	<meta charset="utf-8">
 | |
| 	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 | |
| 	<title>ESMP3</title>
 | |
| 	<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8=" crossorigin="anonymous"></script>
 | |
| 	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
 | |
| 	<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
 | |
| 	<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
 | |
| 	<script src="https://kit.fontawesome.com/272149490a.js" crossorigin="anonymous"></script>
 | |
| </head>
 | |
| 
 | |
| <body>
 | |
| 	<div class="container bg-dark text-light">
 | |
| 		<div class="row">
 | |
| 			<div class="col-sm-1">
 | |
| 				<h1 id="play_state_icon"><i class="fa fa-stop"></i></h1>
 | |
| 			</div>
 | |
| 			<div class="col-sm-11">
 | |
| 				<h2><i class="fa fa-compact-disc"></i> <span id="album"></span></h2>
 | |
| 				<h2><i class="fa fa-scroll"></i> <span id="track"></span></h2>
 | |
| 			</div>
 | |
| 		</div>
 | |
| 	</div>
 | |
| 	<div class="container">
 | |
| 		<div class="row">
 | |
| 			<div class="col">
 | |
| 				<input type="range" class="custom-range" id="position_slider" disabled>
 | |
| 			</div>
 | |
| 		</div>
 | |
| 		<div class="row">
 | |
| 			<div class="col-sm-6">
 | |
| 			</div>
 | |
| 			<div class="col-sm-1">
 | |
| 				<h3><i class="fa fa-volume-down"></i></h3>
 | |
| 			</div>
 | |
| 			<div class="col-sm-4">
 | |
| 				<input type="range" class="custom-range" id="volume_slider">
 | |
| 			</div>
 | |
| 			<div class="col-sm-1">
 | |
| 				<h3><i class="fa fa-volume-up"></i></h3>
 | |
| 			</div>
 | |
| 		</div>
 | |
| 		<div class="row">
 | |
| 			<div class="col">
 | |
| 				<button type="button" class="btn btn-primary btn-lg btn-block" id="button_track_prev"><i class="fa fa-step-backward"></i></button>
 | |
| 			</div>
 | |
| 			<div class="col">
 | |
| 				<button type="button" class="btn btn-primary btn-lg btn-block" id="button_stop"><i class="fa fa-stop"></i></button>
 | |
| 			</div>
 | |
| 			<div class="col">
 | |
| 				<button type="button" class="btn btn-primary btn-lg btn-block" id="button_play"><i class="fa fa-play"></i></button>
 | |
| 			</div>
 | |
| 			<div class="col">
 | |
| 				<button type="button" class="btn btn-primary btn-lg btn-block" id="button_track_next"><i class="fa fa-step-forward"></i></button>
 | |
| 			</div>
 | |
| 			<div class="col">
 | |
| 				<button type="button" class="btn btn-primary btn-lg btn-block" id="button_lock"><i class="fa fa-lock-open"></i></button>
 | |
| 			</div>
 | |
| 			<div class="col">
 | |
| 				<button type="button" class="btn btn-primary btn-lg btn-block" id="button_open"><i class="fa fa-eject"></i></button>
 | |
| 			</div>
 | |
| 			<div class="col">
 | |
| 				<button type="button" class="btn btn-primary btn-lg btn-block" id="button_settings"><i class="fa fa-cog"></i></button>
 | |
| 			</div>
 | |
| 		</div>
 | |
| 	</div>
 | |
| 	
 | |
| 	<div class="container">
 | |
| 		<table class="table table-hover table-sm" id="track_list_table">
 | |
| 			<thead class="thead-light">
 | |
| 				<tr>
 | |
| 					<th>Nr.</th>
 | |
| 					<th>Status</th>
 | |
| 					<th>Track</th>
 | |
| 				</tr>
 | |
| 			</thead>
 | |
| 			<tbody class="" id="track_list">
 | |
| 			
 | |
| 			</tbody>
 | |
| 		</table>
 | |
| 	</div>
 | |
| 	
 | |
| 	
 | |
| 	
 | |
| 	<div class="modal fade" id="openModal" tabindex="-1" role="dialog">
 | |
| 		<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" role="document">
 | |
| 			<div class="modal-content">
 | |
| 				<div class="modal-header">
 | |
| 					<h5 class="modal-title">Album öffnen</h5>
 | |
| 					<button type="button" class="close" data-dismiss="modal">
 | |
| 						<span>×</span>
 | |
| 					</button>
 | |
| 				</div>
 | |
| 
 | |
| 				<h6>Open URL</h6>
 | |
| 				<div class="input-group">
 | |
| 					<div class="input-group-prepend">
 | |
| 						<span class="input-group-text">
 | |
| 							<i class="fa fa-link"></i>
 | |
| 						</span>
 | |
| 					</div>
 | |
| 					<input type="text" class="form-control" id="input_url" />
 | |
| 					<div class="input-group-append">
 | |
| 						<button class="btn btn-primary" id="button_url_open">Go</button>
 | |
| 						<button class="btn btn-danger" id="button_url_add_mapping" style="display: none;"><i class="fa fa-arrows-alt-h"></i></button>
 | |
| 					</div>
 | |
| 				</div>
 | |
| 				
 | |
| 				<div class="modal-body">
 | |
| 					<div id="albums_without_id_area">
 | |
| 						<h6>Albums without RFID card</h6>
 | |
| 						<table class="table table-hover table-sm">
 | |
| 							<tbody id="albums_without_id">
 | |
| 							</tbody>
 | |
| 						</table>
 | |
| 					</div>
 | |
| 					
 | |
| 					<h6>Albums with RFID</h6>
 | |
| 					<table class="table table-hover table-sm">
 | |
| 						<tbody id="albums_with_id">
 | |
| 						</tbody>
 | |
| 					</table>
 | |
| 				</div>
 | |
| 				
 | |
| 				<div class="modal-footer">
 | |
| 					<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
 | |
| 				</div>
 | |
| 			</div>
 | |
| 		</div>
 | |
| 	</div>
 | |
| 
 | |
| 	<div class="modal fade" id="settingsModal" tabindex="-1" role="dialog">
 | |
| 			<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" role="document">
 | |
| 				<div class="modal-content">
 | |
| 					<div class="modal-header">
 | |
| 						<h5 class="modal-title">Settings</h5>
 | |
| 						<button type="button" class="close" data-dismiss="modal">
 | |
| 							<span>×</span>
 | |
| 						</button>
 | |
| 					</div>
 | |
| 					
 | |
| 					<div class="modal-body">
 | |
| 						<h6>Last RFID id:</h6>
 | |
| 						<span id="last_rfid_id"></span> <button class="btn btn-warning" id="button_add_mapping"><i class="fa fa-arrows-alt-h"></i></button>
 | |
| 						
 | |
| 						<h6>Last RFID data:</h6>
 | |
| 						<span id="last_rfid_data"></span>
 | |
| 
 | |
| 						<h6>Actions</h6>
 | |
| 						<button type="button" class="btn btn-danger btn-lg btn-block" id="button_reset_vs1053">Reset VS1053 chip</button>
 | |
| 						<button type="button" class="btn btn-danger btn-lg btn-block" id="button_reboot">Reboot ESMP3</button>
 | |
| 					</div>
 | |
| 					
 | |
| 					<div class="modal-footer">
 | |
| 						<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
 | |
| 					</div>
 | |
| 				</div>
 | |
| 			</div>
 | |
| 		</div>
 | |
| </body>
 | |
| 
 | |
| <script>
 | |
| update_player = function(data) {
 | |
| 	$('#play_state_icon i').removeClass('fa-stop', 'fa-play').addClass(data.playing ? 'fa-play' : 'fa-stop');
 | |
| 	
 | |
| 	if (data.playing) {
 | |
| 		$('#button_play').removeClass('btn-primary').addClass('btn-secondary', 'btn-disabled');
 | |
| 		$('#button_stop').removeClass('btn-secondary', 'btn-disabled').addClass('btn-primary');
 | |
| 	} else if (data.playlist) {
 | |
| 		$('#button_play').removeClass('btn-secondary', 'btn-disabled').addClass('btn-primary');
 | |
| 		$('#button_stop').removeClass('btn-primary').addClass('btn-secondary', 'btn-disabled');
 | |
| 	} else {
 | |
| 		$('#button_play').removeClass('btn-primary').addClass('btn-secondary', 'btn-disabled');
 | |
| 		$('#button_stop').removeClass('btn-primary').addClass('btn-secondary', 'btn-disabled');
 | |
| 	}
 | |
| 	
 | |
| 	$('#volume_slider').attr('min', data.volume.min).attr('max', data.volume.max).val(data.volume.current);
 | |
| 	
 | |
| 	if (data.playlist) update_playlist(data.playlist);
 | |
| }
 | |
| 
 | |
| update_playlist = function(data) {
 | |
| 	$('#track_list tr').remove();
 | |
| 	for (var i=0; i<data.files.length; i++) {
 | |
| 		tr = $('<tr>').data('track', i);
 | |
| 		tr.append($('<td>').html(i + 1));
 | |
| 		tr.append($('<td>').html(data.current_track==i ? '<i class="fa fa-play"></i>' : ''));
 | |
| 		tr.append($('<td>').html(data.files[i].substr(data.files[i].title)));
 | |
| 		$('#track_list').append(tr);
 | |
| 	}
 | |
| 	
 | |
| 	if (data.has_track_next) {
 | |
| 		$('#button_track_next').removeClass('btn-secondary', 'btn-disabled').addClass('btn-primary');
 | |
| 	} else {
 | |
| 		$('#button_track_next').removeClass('btn-primary').addClass('btn-secondary', 'btn-disabled');
 | |
| 	}
 | |
| 	
 | |
| 	if (data.has_track_prev) {
 | |
| 		$('#button_track_prev').removeClass('btn-secondary', 'btn-disabled').addClass('btn-primary');
 | |
| 	} else {
 | |
| 		$('#button_track_prev').removeClass('btn-primary').addClass('btn-secondary', 'btn-disabled');
 | |
| 	}
 | |
| 	
 | |
| 	$('#album').html(data.title);
 | |
| 	var file = data.files[data.current_track];
 | |
| 	if (file) {
 | |
| 		$('#track').html(file.title); 
 | |
| 	}
 | |
| }
 | |
| 
 | |
| update_controller = function(data) {
 | |
| 	if (data.lock_state == "locked") {
 | |
| 		$('#button_lock').removeClass('btn-primary', 'btn-warning').addClass('btn-danger');
 | |
| 		$('#button_lock i').removeClass('fa-lock-open').addClass('fa-lock');
 | |
| 	} else if (data.lock_state == "locking") {
 | |
| 		$('#button_lock').removeClass('btn-primary', 'btn-danger').addClass('btn-warning');
 | |
| 		$('#button_lock i').removeClass('fa-lock-open').addClass('fa-lock');
 | |
| 	} else {
 | |
| 		$('#button_lock').removeClass('btn-danger', 'btn-warning').addClass('btn-primary');
 | |
| 		$('#button_lock i').removeClass('fa-lock').addClass('fa-lock-open');
 | |
| 	}
 | |
| 
 | |
| 	$('#button_add_mapping').toggle(data.last_rfid.uid.length>0);
 | |
| 	$('#last_rfid_id').html(data.last_rfid.uid);
 | |
| 	$('#last_rfid_data').html(data.last_rfid.data);
 | |
| }
 | |
| 
 | |
| update_playlist_manager = function(data) {
 | |
| 	if (data.unmapped.length > 0) {
 | |
| 		$('#albums_without_id_area').show();
 | |
| 		$('#albums_without_id tr').remove();
 | |
| 		data.unmapped = data.unmapped.sort();
 | |
| 		for (var i=0; i<data.unmapped.length; i++) {
 | |
| 			var tr = $('<tr>').attr('data-folder', data.unmapped[i]);
 | |
| 			tr.append($('<td>').html(data.unmapped[i].substr(1)));
 | |
| 			tr.append($('<td>').append($('<button>').addClass('button btn-warning add_mapping_button').hide().append($('<i>').addClass('fa fa-arrows-alt-h'))));
 | |
| 			$('#albums_without_id').append(tr);
 | |
| 		}
 | |
| 	} else {
 | |
| 		$('#albums_without_id_area').hide();
 | |
| 	}
 | |
| 	
 | |
| 	var folders = Object.keys(data.folders).sort();
 | |
| 	for (var i in folders) {
 | |
| 		var folder = folders[i];
 | |
| 		var tr = $('<tr>').attr('data-folder', folder);
 | |
| 		tr.append($('<td>').html(folder.substr(1)));
 | |
| 		tr.append($('<td>').append($('<button>').addClass('button btn-danger add_mapping_button').hide().append($('<i>').addClass('fa fa-arrows-alt-h'))));
 | |
| 		$('#albums_with_id').append(tr);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| update_position = function(data) {
 | |
| 	$('#position_slider').attr('max', data.file_size).val(data.position);
 | |
| }
 | |
| 
 | |
| process_ws_message = function(event) {
 | |
| 	var data = event.data.split("\n");;
 | |
| 	for (var i=0; i<data.length; i++) {
 | |
| 		var json = JSON.parse(data[i]);
 | |
| 		console.log(json);
 | |
| 		if (json === null) continue;
 | |
| 		switch(json["_type"]) {
 | |
| 			case "position": update_position(json); break;
 | |
| 			case "player": update_player(json); break;
 | |
| 			case "playlist_manager": update_playlist_manager(json); break;
 | |
| 			case "controller": update_controller(json); break;
 | |
| 		}	
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var play_on_click = true;
 | |
| 
 | |
| $(function() {
 | |
| 	ws = new WebSocket("ws://" + location.host + "/ws");
 | |
| 	ws.onmessage = process_ws_message;
 | |
| 	
 | |
| 	$('#volume_slider').change(function(e) { ws.send("volume=" + e.target.value); });
 | |
| 	$('#button_play').click(function(e) { ws.send("play"); });
 | |
| 	$('#button_stop').click(function(e) { ws.send("stop"); });
 | |
| 	$('#button_track_next').click(function(e) { ws.send("track_next"); });
 | |
| 	$('#button_track_prev').click(function(e) { ws.send("track_prev"); });
 | |
| 	$('#button_open').click(function(e) { $('#openModal').modal('show'); });
 | |
| 	$('#track_list').on('click', 'tr', function(e) { ws.send("track=" + $(e.target).parent().data('track')); });
 | |
| 	$('#albums_without_id, #albums_with_id').on('click', 'tr', function(e) { if (play_on_click) {ws.send("play " + $(e.target).parents('tr').data('folder')); $('#openModal').modal('hide');} });
 | |
| 	$('#button_settings').click(function(e) { $('#settingsModal').modal('show'); });
 | |
| 	$('#button_reset_vs1053').click(function(e) { ws.send("reset_vs1053"); $('#settingsModal').modal('hide'); });
 | |
| 	$('#button_reboot').click(function(e) { ws.send("reboot"); $('#settingsModal').modal('hide'); });
 | |
| 	$('#button_url_open').click(function(e) { ws.send("play " + $('#input_url').val()); $('#openModal').modal('hide');});
 | |
| 	$('#button_add_mapping').click(function(e) {
 | |
| 		$('#settingsModal').modal('hide');
 | |
| 		$('#openModal').modal('show');
 | |
| 		$('.add_mapping_button').show();
 | |
| 		$('#button_url_open').hide();
 | |
| 		$('#button_url_add_mapping').show();
 | |
| 		play_on_click = false;
 | |
| 	});
 | |
| 	$('#openModal').on('click', '.add_mapping_button', function(e) {
 | |
| 		ws.send("add_mapping=" + $('#last_rfid_id').html() + "=" + $(e.target).parents('tr').data('folder'));
 | |
| 		$('#openModal').modal('hide');
 | |
| 		$('.add_mapping_button').hide();
 | |
| 		$('#button_url_open').hide();
 | |
| 		$('#button_url_add_mapping').show();
 | |
| 		e.stopPropagation();
 | |
| 		play_on_click=true;
 | |
| 		return false;
 | |
| 	});
 | |
| 	$('#button_url_add_mapping').click(function(e) {
 | |
| 		ws.send("add_mapping=" + $('#last_rfid_id').html() + "=" + $('#input_url').val());
 | |
| 		$('#openModal').modal('hide');
 | |
| 		$('.add_mapping_button').hide();
 | |
| 		$('#button_url_open').hide();
 | |
| 		$('#button_url_add_mapping').show();
 | |
| 		e.stopPropagation();
 | |
| 		play_on_click=true;
 | |
| 		return false;
 | |
| 	});
 | |
| });
 | |
| </script>
 | |
| </html>
 |