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