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 *view = new BView(rect,"",B_FOLLOW_ALL, B_WILL_DRAW|B_PULSE_NEEDED); 78 view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 79 AddChild(view); 80 81 BRect stringRect(16, 5, 60, 22); 82 BStringView *stringView = new BStringView(stringRect, "event", "Event"); 83 stringView->SetFont(be_bold_font); 84 view->AddChild(stringView); 85 86 stringRect.OffsetBy(100, 0); 87 stringView = new BStringView(stringRect, "sound", "Sound"); 88 stringView->SetFont(be_bold_font); 89 view->AddChild(stringView); 90 91 rect.left += 13; 92 rect.right -= B_V_SCROLL_BAR_WIDTH + 13; 93 rect.top += 28; 94 rect.bottom -= 7; 95 fEventList = new HEventList(rect); 96 fEventList->SetType(BMediaFiles::B_SOUNDS); 97 98 BScrollView *scrollView = new BScrollView("" 99 ,fEventList 100 ,B_FOLLOW_ALL 101 ,0 102 ,false 103 ,true); 104 view->AddChild(scrollView); 105 106 rect = Bounds(); 107 rect.top = rect.bottom - 105; 108 view = new BView(rect,"",B_FOLLOW_LEFT_RIGHT|B_FOLLOW_BOTTOM,B_WILL_DRAW|B_PULSE_NEEDED); 109 view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 110 AddChild(view); 111 rect = view->Bounds().InsetBySelf(12, 12); 112 BBox *box = new BBox(rect,"",B_FOLLOW_ALL); 113 view->AddChild(box); 114 rect = box->Bounds(); 115 rect.top += 10; 116 rect.left += 15; 117 rect.right -= 10; 118 rect.bottom = rect.top + 20; 119 BMenu *menu = new BMenu("file"); 120 menu->SetRadioMode(true); 121 menu->SetLabelFromMarked(true); 122 menu->AddSeparatorItem(); 123 124 menu->AddItem(new BMenuItem("<none>",new BMessage(M_NONE_MESSAGE))); 125 menu->AddItem(new BMenuItem("Other…",new BMessage(M_OTHER_MESSAGE))); 126 BMenuField *menuField = new BMenuField(rect 127 ,"filemenu" 128 ,"Sound File:" 129 ,menu 130 ,B_FOLLOW_TOP|B_FOLLOW_LEFT); 131 menuField->SetDivider(menuField->StringWidth("Sound File:")+10); 132 box->AddChild(menuField); 133 rect.OffsetBy(-2,38); 134 rect.left = rect.right - 80; 135 BButton *button = new BButton(rect 136 ,"stop" 137 ,"Stop" 138 ,new BMessage(M_STOP_MESSAGE) 139 ,B_FOLLOW_RIGHT|B_FOLLOW_TOP); 140 box->AddChild(button); 141 142 rect.OffsetBy(-90,0); 143 button = new BButton(rect 144 ,"play" 145 ,"Play" 146 ,new BMessage(M_PLAY_MESSAGE) 147 ,B_FOLLOW_RIGHT|B_FOLLOW_TOP); 148 box->AddChild(button); 149 150 // setup file menu 151 SetupMenuField(); 152 menu->FindItem("<none>")->SetMarked(true); 153 } 154 155 156 /*********************************************************** 157 * MessageReceived 158 ***********************************************************/ 159 void 160 HWindow::MessageReceived(BMessage *message) 161 { 162 switch(message->what) { 163 case M_OTHER_MESSAGE: 164 { 165 BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField); 166 BMenu *menu = menufield->Menu(); 167 168 int32 sel = fEventList->CurrentSelection(); 169 if(sel >= 0) { 170 HEventItem *item = cast_as(fEventList->ItemAt(sel),HEventItem); 171 BPath path(item->Path()); 172 if(path.InitCheck() != B_OK) { 173 BMenuItem *item = menu->FindItem("<none>"); 174 if(item) 175 item->SetMarked(true); 176 } else{ 177 BMenuItem *item = menu->FindItem(path.Leaf()); 178 if(item) 179 item->SetMarked(true); 180 } 181 } 182 fFilePanel->Show(); 183 break; 184 } 185 case B_SIMPLE_DATA: 186 case B_REFS_RECEIVED: 187 { 188 entry_ref ref; 189 int32 sel = fEventList->CurrentSelection(); 190 if(message->FindRef("refs",&ref) == B_OK && sel >= 0) { 191 BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField); 192 BMenu *menu = menufield->Menu(); 193 // check audio file 194 BNode node(&ref); 195 BNodeInfo ninfo(&node); 196 char type[B_MIME_TYPE_LENGTH+1]; 197 ninfo.GetType(type); 198 BMimeType mtype(type); 199 BMimeType superType; 200 mtype.GetSupertype(&superType); 201 if(strcmp(superType.Type(),"audio") != 0) { 202 beep(); 203 (new BAlert("","This is not a audio file.","OK",NULL,NULL, 204 B_WIDTH_AS_USUAL,B_STOP_ALERT))->Go(); 205 break; 206 } 207 // add file item 208 BMessage *msg = new BMessage(M_ITEM_MESSAGE); 209 BPath path(&ref); 210 msg->AddRef("refs",&ref); 211 BMenuItem *menuitem = menu->FindItem(path.Leaf()); 212 if(!menuitem) 213 menu->AddItem(menuitem = new BMenuItem(path.Leaf(),msg),0); 214 // refresh item 215 fEventList->SetPath(BPath(&ref).Path()); 216 // check file menu 217 if(menuitem) 218 menuitem->SetMarked(true); 219 } 220 break; 221 } 222 case M_PLAY_MESSAGE: 223 { 224 int32 sel = fEventList->CurrentSelection(); 225 if(sel >= 0) 226 { 227 HEventItem *item = cast_as(fEventList->ItemAt(sel),HEventItem); 228 const char* path = item->Path(); 229 if(path) 230 { 231 entry_ref ref; 232 ::get_ref_for_path(path,&ref); 233 delete fPlayer; 234 fPlayer = new BFileGameSound(&ref,false); 235 fPlayer->StartPlaying(); 236 } 237 } 238 break; 239 } 240 case M_STOP_MESSAGE: 241 { 242 if(!fPlayer) 243 break; 244 if(fPlayer->IsPlaying()) 245 { 246 fPlayer->StopPlaying(); 247 delete fPlayer; 248 fPlayer = NULL; 249 } 250 break; 251 } 252 case M_EVENT_CHANGED: 253 { 254 const char* path; 255 BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField); 256 BMenu *menu = menufield->Menu(); 257 258 if(message->FindString("path",&path) == B_OK) { 259 BPath path(path); 260 if(path.InitCheck() != B_OK) { 261 BMenuItem *item = menu->FindItem("<none>"); 262 if(item) 263 item->SetMarked(true); 264 } else { 265 BMenuItem *item = menu->FindItem(path.Leaf()); 266 if(item) 267 item->SetMarked(true); 268 } 269 } 270 break; 271 } 272 case M_ITEM_MESSAGE: 273 { 274 entry_ref ref; 275 if(message->FindRef("refs",&ref) == B_OK) { 276 fEventList->SetPath(BPath(&ref).Path()); 277 } 278 break; 279 } 280 case M_NONE_MESSAGE: 281 { 282 fEventList->SetPath(NULL); 283 break; 284 } 285 default: 286 _inherited::MessageReceived(message); 287 } 288 } 289 290 /*********************************************************** 291 * Init menu 292 ***********************************************************/ 293 void 294 HWindow::SetupMenuField() 295 { 296 BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField); 297 BMenu *menu = menufield->Menu(); 298 int32 count = fEventList->CountItems(); 299 for(int32 i = 0; i < count; i++) { 300 HEventItem *item = cast_as(fEventList->ItemAt(i), HEventItem); 301 if(!item) 302 continue; 303 304 BPath path(item->Path()); 305 if(path.InitCheck() != B_OK) 306 continue; 307 if(menu->FindItem(path.Leaf())) 308 continue; 309 310 BMessage *msg = new BMessage(M_ITEM_MESSAGE); 311 entry_ref ref; 312 ::get_ref_for_path(path.Path(),&ref); 313 msg->AddRef("refs",&ref); 314 menu->AddItem(new BMenuItem(path.Leaf(),msg),0); 315 } 316 317 BPath path("/boot/beos/etc/sounds"); 318 status_t err = B_OK; 319 BDirectory dir( path.Path() ); 320 BEntry entry; 321 BPath item_path; 322 while( err == B_OK ){ 323 err = dir.GetNextEntry( (BEntry*)&entry, TRUE ); 324 if( entry.InitCheck() != B_NO_ERROR ){ 325 break; 326 } 327 entry.GetPath(&item_path); 328 329 if( menu->FindItem(item_path.Leaf()) ) 330 continue; 331 332 BMessage *msg = new BMessage(M_ITEM_MESSAGE); 333 entry_ref ref; 334 ::get_ref_for_path(item_path.Path(),&ref); 335 msg->AddRef("refs",&ref); 336 menu->AddItem(new BMenuItem(item_path.Leaf(),msg),0); 337 } 338 339 path.SetTo("/boot/home/config/sounds"); 340 dir.SetTo(path.Path()); 341 err = B_OK; 342 while( err == B_OK ){ 343 err = dir.GetNextEntry( (BEntry*)&entry, TRUE ); 344 if( entry.InitCheck() != B_NO_ERROR ){ 345 break; 346 } 347 entry.GetPath(&item_path); 348 349 if( menu->FindItem(item_path.Leaf()) ) 350 continue; 351 352 BMessage *msg = new BMessage(M_ITEM_MESSAGE); 353 entry_ref ref; 354 355 ::get_ref_for_path(item_path.Path(),&ref); 356 msg->AddRef("refs",&ref); 357 menu->AddItem(new BMenuItem(item_path.Leaf(),msg),0); 358 } 359 360 path.SetTo("/boot/home/media"); 361 dir.SetTo(path.Path()); 362 err = B_OK; 363 while( err == B_OK ){ 364 err = dir.GetNextEntry( (BEntry*)&entry, TRUE ); 365 if( entry.InitCheck() != B_NO_ERROR ){ 366 break; 367 } 368 entry.GetPath(&item_path); 369 370 if( menu->FindItem(item_path.Leaf()) ) 371 continue; 372 373 BMessage *msg = new BMessage(M_ITEM_MESSAGE); 374 entry_ref ref; 375 376 ::get_ref_for_path(item_path.Path(),&ref); 377 msg->AddRef("refs",&ref); 378 menu->AddItem(new BMenuItem(item_path.Leaf(),msg),0); 379 } 380 381 } 382 383 384 /*********************************************************** 385 * Pulse 386 ***********************************************************/ 387 void 388 HWindow::Pulse() 389 { 390 int32 sel = fEventList->CurrentSelection(); 391 BMenuField *menufield = cast_as(FindView("filemenu"),BMenuField); 392 BButton *button = cast_as(FindView("play"),BButton); 393 BButton *stop = cast_as(FindView("stop"),BButton); 394 395 if(!menufield) 396 return; 397 if(sel >=0) { 398 menufield->SetEnabled(true); 399 button->SetEnabled(true); 400 } else { 401 menufield->SetEnabled(false); 402 button->SetEnabled(false); 403 } 404 if(fPlayer) { 405 if(fPlayer->IsPlaying()) 406 stop->SetEnabled(true); 407 else 408 stop->SetEnabled(false); 409 } else 410 stop->SetEnabled(false); 411 } 412 413 414 /*********************************************************** 415 * DispatchMessage 416 ***********************************************************/ 417 void 418 HWindow::DispatchMessage(BMessage *message,BHandler *handler) 419 { 420 if(message->what == B_PULSE) 421 Pulse(); 422 BWindow::DispatchMessage(message,handler); 423 } 424 425 /*********************************************************** 426 * QuitRequested 427 ***********************************************************/ 428 bool 429 HWindow::QuitRequested() 430 { 431 fEventList->RemoveAll(); 432 be_app->PostMessage(B_QUIT_REQUESTED); 433 return true; 434 } 435