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, 3 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

# User Rev Content
1 cebix 1.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 cebix 1.3 if (argc < 2)
190     return;
191    
192     for (int i=1; i<argc; i++) {
193     if (argv[i][0] == '-')
194     continue;
195 cebix 1.1 player.Stop();
196 cebix 1.3 LoadPSIDFile(argv[i]);
197 cebix 1.1 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 cebix 1.2 "SIDPlayer\nVersion " VERSION "\n\n"
313 cebix 1.1 "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 cebix 1.3 InitAll(argc, argv);
650 cebix 1.1 SIDPlayer *the_app = new SIDPlayer();
651     the_app->Run();
652     delete the_app;
653     ExitAll();
654     return 0;
655     }