Multimedix commited on
Commit
2fd63b8
·
verified ·
1 Parent(s): ae5d08a

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +908 -19
index.html CHANGED
@@ -1,19 +1,908 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="de">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Deutsche Radio Stream - Live Radio aus Deutschland</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ :root {
16
+ --primary-color: #1e3a8a;
17
+ --secondary-color: #3b82f6;
18
+ --accent-color: #f59e0b;
19
+ --dark-bg: #0f172a;
20
+ --light-bg: #1e293b;
21
+ --text-primary: #f1f5f9;
22
+ --text-secondary: #94a3b8;
23
+ --glass-bg: rgba(30, 41, 59, 0.5);
24
+ --glass-border: rgba(148, 163, 184, 0.2);
25
+ }
26
+
27
+ body {
28
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
29
+ background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
30
+ min-height: 100vh;
31
+ color: var(--text-primary);
32
+ overflow-x: hidden;
33
+ }
34
+
35
+ /* Animated Background */
36
+ .bg-animation {
37
+ position: fixed;
38
+ width: 100%;
39
+ height: 100%;
40
+ top: 0;
41
+ left: 0;
42
+ z-index: -1;
43
+ background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #334155 100%);
44
+ overflow: hidden;
45
+ }
46
+
47
+ .bg-animation::before {
48
+ content: '';
49
+ position: absolute;
50
+ width: 200%;
51
+ height: 200%;
52
+ top: -50%;
53
+ left: -50%;
54
+ background: radial-gradient(circle, rgba(59, 130, 246, 0.1) 0%, transparent 70%);
55
+ animation: rotate 30s linear infinite;
56
+ }
57
+
58
+ @keyframes rotate {
59
+ 0% { transform: rotate(0deg); }
60
+ 100% { transform: rotate(360deg); }
61
+ }
62
+
63
+ /* Header */
64
+ header {
65
+ background: var(--glass-bg);
66
+ backdrop-filter: blur(10px);
67
+ border-bottom: 1px solid var(--glass-border);
68
+ padding: 1.5rem 2rem;
69
+ position: sticky;
70
+ top: 0;
71
+ z-index: 100;
72
+ }
73
+
74
+ .header-content {
75
+ max-width: 1400px;
76
+ margin: 0 auto;
77
+ display: flex;
78
+ justify-content: space-between;
79
+ align-items: center;
80
+ flex-wrap: wrap;
81
+ gap: 1rem;
82
+ }
83
+
84
+ .logo {
85
+ display: flex;
86
+ align-items: center;
87
+ gap: 1rem;
88
+ font-size: 1.5rem;
89
+ font-weight: bold;
90
+ color: var(--text-primary);
91
+ }
92
+
93
+ .logo i {
94
+ font-size: 2rem;
95
+ background: linear-gradient(135deg, var(--secondary-color), var(--accent-color));
96
+ -webkit-background-clip: text;
97
+ -webkit-text-fill-color: transparent;
98
+ animation: pulse 2s ease-in-out infinite;
99
+ }
100
+
101
+ @keyframes pulse {
102
+ 0%, 100% { transform: scale(1); }
103
+ 50% { transform: scale(1.1); }
104
+ }
105
+
106
+ .attribution {
107
+ font-size: 0.875rem;
108
+ color: var(--text-secondary);
109
+ }
110
+
111
+ .attribution a {
112
+ color: var(--secondary-color);
113
+ text-decoration: none;
114
+ transition: color 0.3s;
115
+ }
116
+
117
+ .attribution a:hover {
118
+ color: var(--accent-color);
119
+ }
120
+
121
+ /* Main Container */
122
+ .container {
123
+ max-width: 1400px;
124
+ margin: 2rem auto;
125
+ padding: 0 2rem;
126
+ display: grid;
127
+ grid-template-columns: 1fr 350px;
128
+ gap: 2rem;
129
+ }
130
+
131
+ /* Player Section */
132
+ .player-section {
133
+ background: var(--glass-bg);
134
+ backdrop-filter: blur(10px);
135
+ border: 1px solid var(--glass-border);
136
+ border-radius: 20px;
137
+ padding: 2rem;
138
+ }
139
+
140
+ .now-playing {
141
+ text-align: center;
142
+ margin-bottom: 2rem;
143
+ }
144
+
145
+ .station-logo {
146
+ width: 120px;
147
+ height: 120px;
148
+ margin: 0 auto 1.5rem;
149
+ background: linear-gradient(135deg, var(--secondary-color), var(--accent-color));
150
+ border-radius: 20px;
151
+ display: flex;
152
+ align-items: center;
153
+ justify-content: center;
154
+ font-size: 3rem;
155
+ color: white;
156
+ box-shadow: 0 10px 30px rgba(59, 130, 246, 0.3);
157
+ animation: float 3s ease-in-out infinite;
158
+ }
159
+
160
+ @keyframes float {
161
+ 0%, 100% { transform: translateY(0); }
162
+ 50% { transform: translateY(-10px); }
163
+ }
164
+
165
+ .station-name {
166
+ font-size: 2rem;
167
+ font-weight: bold;
168
+ margin-bottom: 0.5rem;
169
+ background: linear-gradient(135deg, var(--text-primary), var(--secondary-color));
170
+ -webkit-background-clip: text;
171
+ -webkit-text-fill-color: transparent;
172
+ }
173
+
174
+ .current-track {
175
+ color: var(--text-secondary);
176
+ font-size: 1.1rem;
177
+ margin-bottom: 1rem;
178
+ min-height: 30px;
179
+ }
180
+
181
+ .visualizer {
182
+ height: 60px;
183
+ display: flex;
184
+ align-items: center;
185
+ justify-content: center;
186
+ gap: 3px;
187
+ margin-bottom: 2rem;
188
+ }
189
+
190
+ .bar {
191
+ width: 4px;
192
+ background: linear-gradient(to top, var(--secondary-color), var(--accent-color));
193
+ border-radius: 2px;
194
+ animation: wave 1s ease-in-out infinite;
195
+ }
196
+
197
+ .bar:nth-child(1) { animation-delay: 0s; height: 20px; }
198
+ .bar:nth-child(2) { animation-delay: 0.1s; height: 30px; }
199
+ .bar:nth-child(3) { animation-delay: 0.2s; height: 25px; }
200
+ .bar:nth-child(4) { animation-delay: 0.3s; height: 35px; }
201
+ .bar:nth-child(5) { animation-delay: 0.4s; height: 20px; }
202
+ .bar:nth-child(6) { animation-delay: 0.5s; height: 30px; }
203
+ .bar:nth-child(7) { animation-delay: 0.6s; height: 25px; }
204
+ .bar:nth-child(8) { animation-delay: 0.7s; height: 35px; }
205
+
206
+ .visualizer.paused .bar {
207
+ animation-play-state: paused;
208
+ opacity: 0.5;
209
+ }
210
+
211
+ @keyframes wave {
212
+ 0%, 100% { transform: scaleY(1); }
213
+ 50% { transform: scaleY(1.5); }
214
+ }
215
+
216
+ /* Player Controls */
217
+ .player-controls {
218
+ display: flex;
219
+ justify-content: center;
220
+ align-items: center;
221
+ gap: 1.5rem;
222
+ margin-bottom: 2rem;
223
+ }
224
+
225
+ .control-btn {
226
+ background: var(--glass-bg);
227
+ border: 1px solid var(--glass-border);
228
+ color: var(--text-primary);
229
+ width: 50px;
230
+ height: 50px;
231
+ border-radius: 50%;
232
+ display: flex;
233
+ align-items: center;
234
+ justify-content: center;
235
+ cursor: pointer;
236
+ transition: all 0.3s;
237
+ font-size: 1.2rem;
238
+ }
239
+
240
+ .control-btn:hover {
241
+ background: var(--secondary-color);
242
+ transform: scale(1.1);
243
+ box-shadow: 0 5px 20px rgba(59, 130, 246, 0.4);
244
+ }
245
+
246
+ .play-btn {
247
+ width: 70px;
248
+ height: 70px;
249
+ font-size: 1.5rem;
250
+ background: linear-gradient(135deg, var(--secondary-color), var(--accent-color));
251
+ border: none;
252
+ }
253
+
254
+ .play-btn:hover {
255
+ box-shadow: 0 10px 30px rgba(59, 130, 246, 0.5);
256
+ }
257
+
258
+ /* Volume Control */
259
+ .volume-control {
260
+ display: flex;
261
+ align-items: center;
262
+ gap: 1rem;
263
+ background: var(--glass-bg);
264
+ padding: 1rem;
265
+ border-radius: 15px;
266
+ border: 1px solid var(--glass-border);
267
+ }
268
+
269
+ .volume-slider {
270
+ flex: 1;
271
+ -webkit-appearance: none;
272
+ appearance: none;
273
+ height: 6px;
274
+ background: var(--light-bg);
275
+ border-radius: 3px;
276
+ outline: none;
277
+ }
278
+
279
+ .volume-slider::-webkit-slider-thumb {
280
+ -webkit-appearance: none;
281
+ appearance: none;
282
+ width: 18px;
283
+ height: 18px;
284
+ background: var(--secondary-color);
285
+ border-radius: 50%;
286
+ cursor: pointer;
287
+ transition: all 0.3s;
288
+ }
289
+
290
+ .volume-slider::-webkit-slider-thumb:hover {
291
+ background: var(--accent-color);
292
+ transform: scale(1.2);
293
+ }
294
+
295
+ /* Stations List */
296
+ .stations-section {
297
+ background: var(--glass-bg);
298
+ backdrop-filter: blur(10px);
299
+ border: 1px solid var(--glass-border);
300
+ border-radius: 20px;
301
+ padding: 1.5rem;
302
+ max-height: 600px;
303
+ overflow-y: auto;
304
+ }
305
+
306
+ .stations-section::-webkit-scrollbar {
307
+ width: 8px;
308
+ }
309
+
310
+ .stations-section::-webkit-scrollbar-track {
311
+ background: var(--light-bg);
312
+ border-radius: 4px;
313
+ }
314
+
315
+ .stations-section::-webkit-scrollbar-thumb {
316
+ background: var(--secondary-color);
317
+ border-radius: 4px;
318
+ }
319
+
320
+ .section-title {
321
+ font-size: 1.5rem;
322
+ margin-bottom: 1.5rem;
323
+ display: flex;
324
+ align-items: center;
325
+ gap: 0.5rem;
326
+ }
327
+
328
+ .station-item {
329
+ display: flex;
330
+ align-items: center;
331
+ gap: 1rem;
332
+ padding: 1rem;
333
+ background: var(--glass-bg);
334
+ border: 1px solid var(--glass-border);
335
+ border-radius: 12px;
336
+ margin-bottom: 0.75rem;
337
+ cursor: pointer;
338
+ transition: all 0.3s;
339
+ }
340
+
341
+ .station-item:hover {
342
+ background: rgba(59, 130, 246, 0.1);
343
+ border-color: var(--secondary-color);
344
+ transform: translateX(5px);
345
+ }
346
+
347
+ .station-item.active {
348
+ background: linear-gradient(135deg, rgba(59, 130, 246, 0.2), rgba(245, 158, 11, 0.2));
349
+ border-color: var(--accent-color);
350
+ }
351
+
352
+ .station-icon {
353
+ width: 50px;
354
+ height: 50px;
355
+ background: linear-gradient(135deg, var(--secondary-color), var(--accent-color));
356
+ border-radius: 10px;
357
+ display: flex;
358
+ align-items: center;
359
+ justify-content: center;
360
+ color: white;
361
+ font-size: 1.2rem;
362
+ }
363
+
364
+ .station-info {
365
+ flex: 1;
366
+ }
367
+
368
+ .station-title {
369
+ font-weight: 600;
370
+ margin-bottom: 0.25rem;
371
+ }
372
+
373
+ .station-genre {
374
+ font-size: 0.875rem;
375
+ color: var(--text-secondary);
376
+ }
377
+
378
+ .station-live {
379
+ width: 8px;
380
+ height: 8px;
381
+ background: #ef4444;
382
+ border-radius: 50%;
383
+ animation: blink 2s infinite;
384
+ }
385
+
386
+ @keyframes blink {
387
+ 0%, 100% { opacity: 1; }
388
+ 50% { opacity: 0.5; }
389
+ }
390
+
391
+ /* Categories */
392
+ .categories {
393
+ display: flex;
394
+ gap: 0.5rem;
395
+ margin-bottom: 1.5rem;
396
+ flex-wrap: wrap;
397
+ }
398
+
399
+ .category-btn {
400
+ padding: 0.5rem 1rem;
401
+ background: var(--glass-bg);
402
+ border: 1px solid var(--glass-border);
403
+ border-radius: 20px;
404
+ color: var(--text-secondary);
405
+ cursor: pointer;
406
+ transition: all 0.3s;
407
+ font-size: 0.875rem;
408
+ }
409
+
410
+ .category-btn:hover {
411
+ background: var(--secondary-color);
412
+ color: white;
413
+ transform: translateY(-2px);
414
+ }
415
+
416
+ .category-btn.active {
417
+ background: var(--secondary-color);
418
+ color: white;
419
+ }
420
+
421
+ /* Responsive Design */
422
+ @media (max-width: 1024px) {
423
+ .container {
424
+ grid-template-columns: 1fr;
425
+ }
426
+
427
+ .stations-section {
428
+ max-height: 400px;
429
+ }
430
+ }
431
+
432
+ @media (max-width: 640px) {
433
+ header {
434
+ padding: 1rem;
435
+ }
436
+
437
+ .header-content {
438
+ flex-direction: column;
439
+ text-align: center;
440
+ }
441
+
442
+ .container {
443
+ padding: 0 1rem;
444
+ margin: 1rem auto;
445
+ }
446
+
447
+ .player-section, .stations-section {
448
+ padding: 1.5rem;
449
+ }
450
+
451
+ .station-name {
452
+ font-size: 1.5rem;
453
+ }
454
+
455
+ .play-btn {
456
+ width: 60px;
457
+ height: 60px;
458
+ font-size: 1.2rem;
459
+ }
460
+
461
+ .control-btn {
462
+ width: 40px;
463
+ height: 40px;
464
+ font-size: 1rem;
465
+ }
466
+ }
467
+
468
+ /* Loading Animation */
469
+ .loading {
470
+ display: inline-block;
471
+ width: 20px;
472
+ height: 20px;
473
+ border: 3px solid var(--glass-border);
474
+ border-radius: 50%;
475
+ border-top-color: var(--secondary-color);
476
+ animation: spin 1s ease-in-out infinite;
477
+ }
478
+
479
+ @keyframes spin {
480
+ to { transform: rotate(360deg); }
481
+ }
482
+
483
+ /* Toast Notification */
484
+ .toast {
485
+ position: fixed;
486
+ bottom: 2rem;
487
+ left: 50%;
488
+ transform: translateX(-50%) translateY(100px);
489
+ background: var(--light-bg);
490
+ border: 1px solid var(--glass-border);
491
+ border-radius: 10px;
492
+ padding: 1rem 2rem;
493
+ display: flex;
494
+ align-items: center;
495
+ gap: 1rem;
496
+ opacity: 0;
497
+ transition: all 0.3s;
498
+ z-index: 1000;
499
+ }
500
+
501
+ .toast.show {
502
+ transform: translateX(-50%) translateY(0);
503
+ opacity: 1;
504
+ }
505
+
506
+ .toast i {
507
+ font-size: 1.5rem;
508
+ color: var(--accent-color);
509
+ }
510
+ </style>
511
+ </head>
512
+ <body>
513
+ <div class="bg-animation"></div>
514
+
515
+ <header>
516
+ <div class="header-content">
517
+ <div class="logo">
518
+ <i class="fas fa-radio"></i>
519
+ <span>Deutsche Radio Stream</span>
520
+ </div>
521
+ <div class="attribution">
522
+ Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a>
523
+ </div>
524
+ </div>
525
+ </header>
526
+
527
+ <main class="container">
528
+ <section class="player-section">
529
+ <div class="now-playing">
530
+ <div class="station-logo" id="stationLogo">
531
+ <i class="fas fa-broadcast-tower"></i>
532
+ </div>
533
+ <h2 class="station-name" id="stationName">Wähle eine Station</h2>
534
+ <p class="current-track" id="currentTrack">---</p>
535
+
536
+ <div class="visualizer paused" id="visualizer">
537
+ <div class="bar"></div>
538
+ <div class="bar"></div>
539
+ <div class="bar"></div>
540
+ <div class="bar"></div>
541
+ <div class="bar"></div>
542
+ <div class="bar"></div>
543
+ <div class="bar"></div>
544
+ <div class="bar"></div>
545
+ </div>
546
+ </div>
547
+
548
+ <div class="player-controls">
549
+ <button class="control-btn" id="prevBtn">
550
+ <i class="fas fa-backward"></i>
551
+ </button>
552
+ <button class="control-btn play-btn" id="playBtn">
553
+ <i class="fas fa-play"></i>
554
+ </button>
555
+ <button class="control-btn" id="nextBtn">
556
+ <i class="fas fa-forward"></i>
557
+ </button>
558
+ </div>
559
+
560
+ <div class="volume-control">
561
+ <i class="fas fa-volume-down"></i>
562
+ <input type="range" class="volume-slider" id="volumeSlider" min="0" max="100" value="70">
563
+ <i class="fas fa-volume-up"></i>
564
+ <span id="volumeValue">70%</span>
565
+ </div>
566
+ </section>
567
+
568
+ <section class="stations-section">
569
+ <h3 class="section-title">
570
+ <i class="fas fa-list"></i>
571
+ Radio Stationen
572
+ </h3>
573
+
574
+ <div class="categories">
575
+ <button class="category-btn active" data-category="all">Alle</button>
576
+ <button class="category-btn" data-category="pop">Pop</button>
577
+ <button class="category-btn" data-category="rock">Rock</button>
578
+ <button class="category-btn" data-category="news">Nachrichten</button>
579
+ <button class="category-btn" data-category="classic">Klassik</button>
580
+ </div>
581
+
582
+ <div class="stations-list" id="stationsList">
583
+ <!-- Stations will be populated by JavaScript -->
584
+ </div>
585
+ </section>
586
+ </main>
587
+
588
+ <div class="toast" id="toast">
589
+ <i class="fas fa-check-circle"></i>
590
+ <span id="toastMessage">Nachricht</span>
591
+ </div>
592
+
593
+ <audio id="audioPlayer" crossorigin="anonymous"></audio>
594
+
595
+ <script>
596
+ // German Radio Stations
597
+ const radioStations = [
598
+ {
599
+ id: 1,
600
+ name: "ANTENNE BAYERN",
601
+ genre: "Pop",
602
+ category: "pop",
603
+ url: "https://mp3channels.webradio.antenne.de/antenne-bayern",
604
+ icon: "fa-broadcast-tower"
605
+ },
606
+ {
607
+ id: 2,
608
+ name: "BAYERN 3",
609
+ genre: "Pop & Rock",
610
+ category: "pop",
611
+ url: "https://br-br3-live.cast.addradio.de/br/br3/live/mp3/128/stream.mp3",
612
+ icon: "fa-music"
613
+ },
614
+ {
615
+ id: 3,
616
+ name: "DEUTSCHLANDFUNK",
617
+ genre: "Nachrichten & Info",
618
+ category: "news",
619
+ url: "https://st01.dlf.de/dlf/01/128/mp3/stream.mp3",
620
+ icon: "fa-newspaper"
621
+ },
622
+ {
623
+ id: 4,
624
+ name: "HR3",
625
+ genre: "Pop",
626
+ category: "pop",
627
+ url: "https://hr-hr3-live.cast.addradio.de/hr/hr3/live/mp3/128/stream.mp3",
628
+ icon: "fa-radio"
629
+ },
630
+ {
631
+ id: 5,
632
+ name: "WDR 2",
633
+ genre: "Pop & News",
634
+ category: "pop",
635
+ url: "https://wdr-wdr2-rheinland.icecast.wdr.de/wdr/wdr2/rheinland/mp3/128/stream.mp3",
636
+ icon: "fa-microphone"
637
+ },
638
+ {
639
+ id: 6,
640
+ name: "SWR3",
641
+ genre: "Pop",
642
+ category: "pop",
643
+ url: "https://swr-swr3-live.cast.addradio.de/swr/swr3/live/mp3/128/stream.mp3",
644
+ icon: "fa-headphones"
645
+ },
646
+ {
647
+ id: 7,
648
+ name: "NDR 2",
649
+ genre: "Pop & Rock",
650
+ category: "rock",
651
+ url: "https://ndr-ndr2-niedersachsen.cast.addradio.de/ndr/ndr2/niedersachsen/mp3/128/stream.mp3",
652
+ icon: "fa-guitar"
653
+ },
654
+ {
655
+ id: 8,
656
+ name: "MDR JUMP",
657
+ genre: "Pop & Rock",
658
+ category: "rock",
659
+ url: "https://mdr-mdr-jump-live.cast.addradio.de/mdr/mdr-jump/live/mp3/128/stream.mp3",
660
+ icon: "fa-compact-disc"
661
+ },
662
+ {
663
+ id: 9,
664
+ name: "RBB 88.8",
665
+ genre: "Pop",
666
+ category: "pop",
667
+ url: "https://rbb-88-8-live.cast.addradio.de/rbb/rbb888/live/mp3/128/stream.mp3",
668
+ icon: "fa-broadcast-tower"
669
+ },
670
+ {
671
+ id: 10,
672
+ name: "BR-KLASSIK",
673
+ genre: "Klassik",
674
+ category: "classic",
675
+ url: "https://br-br-klassik-live.cast.addradio.de/br/br-klassik/live/mp3/128/stream.mp3",
676
+ icon: "fa-violin"
677
+ },
678
+ {
679
+ id: 11,
680
+ name: "DASDING",
681
+ genre: "Pop & Electro",
682
+ category: "pop",
683
+ url: "https://swr-dasding-live.cast.addradio.de/swr/dasding/live/mp3/128/stream.mp3",
684
+ icon: "fa-bolt"
685
+ },
686
+ {
687
+ id: 12,
688
+ name: "YOU FM",
689
+ genre: "Pop & Electro",
690
+ category: "pop",
691
+ url: "https://hr-youfm-live.cast.addradio.de/hr/youfm/live/mp3/128/stream.mp3",
692
+ icon: "fa-star"
693
+ }
694
+ ];
695
+
696
+ let currentStation = null;
697
+ let isPlaying = false;
698
+ let currentStationIndex = -1;
699
+ let filteredStations = [...radioStations];
700
+
701
+ // DOM Elements
702
+ const audioPlayer = document.getElementById('audioPlayer');
703
+ const playBtn = document.getElementById('playBtn');
704
+ const prevBtn = document.getElementById('prevBtn');
705
+ const nextBtn = document.getElementById('nextBtn');
706
+ const volumeSlider = document.getElementById('volumeSlider');
707
+ const volumeValue = document.getElementById('volumeValue');
708
+ const stationName = document.getElementById('stationName');
709
+ const currentTrack = document.getElementById('currentTrack');
710
+ const stationLogo = document.getElementById('stationLogo');
711
+ const visualizer = document.getElementById('visualizer');
712
+ const stationsList = document.getElementById('stationsList');
713
+ const toast = document.getElementById('toast');
714
+ const toastMessage = document.getElementById('toastMessage');
715
+
716
+ // Initialize
717
+ function init() {
718
+ renderStations();
719
+ setupEventListeners();
720
+ audioPlayer.volume = 0.7;
721
+ }
722
+
723
+ // Render stations list
724
+ function renderStations() {
725
+ stationsList.innerHTML = '';
726
+ filteredStations.forEach((station, index) => {
727
+ const stationElement = document.createElement('div');
728
+ stationElement.className = 'station-item';
729
+ stationElement.dataset.stationId = station.id;
730
+
731
+ const actualIndex = radioStations.findIndex(s => s.id === station.id);
732
+
733
+ stationElement.innerHTML = `
734
+ <div class="station-icon">
735
+ <i class="fas ${station.icon}"></i>
736
+ </div>
737
+ <div class="station-info">
738
+ <div class="station-title">${station.name}</div>
739
+ <div class="station-genre">${station.genre}</div>
740
+ </div>
741
+ <div class="station-live"></div>
742
+ `;
743
+
744
+ stationElement.addEventListener('click', () => selectStation(actualIndex));
745
+ stationsList.appendChild(stationElement);
746
+ });
747
+ }
748
+
749
+ // Setup event listeners
750
+ function setupEventListeners() {
751
+ playBtn.addEventListener('click', togglePlay);
752
+ prevBtn.addEventListener('click', playPrevious);
753
+ nextBtn.addEventListener('click', playNext);
754
+
755
+ volumeSlider.addEventListener('input', (e) => {
756
+ const volume = e.target.value / 100;
757
+ audioPlayer.volume = volume;
758
+ volumeValue.textContent = `${e.target.value}%`;
759
+ });
760
+
761
+ audioPlayer.addEventListener('error', (e) => {
762
+ console.error('Audio error:', e);
763
+ showToast('Fehler beim Laden der Station');
764
+ stopPlayback();
765
+ });
766
+
767
+ audioPlayer.addEventListener('ended', () => {
768
+ playNext();
769
+ });
770
+
771
+ // Category filters
772
+ document.querySelectorAll('.category-btn').forEach(btn => {
773
+ btn.addEventListener('click', (e) => {
774
+ document.querySelectorAll('.category-btn').forEach(b => b.classList.remove('active'));
775
+ e.target.classList.add('active');
776
+
777
+ const category = e.target.dataset.category;
778
+ if (category === 'all') {
779
+ filteredStations = [...radioStations];
780
+ } else {
781
+ filteredStations = radioStations.filter(s => s.category === category);
782
+ }
783
+ renderStations();
784
+ });
785
+ });
786
+ }
787
+
788
+ // Select station
789
+ function selectStation(index) {
790
+ if (index < 0 || index >= radioStations.length) return;
791
+
792
+ currentStationIndex = index;
793
+ currentStation = radioStations[index];
794
+
795
+ // Update UI
796
+ stationName.textContent = currentStation.name;
797
+ stationLogo.innerHTML = `<i class="fas ${currentStation.icon}"></i>`;
798
+ currentTrack.textContent = 'Verbinde...';
799
+
800
+ // Update active state in list
801
+ document.querySelectorAll('.station-item').forEach(item => {
802
+ item.classList.remove('active');
803
+ if (parseInt(item.dataset.stationId) === currentStation.id) {
804
+ item.classList.add('active');
805
+ }
806
+ });
807
+
808
+ // Load and play
809
+ audioPlayer.src = currentStation.url;
810
+ audioPlayer.load();
811
+
812
+ if (isPlaying) {
813
+ audioPlayer.play()
814
+ .then(() => {
815
+ currentTrack.textContent = 'Live Stream';
816
+ showToast(`Station: ${currentStation.name}`);
817
+ })
818
+ .catch(err => {
819
+ console.error('Play error:', err);
820
+ showToast('Fehler beim Abspielen');
821
+ stopPlayback();
822
+ });
823
+ }
824
+ }
825
+
826
+ // Toggle play/pause
827
+ function togglePlay() {
828
+ if (!currentStation && currentStationIndex === -1) {
829
+ selectStation(0);
830
+ }
831
+
832
+ if (isPlaying) {
833
+ pausePlayback();
834
+ } else {
835
+ startPlayback();
836
+ }
837
+ }
838
+
839
+ // Start playback
840
+ function startPlayback() {
841
+ if (!currentStation) return;
842
+
843
+ audioPlayer.play()
844
+ .then(() => {
845
+ isPlaying = true;
846
+ playBtn.innerHTML = '<i class="fas fa-pause"></i>';
847
+ visualizer.classList.remove('paused');
848
+ currentTrack.textContent = 'Live Stream';
849
+ })
850
+ .catch(err => {
851
+ console.error('Play error:', err);
852
+ showToast('Fehler beim Abspielen');
853
+ });
854
+ }
855
+
856
+ // Pause playback
857
+ function pausePlayback() {
858
+ audioPlayer.pause();
859
+ isPlaying = false;
860
+ playBtn.innerHTML = '<i class="fas fa-play"></i>';
861
+ visualizer.classList.add('paused');
862
+ currentTrack.textContent = 'Pausiert';
863
+ }
864
+
865
+ // Stop playback
866
+ function stopPlayback() {
867
+ audioPlayer.pause();
868
+ audioPlayer.src = '';
869
+ isPlaying = false;
870
+ playBtn.innerHTML = '<i class="fas fa-play"></i>';
871
+ visualizer.classList.add('paused');
872
+ currentTrack.textContent = '---';
873
+ }
874
+
875
+ // Play previous station
876
+ function playPrevious() {
877
+ if (currentStationIndex > 0) {
878
+ selectStation(currentStationIndex - 1);
879
+ if (!isPlaying) {
880
+ togglePlay();
881
+ }
882
+ }
883
+ }
884
+
885
+ // Play next station
886
+ function playNext() {
887
+ if (currentStationIndex < radioStations.length - 1) {
888
+ selectStation(currentStationIndex + 1);
889
+ if (!isPlaying) {
890
+ togglePlay();
891
+ }
892
+ }
893
+ }
894
+
895
+ // Show toast notification
896
+ function showToast(message) {
897
+ toastMessage.textContent = message;
898
+ toast.classList.add('show');
899
+ setTimeout(() => {
900
+ toast.classList.remove('show');
901
+ }, 3000);
902
+ }
903
+
904
+ // Initialize app
905
+ init();
906
+ </script>
907
+ </body>
908
+ </html>