1 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 2 // 3 // Copyright (c) 2003, OpenBeOS 4 // 5 // This software is part of the OpenBeOS distribution and is covered 6 // by the OpenBeOS license. 7 // 8 // 9 // File: HWindow.cpp 10 // Author: Jérôme Duval, Oliver Ruiz Dorantes, Atsushi Takamatsu 11 // Description: Sounds Preferences 12 // Created : November 24, 2003 13 // 14 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 15 16 #include "HWindow.h" 17 #include "HEventList.h" 18 #include "HEventItem.h" 19 #include <ScrollView.h> 20 #include <StringView.h> 21 #include <ClassInfo.h> 22 #include <MediaFiles.h> 23 #include <MenuBar.h> 24 #include <Box.h> 25 #include <MenuItem.h> 26 #include <MenuField.h> 27 #include <Button.h> 28 #include <Beep.h> 29 #include <Path.h> 30 #include <Application.h> 31 #include <Node.h> 32 #include <NodeInfo.h> 33 #include <Alert.h> 34 #include <Roster.h> 35 #include <fs_attr.h> 36 #include <stdio.h> 37 #include <Sound.h> 38 39 /*********************************************************** 40 * Constructor 41 ***********************************************************/ 42 HWindow::HWindow(BRect rect ,const char* name) 43 :_inherited(rect,name,B_TITLED_WINDOW,0) 44 ,fFilePanel(NULL) 45 ,fPlayer(NULL) 46 { 47 InitGUI(); 48 float min_width,min_height,max_width,max_height; 49 GetSizeLimits(&min_width,&max_width,&min_height,&max_height); 50 min_width = 300; 51 min_height = 200; 52 SetSizeLimits(min_width,max_width,min_height,max_height); 53 54 fFilePanel = new BFilePanel(); 55 fFilePanel->SetTarget(this); 56 57 fEventList->Select(0); 58 } 59 60 /*********************************************************** 61 * Destructor 62 ***********************************************************/ 63 HWindow::~HWindow() 64 { 65 delete fFilePanel; 66 delete fPlayer; 67 } 68 69 /*********************************************************** 70 * Initialize GUIs. 71 ***********************************************************/ 72 void 73 HWindow::InitGUI() 74 { 75 BRect rect = Bounds(); 76 rect.bottom -= 106; 77 BView *listView = new BView(rect,"",B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED); 78 listView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 79 AddChild(listView); 80 81 BRect stringRect(16, 5, 60, 22); 82 BStringView *stringView = new BStringView(stringRect, "event", "Event"); 83 stringView->SetFont(be_bold_font); 84 stringView->ResizeToPreferred(); 85 listView->AddChild(stringView); 86 87 stringRect.OffsetBy(120, 0); 88 stringView = new BStringView(stringRect, "sound", "Sound"); 89 stringView->SetFont(be_bold_font); 90 stringView->ResizeToPreferred(); 91 listView->AddChild(stringView); 92 93 rect.left += 13; 94 rect.right -= B_V_SCROLL_BAR_WIDTH + 13; 95 rect.top += 28; 96 rect.bottom -= 7; 97 fEventList = new HEventList(rect); 98 fEventList->SetType(BMediaFiles::B_SOUNDS); 99 100 BScrollView *scrollView = new BScrollView("" 101 ,fEventList 102 ,B_FOLLOW_ALL 103 ,0 104 ,false 105 ,true); 106 listView->AddChild(scrollView); 107 108 rect = Bounds(); 109 rect.top = rect.bottom - 105; 110 BView *view = new BView(rect,"", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED); 111 view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 112 AddChild(view); 113 rect = view->Bounds().InsetBySelf(12, 12); 114 BBox *box = new BBox(rect,"",B_FOLLOW_ALL); 115 view->AddChild(box); 116 rect = box->Bounds(); 117 rect.top += 10; 118 rect.left += 15; 119 rect.right -= 10; 120 rect.bottom = rect.top + 20; 121 BMenu *menu = new BMenu("file"); 122 menu->SetRadioMode(true); 123 menu->SetLabelFromMarked(true); 124 menu->AddSeparatorItem(); 125 126 menu->AddItem(new BMenuItem("<none>",new BMessage(M_NONE_MESSAGE))); 127 menu->AddItem(new BMenuItem("Other…",new BMessage(M_OTHER_MESSAGE))); 128 BMenuField *menuField = new BMenuField(rect 129 ,"filemenu" 130 ,"Sound File:" 131 ,menu 132 ,B_FOLLOW_TOP | B_FOLLOW_LEFT); 133 menuField->SetDivider(menuField->StringWidth("Sound File:") + 10); 134 box->AddChild(menuField); 135 rect.OffsetBy(-2, menuField->Bounds().Height() + 15); 136 BButton *button = new BButton(rect 137 ,"stop" 138 ,"Stop" 139 ,new BMessage(M_STOP_MESSAGE) 140 ,B_FOLLOW_RIGHT | B_FOLLOW_TOP); 141 button->ResizeToPreferred(); 142 button->MoveTo(box->Bounds().right - button->Bounds().Width() - 15, rect.top); 143 box->AddChild(button); 144 145 rect = button->Frame(); 146 view->ResizeTo(view->Bounds().Width(), 24 + rect.bottom + 12); 147 box->ResizeTo(box->Bounds().Width(), rect.bottom + 12); 148 149 button->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP); 150 button = new BButton(rect 151 ,"play" 152 ,"Play" 153 ,new BMessage(M_PLAY_MESSAGE) 154 ,B_FOLLOW_RIGHT | B_FOLLOW_TOP); 155 button->ResizeToPreferred(); 156 button->MoveTo(rect.left - button->Bounds().Width() - 15, rect.top); 157 box->AddChild(button); 158 159 view->MoveTo(0, listView->Frame().bottom); 160 ResizeTo(Bounds().Width(), listView->Frame().bottom + view->Bounds().Height()); 161 listView->SetResizingMode(B_FOLLOW_ALL); 162 view->SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); 163 164 // setup file menu 165 SetupMenuField(); 166 menu->FindItem("<none>")->SetMarked(true); 167 } 168 169 170 /*********************************************************** 171 * MessageReceived 172 ***********************************************************/ 173 void 174 HWindow::MessageReceived(BMessage *message) 175 { 176 switch(message->what) { 177 case M_OTHER_MESSAGE: 178 { 179 BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField); 180 BMenu *menu = menufield->Menu(); 181 182 int32 sel = fEventList->CurrentSelection(); 183 if(sel >= 0) { 184 HEventItem *item = cast_as(fEventList->ItemAt(sel),HEventItem); 185 BPath path(item->Path()); 186 if(path.InitCheck() != B_OK) { 187 BMenuItem *item = menu->FindItem("<none>"); 188 if(item) 189 item->SetMarked(true); 190 } else{ 191 BMenuItem *item = menu->FindItem(path.Leaf()); 192 if(item) 193 item->SetMarked(true); 194 } 195 } 196 fFilePanel->Show(); 197 break; 198 } 199 case B_SIMPLE_DATA: 200 case B_REFS_RECEIVED: 201 { 202 entry_ref ref; 203 int32 sel = fEventList->CurrentSelection(); 204 if(message->FindRef("refs",&ref) == B_OK && sel >= 0) { 205 BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField); 206 BMenu *menu = menufield->Menu(); 207 // check audio file 208 BNode node(&ref); 209 BNodeInfo ninfo(&node); 210 char type[B_MIME_TYPE_LENGTH+1]; 211 ninfo.GetType(type); 212 BMimeType mtype(type); 213 BMimeType superType; 214 mtype.GetSupertype(&superType); 215 if(strcmp(superType.Type(),"audio") != 0) { 216 beep(); 217 (new BAlert("","This is not a audio file.","OK",NULL,NULL, 218 B_WIDTH_AS_USUAL,B_STOP_ALERT))->Go(); 219 break; 220 } 221 // add file item 222 BMessage *msg = new BMessage(M_ITEM_MESSAGE); 223 BPath path(&ref); 224 msg->AddRef("refs",&ref); 225 BMenuItem *menuitem = menu->FindItem(path.Leaf()); 226 if(!menuitem) 227 menu->AddItem(menuitem = new BMenuItem(path.Leaf(),msg),0); 228 // refresh item 229 fEventList->SetPath(BPath(&ref).Path()); 230 // check file menu 231 if(menuitem) 232 menuitem->SetMarked(true); 233 } 234 break; 235 } 236 case M_PLAY_MESSAGE: 237 { 238 int32 sel = fEventList->CurrentSelection(); 239 if(sel >= 0) 240 { 241 HEventItem *item = cast_as(fEventList->ItemAt(sel),HEventItem); 242 const char* path = item->Path(); 243 if(path) 244 { 245 entry_ref ref; 246 ::get_ref_for_path(path,&ref); 247 delete fPlayer; 248 fPlayer = new BFileGameSound(&ref,false); 249 fPlayer->StartPlaying(); 250 } 251 } 252 break; 253 } 254 case M_STOP_MESSAGE: 255 { 256 if(!fPlayer) 257 break; 258 if(fPlayer->IsPlaying()) 259 { 260 fPlayer->StopPlaying(); 261 delete fPlayer; 262 fPlayer = NULL; 263 } 264 break; 265 } 266 case M_EVENT_CHANGED: 267 { 268 const char* path; 269 BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField); 270 BMenu *menu = menufield->Menu(); 271 272 if(message->FindString("path",&path) == B_OK) { 273 BPath path(path); 274 if(path.InitCheck() != B_OK) { 275 BMenuItem *item = menu->FindItem("<none>"); 276 if(item) 277 item->SetMarked(true); 278 } else { 279 BMenuItem *item = menu->FindItem(path.Leaf()); 280 if(item) 281 item->SetMarked(true); 282 } 283 } 284 break; 285 } 286 case M_ITEM_MESSAGE: 287 { 288 entry_ref ref; 289 if(message->FindRef("refs",&ref) == B_OK) { 290 fEventList->SetPath(BPath(&ref).Path()); 291 } 292 break; 293 } 294 case M_NONE_MESSAGE: 295 { 296 fEventList->SetPath(NULL); 297 break; 298 } 299 default: 300 _inherited::MessageReceived(message); 301 } 302 } 303 304 /*********************************************************** 305 * Init menu 306 ***********************************************************/ 307 void 308 HWindow::SetupMenuField() 309 { 310 BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField); 311 BMenu *menu = menufield->Menu(); 312 int32 count = fEventList->CountItems(); 313 for(int32 i = 0; i < count; i++) { 314 HEventItem *item = cast_as(fEventList->ItemAt(i), HEventItem); 315 if(!item) 316 continue; 317 318 BPath path(item->Path()); 319 if(path.InitCheck() != B_OK) 320 continue; 321 if(menu->FindItem(path.Leaf())) 322 continue; 323 324 BMessage *msg = new BMessage(M_ITEM_MESSAGE); 325 entry_ref ref; 326 ::get_ref_for_path(path.Path(),&ref); 327 msg->AddRef("refs",&ref); 328 menu->AddItem(new BMenuItem(path.Leaf(),msg),0); 329 } 330 331 BPath path("/boot/beos/etc/sounds"); 332 status_t err = B_OK; 333 BDirectory dir( path.Path() ); 334 BEntry entry; 335 BPath item_path; 336 while( err == B_OK ){ 337 err = dir.GetNextEntry( (BEntry*)&entry, TRUE ); 338 if( entry.InitCheck() != B_NO_ERROR ){ 339 break; 340 } 341 entry.GetPath(&item_path); 342 343 if( menu->FindItem(item_path.Leaf()) ) 344 continue; 345 346 BMessage *msg = new BMessage(M_ITEM_MESSAGE); 347 entry_ref ref; 348 ::get_ref_for_path(item_path.Path(),&ref); 349 msg->AddRef("refs",&ref); 350 menu->AddItem(new BMenuItem(item_path.Leaf(),msg),0); 351 } 352 353 path.SetTo("/boot/home/config/sounds"); 354 dir.SetTo(path.Path()); 355 err = B_OK; 356 while( err == B_OK ){ 357 err = dir.GetNextEntry( (BEntry*)&entry, TRUE ); 358 if( entry.InitCheck() != B_NO_ERROR ){ 359 break; 360 } 361 entry.GetPath(&item_path); 362 363 if( menu->FindItem(item_path.Leaf()) ) 364 continue; 365 366 BMessage *msg = new BMessage(M_ITEM_MESSAGE); 367 entry_ref ref; 368 369 ::get_ref_for_path(item_path.Path(),&ref); 370 msg->AddRef("refs",&ref); 371 menu->AddItem(new BMenuItem(item_path.Leaf(),msg),0); 372 } 373 374 path.SetTo("/boot/home/media"); 375 dir.SetTo(path.Path()); 376 err = B_OK; 377 while( err == B_OK ){ 378 err = dir.GetNextEntry( (BEntry*)&entry, TRUE ); 379 if( entry.InitCheck() != B_NO_ERROR ){ 380 break; 381 } 382 entry.GetPath(&item_path); 383 384 if( menu->FindItem(item_path.Leaf()) ) 385 continue; 386 387 BMessage *msg = new BMessage(M_ITEM_MESSAGE); 388 entry_ref ref; 389 390 ::get_ref_for_path(item_path.Path(),&ref); 391 msg->AddRef("refs",&ref); 392 menu->AddItem(new BMenuItem(item_path.Leaf(),msg),0); 393 } 394 395 } 396 397 398 /*********************************************************** 399 * Pulse 400 ***********************************************************/ 401 void 402 HWindow::Pulse() 403 { 404 int32 sel = fEventList->CurrentSelection(); 405 BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField); 406 BButton *button = cast_as(FindView("play"),BButton); 407 BButton *stop = cast_as(FindView("stop"),BButton); 408 409 if(!menufield) 410 return; 411 if(sel >=0) { 412 menufield->SetEnabled(true); 413 button->SetEnabled(true); 414 } else { 415 menufield->SetEnabled(false); 416 button->SetEnabled(false); 417 } 418 if(fPlayer) { 419 if(fPlayer->IsPlaying()) 420 stop->SetEnabled(true); 421 else 422 stop->SetEnabled(false); 423 } else 424 stop->SetEnabled(false); 425 } 426 427 428 /*********************************************************** 429 * DispatchMessage 430 ***********************************************************/ 431 void 432 HWindow::DispatchMessage(BMessage *message,BHandler *handler) 433 { 434 if(message->what == B_PULSE) 435 Pulse(); 436 BWindow::DispatchMessage(message,handler); 437 } 438 439 /*********************************************************** 440 * QuitRequested 441 ***********************************************************/ 442 bool 443 HWindow::QuitRequested() 444 { 445 fEventList->RemoveAll(); 446 be_app->PostMessage(B_QUIT_REQUESTED); 447 return true; 448 } 449