ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SIDPlayer/src/main_beos.cpp
Revision: 1.3
Committed: 2001-01-04T19:54:13Z (23 years, 2 months ago) by cebix
Branch: MAIN
Changes since 1.2: +8 -3 lines
Log Message:
- split prefs.cpp into prefs.cpp and prefs_items.cpp
- it's now possible to specify prefs items on the command line

File Contents

# Content
1 /*
2 * main_beos.cpp - SIDPlayer BeOS main program
3 *
4 * SIDPlayer (C) Copyright 1996-2000 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "sys.h"
22
23 #include <AppKit.h>
24 #include <InterfaceKit.h>
25 #include <storage/Path.h>
26 #include <media/SoundPlayer.h>
27
28 #include <stdio.h>
29
30 #include "main.h"
31 #include "prefs_window.h"
32
33
34 // Message codes
35 const uint32 MSG_NEW_MODULE = 'load';
36 const uint32 MSG_NEW_SONG = 'song';
37 const uint32 MSG_SHOW_PREFS = 'pref';
38 const uint32 MSG_PLAY_PAUSE = 'plpa';
39 const uint32 MSG_STOP = 'stop';
40 const uint32 MSG_NEXT = 'next';
41 const uint32 MSG_PREV = 'prev';
42
43
44 class MainWindow;
45 class SpeedSlider;
46
47 // Application object
48 class SIDPlayer : public BApplication {
49 public:
50 SIDPlayer();
51 virtual ~SIDPlayer();
52 virtual void ArgvReceived(int32 argc, char **argv);
53 virtual void RefsReceived(BMessage *msg);
54 virtual void MessageReceived(BMessage *msg);
55 virtual void ReadyToRun(void);
56 virtual void AboutRequested(void);
57
58 private:
59 static void buffer_proc(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format);
60
61 MainWindow *main_window;
62 PrefsWindow *prefs_window;
63 BSoundPlayer player;
64 bool player_stopped;
65 };
66
67
68 // Main window object
69 class MainWindow : public BWindow {
70 public:
71 MainWindow();
72 virtual bool QuitRequested(void);
73 virtual void MessageReceived(BMessage *msg);
74
75 private:
76 BStringView *make_name_display(BRect frame, char *label_text, BView *parent);
77
78 rgb_color fill_color;
79
80 BStringView *name_view;
81 BStringView *author_view;
82 BStringView *copyright_view;
83 BStringView *position_view;
84 SpeedSlider *speed_slider;
85 };
86
87
88 // Top view object (handles drag&drop)
89 class TopView : public BView {
90 public:
91 TopView(BRect frame, const char *name, uint32 resizingMode, uint32 flags);
92 virtual void MessageReceived(BMessage *msg);
93 virtual void KeyDown(const char *bytes, int32 numBytes);
94 };
95
96
97 // Buttons
98 class PlayPauseButton : public BButton {
99 public:
100 PlayPauseButton(BRect frame, BMessage *msg);
101 virtual void Draw(BRect update);
102 };
103
104 class StopButton : public BButton {
105 public:
106 StopButton(BRect frame, BMessage *msg);
107 virtual void Draw(BRect update);
108 };
109
110 class NextButton : public BButton {
111 public:
112 NextButton(BRect frame, BMessage *msg);
113 virtual void Draw(BRect update);
114 };
115
116 class PrevButton : public BButton {
117 public:
118 PrevButton(BRect frame, BMessage *msg);
119 virtual void Draw(BRect update);
120 };
121
122
123 // Speed slider
124 class SpeedSlider : public BSlider {
125 public:
126 SpeedSlider(BRect frame, const char *name) : BSlider(frame, name, "Speed", NULL, -100, 100, B_TRIANGLE_THUMB)
127 {
128 SetHashMarks(B_HASH_MARKS_TOP);
129 SetHashMarkCount(3);
130 const rgb_color bar_color = {128, 128, 216, 0};
131 SetBarColor(bar_color);
132 SetValue(0);
133 }
134 virtual ~SpeedSlider() {}
135 virtual void SetValue(int32 value)
136 {
137 int percent = value < 0 ? 100 + value / 2 : 100 + value;
138 sprintf(status, "%d%%", percent);
139 SIDAdjustSpeed(percent);
140 BSlider::SetValue(value);
141 }
142 virtual char *UpdateText(void) const
143 {
144 return status;
145 }
146
147 private:
148 mutable char status[32];
149 };
150
151
152 /*
153 * Application constructor
154 */
155
156 #if B_HOST_IS_LENDIAN
157 const media_raw_audio_format audio_format = {44100.0, 2, media_raw_audio_format::B_AUDIO_SHORT, B_MEDIA_LITTLE_ENDIAN, 4096};
158 #else
159 const media_raw_audio_format audio_format = {44100.0, 2, media_raw_audio_format::B_AUDIO_SHORT, B_MEDIA_BIG_ENDIAN, 4096};
160 #endif
161
162 SIDPlayer::SIDPlayer() : BApplication("application/x-vnd.cebix-SIDPlayer"), player(&audio_format, "SIDPlayer", buffer_proc)
163 {
164 main_window = NULL;
165 player.SetHasData(true);
166 player_stopped = true;
167 }
168
169
170 /*
171 * Application destructor
172 */
173
174 SIDPlayer::~SIDPlayer()
175 {
176 main_window = NULL;
177 prefs_window = NULL;
178 player.Stop();
179 player_stopped = true;
180 }
181
182
183 /*
184 * Shell arguments received
185 */
186
187 void SIDPlayer::ArgvReceived(int32 argc, char **argv)
188 {
189 if (argc < 2)
190 return;
191
192 for (int i=1; i<argc; i++) {
193 if (argv[i][0] == '-')
194 continue;
195 player.Stop();
196 LoadPSIDFile(argv[i]);
197 player.Start();
198 player_stopped = false;
199 if (main_window)
200 main_window->PostMessage(MSG_NEW_MODULE);
201 }
202 }
203
204
205 /*
206 * Tracker arguments received
207 */
208
209 void SIDPlayer::RefsReceived(BMessage *msg)
210 {
211 entry_ref the_ref;
212 if (msg->FindRef("refs", &the_ref) == B_NO_ERROR) {
213 BEntry the_entry;
214 if (the_entry.SetTo(&the_ref) == B_NO_ERROR) {
215 if (the_entry.IsFile()) {
216 BPath the_path;
217 the_entry.GetPath(&the_path);
218 player.Stop();
219 LoadPSIDFile(the_path.Path());
220 player.Start();
221 player_stopped = false;
222 if (main_window)
223 main_window->PostMessage(MSG_NEW_MODULE);
224 }
225 }
226 }
227 }
228
229
230 /*
231 * Message received
232 */
233
234 void SIDPlayer::MessageReceived(BMessage *msg)
235 {
236 switch (msg->what) {
237
238 case B_SIMPLE_DATA: // Dropped message
239 RefsReceived(msg);
240 break;
241
242 case MSG_SHOW_PREFS:
243 if (!prefs_window_open)
244 prefs_window = new PrefsWindow();
245 else if (prefs_window)
246 prefs_window->Activate(true);
247 break;
248
249 case MSG_PLAY_PAUSE:
250 if (player_stopped) {
251 player.Start();
252 player_stopped = false;
253 } else {
254 player.Stop();
255 player_stopped = true;
256 }
257 break;
258
259 case MSG_STOP:
260 player.Stop();
261 player_stopped = true;
262 SelectSong(current_song);
263 main_window->PostMessage(MSG_NEW_SONG);
264 break;
265
266 case MSG_NEXT:
267 if (current_song < number_of_songs-1) {
268 player.Stop();
269 SelectSong(current_song + 1);
270 main_window->PostMessage(MSG_NEW_SONG);
271 if (!player_stopped)
272 player.Start();
273 }
274 break;
275
276 case MSG_PREV:
277 if (current_song > 0) {
278 player.Stop();
279 SelectSong(current_song - 1);
280 main_window->PostMessage(MSG_NEW_SONG);
281 if (!player_stopped)
282 player.Start();
283 }
284 break;
285
286 default:
287 BApplication::MessageReceived(msg);
288 break;
289 }
290 }
291
292
293 /*
294 * Arguments processed, open player window
295 */
296
297 void SIDPlayer::ReadyToRun(void)
298 {
299 main_window = new MainWindow();
300 if (psid_loaded)
301 main_window->PostMessage(MSG_NEW_MODULE);
302 }
303
304
305 /*
306 * Show About window
307 */
308
309 void AboutWindow(void)
310 {
311 BAlert *theAlert = new BAlert("",
312 "SIDPlayer\nVersion " VERSION "\n\n"
313 "Copyright " B_UTF8_COPYRIGHT " 1996-2000 Christian Bauer\n"
314 "E-mail: Christian.Bauer@uni-mainz.de\n"
315 "http://www.uni-mainz.de/~bauec002/\n\n"
316 "SIDPlayer comes with ABSOLUTELY NO\n"
317 "WARRANTY. This is free software, and\n"
318 "you are welcome to redistribute it\n"
319 "under the terms of the GNU General\n"
320 "Public License.\n",
321 "OK", NULL, NULL, B_WIDTH_FROM_LABEL);
322
323 BTextView *theText = theAlert->TextView();
324 if (theText) {
325 theText->SetStylable(true);
326 theText->Select(0, 9);
327 BFont ourFont;
328 theText->SetFontAndColor(be_bold_font);
329 theText->GetFontAndColor(2, &ourFont, NULL);
330 ourFont.SetSize(24);
331 theText->SetFontAndColor(&ourFont);
332 }
333 theAlert->Go();
334 }
335
336 void SIDPlayer::AboutRequested(void)
337 {
338 AboutWindow();
339 }
340
341
342 /*
343 * SoundPlayer buffer procedure
344 */
345
346 void SIDPlayer::buffer_proc(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format)
347 {
348 SIDCalcBuffer((uint8 *)buffer, size);
349 }
350
351
352 /*
353 * Main window constructor
354 */
355
356 MainWindow::MainWindow() : BWindow(BRect(0, 0, 284, 96), "SIDPlayer", B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS)
357 {
358 fill_color = ui_color(B_PANEL_BACKGROUND_COLOR);
359 BRect b = Bounds();
360
361 // Move window to right position
362 Lock();
363 MoveTo(80, 80);
364
365 // Create menu bar
366 BMenuBar *bar = new BMenuBar(BRect(0, 0, b.right, b.bottom), "menubar");
367 BMenu *menu = new BMenu("File");
368 menu->AddItem(new BMenuItem("About SIDPlayer" B_UTF8_ELLIPSIS, new BMessage(B_ABOUT_REQUESTED)));
369 menu->AddItem(new BSeparatorItem());
370 menu->AddItem(new BMenuItem("Sound Control" B_UTF8_ELLIPSIS, new BMessage(MSG_SHOW_PREFS), 'P'));
371 menu->AddItem(new BSeparatorItem());
372 menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'));
373 menu->SetTargetForItems(be_app);
374 bar->AddItem(menu);
375 AddChild(bar);
376 SetKeyMenuBar(bar);
377 float menu_height = bar->Bounds().Height();
378
379 // Resize window to fit menu bar
380 ResizeBy(0, menu_height);
381
382 // Light gray background
383 TopView *top = new TopView(BRect(0, menu_height, b.right, b.bottom + menu_height), "main", B_FOLLOW_NONE, B_WILL_DRAW);
384 AddChild(top);
385 top->SetViewColor(fill_color);
386
387 // Name/author/copyright display
388 name_view = make_name_display(BRect(0, 5, 279, 21), "Name", top);
389 author_view = make_name_display(BRect(0, 25, 279, 41), "Author", top);
390 copyright_view = make_name_display(BRect(0, 45, 279, 61), "Copyright", top);
391
392 // Buttons
393 top->AddChild(new PlayPauseButton(BRect(6, 67, 36, 91), new BMessage(MSG_PLAY_PAUSE)));
394 top->AddChild(new StopButton(BRect(37, 67, 67, 91), new BMessage(MSG_STOP)));
395 top->AddChild(new PrevButton(BRect(68, 67, 98, 91), new BMessage(MSG_PREV)));
396 top->AddChild(new NextButton(BRect(99, 67, 129, 91), new BMessage(MSG_NEXT)));
397
398 // Position indicator
399 top->AddChild(position_view = new BStringView(BRect(134, 72, 193, 85), "position", ""));
400 position_view->SetViewColor(fill_color);
401
402 // Speed slider
403 top->AddChild(speed_slider = new SpeedSlider(BRect(194, 62, 279, 63), "speed"));
404
405 // Show window
406 top->MakeFocus();
407 Unlock();
408 Show();
409 }
410
411
412 /*
413 * Create name display field
414 */
415
416 BStringView *MainWindow::make_name_display(BRect frame, char *label_text, BView *parent)
417 {
418 // Label to the left of the display field
419 BRect label_rect = frame;
420 label_rect.right = label_rect.left + 65;
421
422 BStringView *label = new BStringView(label_rect, "", label_text);
423 parent->AddChild(label);
424 label->SetViewColor(fill_color);
425 label->SetLowColor(fill_color);
426 label->SetAlignment(B_ALIGN_RIGHT);
427 label->SetFont(be_bold_font);
428
429 // Box around display field
430 BRect frame_rect = frame;
431 frame_rect.left += 70;
432
433 BBox *box = new BBox(frame_rect);
434 parent->AddChild(box);
435 box->SetViewColor(fill_color);
436 box->SetLowColor(fill_color);
437
438 // The display field
439 BRect textview_rect = frame_rect;
440 textview_rect.OffsetTo(0, 0);
441 textview_rect.InsetBy(4, 2);
442
443 BStringView *text = new BStringView(textview_rect, "", "");
444 box->AddChild(text);
445 text->SetViewColor(fill_color);
446 text->SetLowColor(fill_color);
447 text->SetFont(be_plain_font);
448 return text;
449 }
450
451
452 /*
453 * Main window closed, quit program
454 */
455
456 bool MainWindow::QuitRequested(void)
457 {
458 be_app->PostMessage(B_QUIT_REQUESTED);
459 return true;
460 }
461
462
463 /*
464 * Message received
465 */
466
467 void MainWindow::MessageReceived(BMessage *msg)
468 {
469 switch (msg->what) {
470 case MSG_NEW_MODULE:
471 // Update text views
472 Lock();
473 name_view->SetText(module_name);
474 author_view->SetText(author_name);
475 copyright_view->SetText(copyright_info);
476 Unlock();
477 // falls through
478
479 case MSG_NEW_SONG:
480 // Update position indicator and speed slider
481 if (number_of_songs > 0) {
482 char str[16];
483 sprintf(str, "Song %d/%d", current_song + 1, number_of_songs);
484 position_view->SetText(str);
485 }
486 speed_slider->SetValue(0);
487 break;
488
489 case MSG_SHOW_PREFS:
490 case MSG_PLAY_PAUSE:
491 case MSG_STOP:
492 case MSG_NEXT:
493 case MSG_PREV:
494 be_app->PostMessage(msg);
495 break;
496
497 default:
498 BWindow::MessageReceived(msg);
499 break;
500 }
501 }
502
503
504 /*
505 * TopView handles dropped messages (load new PSID module) and keypresses
506 */
507
508 TopView::TopView(BRect frame, const char *name, uint32 resizingMode, uint32 flags)
509 : BView(frame, name, resizingMode, flags) {}
510
511 void TopView::MessageReceived(BMessage *msg)
512 {
513 if (msg->what == B_SIMPLE_DATA)
514 be_app->PostMessage(msg);
515 else
516 BView::MessageReceived(msg);
517 }
518
519 void TopView::KeyDown(const char *bytes, int32 numBytes)
520 {
521 BMessage *msg = Window()->CurrentMessage();
522 uint32 modifiers = 0;
523 msg->FindInt32("modifiers", (int32 *)&modifiers);
524
525 switch (bytes[0]) {
526 case 'p':
527 case 'P':
528 Window()->PostMessage(MSG_PLAY_PAUSE);
529 break;
530
531 case B_ESCAPE:
532 case B_SPACE:
533 case 's':
534 case 'S':
535 Window()->PostMessage(MSG_STOP);
536 break;
537
538 case B_LEFT_ARROW:
539 Window()->PostMessage(MSG_PREV);
540 break;
541
542 case B_RIGHT_ARROW:
543 case 'n':
544 case 'N':
545 Window()->PostMessage(MSG_NEXT);
546 break;
547
548 case 'q':
549 case 'Q':
550 be_app->PostMessage(B_QUIT_REQUESTED);
551 break;
552 }
553 }
554
555
556 /*
557 * Play/Pause button
558 */
559
560 PlayPauseButton::PlayPauseButton(BRect frame, BMessage *msg) : BButton(frame, "play", "", msg) {};
561
562 void PlayPauseButton::Draw(BRect update)
563 {
564 // First draw normal button
565 BButton::Draw(update);
566
567 // Then draw play/pause image on top of it
568 if (Value())
569 SetHighColor(255, 255, 255);
570 else
571 SetHighColor(0, 0, 0);
572
573 FillRect(BRect(11, 8, 13, 16));
574 FillTriangle(BPoint(16, 8), BPoint(16, 16), BPoint(20, 12));
575 }
576
577
578 /*
579 * Stop button
580 */
581
582 StopButton::StopButton(BRect frame, BMessage *msg) : BButton(frame, "stop", "", msg) {};
583
584 void StopButton::Draw(BRect update)
585 {
586 // First draw normal button
587 BButton::Draw(update);
588
589 // Then draw stop image on top of it
590 if (Value())
591 SetHighColor(255, 255, 255);
592 else
593 SetHighColor(0, 0, 0);
594
595 FillRect(BRect(11, 8, 20, 16));
596 }
597
598
599 /*
600 * "Next" button
601 */
602
603 NextButton::NextButton(BRect frame, BMessage *msg) : BButton(frame, "next", "", msg) {};
604
605 void NextButton::Draw(BRect update)
606 {
607 // First draw normal button
608 BButton::Draw(update);
609
610 // Then draw "next" image on top of it
611 if (Value())
612 SetHighColor(255, 255, 255);
613 else
614 SetHighColor(0, 0, 0);
615
616 FillTriangle(BPoint(12, 8), BPoint(12, 16), BPoint(16, 12));
617 FillRect(BRect(17, 8, 19, 16));
618 }
619
620
621 /*
622 * "Prev" button
623 */
624
625 PrevButton::PrevButton(BRect frame, BMessage *msg) : BButton(frame, "prev", "", msg) {};
626
627 void PrevButton::Draw(BRect update)
628 {
629 // First draw normal button
630 BButton::Draw(update);
631
632 // Then draw "prev" image on top of it
633 if (Value())
634 SetHighColor(255, 255, 255);
635 else
636 SetHighColor(0, 0, 0);
637
638 FillRect(BRect(12, 8, 14, 16));
639 FillTriangle(BPoint(19, 8), BPoint(19, 16), BPoint(15, 12));
640 }
641
642
643 /*
644 * Main program
645 */
646
647 int main(int argc, char **argv)
648 {
649 InitAll(argc, argv);
650 SIDPlayer *the_app = new SIDPlayer();
651 the_app->Run();
652 delete the_app;
653 ExitAll();
654 return 0;
655 }