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