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: MediaViews.cpp 10 // Author: Sikosis, Jérôme Duval 11 // Description: Media Preferences 12 // Created : June 25, 2003 13 // 14 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 15 16 17 #include "MediaViews.h" 18 19 #include <Box.h> 20 #include <Button.h> 21 #include <Catalog.h> 22 #include <Deskbar.h> 23 #include <Entry.h> 24 #include <GridView.h> 25 #include <GroupView.h> 26 #include <Locale.h> 27 #include <MediaAddOn.h> 28 #include <MediaRoster.h> 29 #include <MenuField.h> 30 #include <PopUpMenu.h> 31 #include <SpaceLayoutItem.h> 32 #include <String.h> 33 #include <TextView.h> 34 35 #include <stdio.h> 36 37 38 #undef B_TRANSLATE_CONTEXT 39 #define B_TRANSLATE_CONTEXT "Media views" 40 41 42 SettingsView::SettingsView (bool isVideo) 43 : 44 BView("SettingsView", B_WILL_DRAW | B_SUPPORTS_LAYOUT), 45 fIsVideo(isVideo) 46 { 47 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 48 49 // create the default box 50 51 // input menu 52 fInputMenu = new BPopUpMenu(B_TRANSLATE("<none>")); 53 fInputMenu->SetLabelFromMarked(true); 54 BMenuField* inputMenuField = new BMenuField("inputMenuField", 55 fIsVideo ? B_TRANSLATE("Video input:") 56 : B_TRANSLATE("Audio input:"), fInputMenu, NULL); 57 58 // output menu 59 fOutputMenu = new BPopUpMenu(B_TRANSLATE("<none>")); 60 fOutputMenu->SetLabelFromMarked(true); 61 BMenuField* outputMenuField = new BMenuField("outputMenuField", 62 fIsVideo ? B_TRANSLATE("Video output:") 63 : B_TRANSLATE("Audio output:"), fOutputMenu, NULL); 64 65 // channel menu (audio only) 66 BMenuField* channelMenuField = NULL; 67 if (!fIsVideo) { 68 fChannelMenu = new BPopUpMenu(B_TRANSLATE("<none>")); 69 fChannelMenu->SetLabelFromMarked(true); 70 channelMenuField = new BMenuField("channelMenuField", 71 B_TRANSLATE("Channel:"), fChannelMenu, NULL); 72 channelMenuField->SetDivider(StringWidth(B_TRANSLATE("Channel:"))+5); 73 } 74 75 BBox* defaultsBox = new BBox("defaults"); 76 defaultsBox->SetLabel(fIsVideo ? B_TRANSLATE("Default nodes") 77 : B_TRANSLATE("Defaults")); 78 79 // put our menus in a BGridView in our BBox, this way, the BBox makes sure 80 // we have are not blocking the label. 81 BGridView* defaultsGridView = new BGridView(); 82 defaultsBox->AddChild(defaultsGridView); 83 84 BGridLayout* defaultsGrid = defaultsGridView->GridLayout(); 85 defaultsGrid->SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING, 86 B_USE_DEFAULT_SPACING); 87 88 BLayoutItem* labelItem = inputMenuField->CreateLabelLayoutItem(); 89 BLayoutItem* menuItem = inputMenuField->CreateMenuBarLayoutItem(); 90 defaultsGrid->AddItem(labelItem, 0, 0, 1, 1); 91 defaultsGrid->AddItem(menuItem, 1, 0, 3, 1); 92 93 int32 outputMenuWidth = 3; 94 if (channelMenuField) { 95 outputMenuWidth = 1; 96 labelItem = channelMenuField->CreateLabelLayoutItem(); 97 menuItem = channelMenuField->CreateMenuBarLayoutItem(); 98 defaultsGrid->AddItem(labelItem, 2, 1, 1, 1); 99 defaultsGrid->AddItem(menuItem, 3, 1, 1, 1); 100 } 101 102 labelItem = outputMenuField->CreateLabelLayoutItem(); 103 menuItem = outputMenuField->CreateMenuBarLayoutItem(); 104 defaultsGrid->AddItem(labelItem, 0, 1, 1, 1); 105 defaultsGrid->AddItem(menuItem, 1, 1, outputMenuWidth, 1); 106 107 108 rgb_color red_color = {222, 32, 33}; 109 fRestartView = new BStringView("restartStringView", 110 B_TRANSLATE("Restart the media server to apply changes.")); 111 fRestartView->SetHighColor(red_color); 112 defaultsBox->AddChild(fRestartView); 113 fRestartView->Hide(); 114 115 // create the realtime box 116 BBox* realtimeBox = new BBox("realtime"); 117 realtimeBox->SetLabel(B_TRANSLATE("Real-time")); 118 119 BMessage* message = new BMessage(ML_ENABLE_REAL_TIME); 120 message->AddBool("isVideo", fIsVideo); 121 fRealtimeCheckBox = new BCheckBox("realtimeCheckBox", 122 fIsVideo ? B_TRANSLATE("Enable real-time video") 123 : B_TRANSLATE("Enable real-time audio"), 124 message); 125 126 uint32 flags; 127 BMediaRoster::Roster()->GetRealtimeFlags(&flags); 128 if (flags & (fIsVideo ? B_MEDIA_REALTIME_VIDEO : B_MEDIA_REALTIME_AUDIO)) 129 fRealtimeCheckBox->SetValue(B_CONTROL_ON); 130 131 BTextView* textView = new BTextView("stringView"); 132 textView->Insert(fIsVideo ? B_TRANSLATE( 133 "Enabling real-time video allows system to " 134 "perform video operations as fast and smoothly as possible. It " 135 "achieves optimum performance by using more RAM." 136 "\n\nOnly enable this feature if you need the lowest latency possible.") 137 : B_TRANSLATE( 138 "Enabling real-time audio allows system to record and play audio " 139 "as fast as possible. It achieves this performance by using more" 140 " CPU and RAM.\n\nOnly enable this feature if you need the lowest" 141 " latency possible.")); 142 143 textView->MakeEditable(false); 144 textView->MakeSelectable(false); 145 textView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 146 147 BGroupLayout* realtimeBoxLayout = new BGroupLayout(B_VERTICAL, 5); 148 realtimeBoxLayout->SetInsets(10,10,10,10); 149 realtimeBox->SetLayout(realtimeBoxLayout); 150 151 realtimeBoxLayout->AddItem(BSpaceLayoutItem::CreateVerticalStrut(5)); 152 realtimeBoxLayout->AddView(fRealtimeCheckBox); 153 realtimeBoxLayout->AddView(textView); 154 155 // create the bottom line: volume in deskbar checkbox and restart button 156 BGroupView* bottomView = new BGroupView(B_HORIZONTAL); 157 BButton* restartButton = new BButton("restartButton", 158 B_TRANSLATE("Restart media services"), 159 new BMessage(ML_RESTART_MEDIA_SERVER)); 160 161 if (!fIsVideo) { 162 fVolumeCheckBox = new BCheckBox("volumeCheckBox", 163 B_TRANSLATE("Show volume control on Deskbar"), 164 new BMessage(ML_SHOW_VOLUME_CONTROL)); 165 bottomView->GroupLayout()->AddView(fVolumeCheckBox); 166 if (BDeskbar().HasItem("MediaReplicant")) 167 fVolumeCheckBox->SetValue(B_CONTROL_ON); 168 } 169 else{ 170 bottomView->GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue()); 171 } 172 bottomView->GroupLayout()->AddView(restartButton); 173 174 // compose all stuff 175 BGroupLayout* rootlayout = new BGroupLayout(B_VERTICAL, 5); 176 SetLayout(rootlayout); 177 178 rootlayout->AddView(defaultsBox); 179 rootlayout->AddView(realtimeBox); 180 rootlayout->AddView(bottomView); 181 } 182 183 184 void 185 SettingsView::AddNodes(NodeList& list, bool isInput) 186 { 187 BMenu* menu = isInput ? fInputMenu : fOutputMenu; 188 189 for (BMenuItem* item; (item = menu->RemoveItem((int32)0)) != NULL;) 190 delete item; 191 192 BMessage message(ML_DEFAULT_CHANGE); 193 message.AddBool("isVideo", fIsVideo); 194 message.AddBool("isInput", isInput); 195 196 for (int32 i = 0; i < list.CountItems(); i++) { 197 dormant_node_info* info = list.ItemAt(i); 198 menu->AddItem(new SettingsItem(info, new BMessage(message))); 199 } 200 } 201 202 203 void 204 SettingsView::SetDefault(dormant_node_info &info, bool isInput, int32 outputID) 205 { 206 BMenu* menu = isInput ? fInputMenu : fOutputMenu; 207 208 for (int32 i = 0; i < menu->CountItems(); i++) { 209 SettingsItem* item = static_cast<SettingsItem*>(menu->ItemAt(i)); 210 if (item->fInfo && item->fInfo->addon == info.addon 211 && item->fInfo->flavor_id == info.flavor_id) { 212 item->SetMarked(true); 213 break; 214 } 215 } 216 217 if (!fIsVideo && !isInput && outputID >= 0) { 218 BMenuItem* item; 219 while ((item = fChannelMenu->RemoveItem((int32)0)) != NULL) 220 delete item; 221 222 BMediaRoster* roster = BMediaRoster::Roster(); 223 media_node node; 224 media_node_id node_id; 225 status_t err; 226 if (roster->GetInstancesFor(info.addon, info.flavor_id, 227 &node_id) != B_OK) { 228 err = roster->InstantiateDormantNode(info, &node, 229 B_FLAVOR_IS_GLOBAL); 230 } else { 231 err = roster->GetNodeFor(node_id, &node); 232 } 233 234 if (err == B_OK) { 235 media_input inputs[16]; 236 int32 inputCount = 16; 237 if (roster->GetAllInputsFor(node, inputs, 16, &inputCount)==B_OK) { 238 BMessage message(ML_DEFAULTOUTPUT_CHANGE); 239 240 for (int32 i = 0; i < inputCount; i++) { 241 media_input* input = new media_input(); 242 memcpy(input, &inputs[i], sizeof(*input)); 243 item = new Settings2Item(&info, input, 244 new BMessage(message)); 245 fChannelMenu->AddItem(item); 246 if (inputs[i].destination.id == outputID) 247 item->SetMarked(true); 248 } 249 } 250 } 251 } 252 } 253 254 255 SettingsItem::SettingsItem(dormant_node_info* info, BMessage* message, 256 char shortcut, uint32 modifiers) 257 : 258 BMenuItem(info->name, message, shortcut, modifiers), 259 fInfo(info) 260 { 261 262 } 263 264 265 status_t 266 SettingsItem::Invoke(BMessage* message) 267 { 268 if (IsMarked()) 269 return B_OK; 270 return BMenuItem::Invoke(message); 271 } 272 273 274 Settings2Item::Settings2Item(dormant_node_info* info, media_input* input, 275 BMessage* message, char shortcut, uint32 modifiers) 276 : 277 BMenuItem(input->name, message, shortcut, modifiers), 278 fInfo(info), 279 fInput(input) 280 { 281 } 282 283 284 Settings2Item::~Settings2Item() 285 { 286 delete fInput; 287 } 288 289 290 status_t 291 Settings2Item::Invoke(BMessage* message) 292 { 293 if (IsMarked()) 294 return B_OK; 295 return BMenuItem::Invoke(message); 296 } 297 298