1 /* 2 * Copyright 2014-2016, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include "MidiSettingsView.h" 7 8 #include <MidiSettings.h> 9 10 #include <Box.h> 11 #include <Catalog.h> 12 #include <Directory.h> 13 #include <Entry.h> 14 #include <FindDirectory.h> 15 #include <GridView.h> 16 #include <LayoutBuilder.h> 17 #include <ListView.h> 18 #include <Locale.h> 19 #include <Node.h> 20 #include <NodeInfo.h> 21 #include <NodeMonitor.h> 22 #include <Path.h> 23 #include <PathFinder.h> 24 #include <ScrollView.h> 25 #include <StringList.h> 26 #include <StringView.h> 27 28 #include <stdio.h> 29 30 31 #undef B_TRANSLATION_CONTEXT 32 #define B_TRANSLATION_CONTEXT "Midi View" 33 34 const static uint32 kSelectSoundFont = 'SeSf'; 35 const static uint32 kDoubleClick = 'DClk'; 36 37 38 MidiSettingsView::MidiSettingsView() 39 : 40 SettingsView() 41 { 42 BBox* defaultsBox = new BBox("SoundFonts"); 43 defaultsBox->SetLabel(B_TRANSLATE("SoundFonts")); 44 BGridView* defaultsGridView = new BGridView(); 45 46 fListView = new BListView(B_SINGLE_SELECTION_LIST); 47 fListView->SetSelectionMessage(new BMessage(kSelectSoundFont)); 48 fListView->SetInvocationMessage(new BMessage(kDoubleClick)); 49 50 BScrollView* scrollView = new BScrollView("ScrollView", fListView, 51 0, false, true); 52 BLayoutBuilder::Grid<>(defaultsGridView) 53 .SetInsets(B_USE_DEFAULT_SPACING, 0, B_USE_DEFAULT_SPACING, 54 B_USE_DEFAULT_SPACING) 55 .Add(scrollView, 0, 0); 56 57 defaultsBox->AddChild(defaultsGridView); 58 fSoundFontStatus = new BStringView("SoundFontStatus", ""); 59 60 BLayoutBuilder::Group<>(this) 61 .SetInsets(0, 0, 0, 0) 62 .Add(defaultsBox) 63 .AddGroup(B_HORIZONTAL) 64 .AddGlue() 65 .Add(fSoundFontStatus) 66 .AddGlue() 67 .End() 68 .AddGlue(); 69 } 70 71 72 /* virtual */ 73 void 74 MidiSettingsView::AttachedToWindow() 75 { 76 SettingsView::AttachedToWindow(); 77 78 fListView->SetTarget(this); 79 _LoadSettings(); 80 _RetrieveSoundFontList(); 81 _SelectActiveSoundFont(); 82 _UpdateSoundFontStatus(); 83 _WatchFolders(); 84 } 85 86 87 /* virtual */ 88 void 89 MidiSettingsView::DetachedFromWindow() 90 { 91 SettingsView::DetachedFromWindow(); 92 93 stop_watching(this); 94 } 95 96 97 /* virtual */ 98 void 99 MidiSettingsView::MessageReceived(BMessage* message) 100 { 101 switch (message->what) { 102 case B_NODE_MONITOR: 103 { 104 int32 selected = fListView->CurrentSelection(); 105 BStringItem* olditem = (BStringItem*)fListView->ItemAt(selected); 106 107 _RetrieveSoundFontList(); 108 109 int32 count = fListView->CountItems(); 110 if (count == 1) { 111 fListView->Select(0); 112 _SaveSettings(); 113 } else if (olditem != NULL) { 114 for (int32 i = 0; i < fListView->CountItems(); i++) { 115 BStringItem* item = (BStringItem*)fListView->ItemAt(i); 116 if (!strcmp(item->Text(), olditem->Text())) { 117 fListView->Select(i); 118 break; 119 } 120 } 121 } 122 _UpdateSoundFontStatus(); 123 break; 124 } 125 case kSelectSoundFont: 126 { 127 int selection = fListView->CurrentSelection(); 128 if (selection < 0) 129 _SelectActiveSoundFont(); 130 else 131 _SaveSettings(); 132 133 _UpdateSoundFontStatus(); 134 break; 135 } 136 case kDoubleClick: 137 { 138 int selection = fListView->CurrentSelection(); 139 BStringItem* item = (BStringItem*)fListView->ItemAt(selection); 140 141 BEntry entry(item->Text()); 142 BEntry parent; 143 entry.GetParent(&parent); 144 entry_ref folderRef; 145 parent.GetRef(&folderRef); 146 BMessenger msgr("application/x-vnd.Be-TRAK"); 147 BMessage refMsg(B_REFS_RECEIVED); 148 refMsg.AddRef("refs",&folderRef); 149 msgr.SendMessage(&refMsg); 150 break; 151 } 152 153 default: 154 SettingsView::MessageReceived(message); 155 break; 156 } 157 } 158 159 160 void 161 MidiSettingsView::_RetrieveSoundFontList() 162 { 163 // TODO: Duplicated code between here 164 // and BSoftSynth::SetDefaultInstrumentsFile 165 BStringList paths; 166 status_t status = BPathFinder::FindPaths(B_FIND_PATH_DATA_DIRECTORY, 167 "synth", paths); 168 if (status != B_OK) 169 return; 170 171 fListView->MakeEmpty(); 172 173 for (int32 i = 0; i < paths.CountStrings(); i++) { 174 BDirectory directory(paths.StringAt(i).String()); 175 BEntry entry; 176 if (directory.InitCheck() != B_OK) 177 continue; 178 while (directory.GetNextEntry(&entry) == B_OK) { 179 BNode node(&entry); 180 BNodeInfo nodeInfo(&node); 181 char mimeType[B_MIME_TYPE_LENGTH]; 182 // TODO: For some reason the mimetype check fails. 183 // maybe because the file hasn't yet been sniffed and recognized? 184 if (nodeInfo.GetType(mimeType) == B_OK 185 /*&& !strcmp(mimeType, "audio/x-soundfont")*/) { 186 BPath fullPath = paths.StringAt(i).String(); 187 fullPath.Append(entry.Name()); 188 fListView->AddItem(new BStringItem(fullPath.Path())); 189 } 190 } 191 } 192 } 193 194 195 void 196 MidiSettingsView::_LoadSettings() 197 { 198 struct BPrivate::midi_settings settings; 199 if (BPrivate::read_midi_settings(&settings) == B_OK) 200 fActiveSoundFont = new BString(settings.soundfont_file); 201 } 202 203 204 void 205 MidiSettingsView::_SaveSettings() 206 { 207 fActiveSoundFont = new BString(_SelectedSoundFont()); 208 if (fActiveSoundFont->Length() > 0) { 209 struct BPrivate::midi_settings settings; 210 strlcpy(settings.soundfont_file, fActiveSoundFont->String(), 211 sizeof(settings.soundfont_file)); 212 BPrivate::write_midi_settings(settings); 213 } 214 } 215 216 217 void 218 MidiSettingsView::_SelectActiveSoundFont() 219 { 220 int32 count = fListView->CountItems(); 221 if (count == 1) { 222 fListView->Select(0); 223 _SaveSettings(); 224 return; 225 } 226 for (int32 i = 0; i < fListView->CountItems(); i++) { 227 BStringItem* item = (BStringItem*)fListView->ItemAt(i); 228 if (!strcmp(item->Text(), fActiveSoundFont->String())) { 229 fListView->Select(i); 230 break; 231 } 232 } 233 } 234 235 236 BString 237 MidiSettingsView::_SelectedSoundFont() const 238 { 239 BString string; 240 int32 selection = fListView->CurrentSelection(); 241 if (selection >= 0) { 242 BStringItem* item = (BStringItem*)fListView->ItemAt(selection); 243 if (item != NULL) 244 string = item->Text(); 245 } 246 247 return string; 248 } 249 250 251 void 252 MidiSettingsView::_UpdateSoundFontStatus() 253 { 254 if (fListView->IsEmpty()) { 255 fSoundFontStatus->SetText( 256 B_TRANSLATE("There are no SoundFont installed.")); 257 return; 258 } 259 int32 selection = fListView->CurrentSelection(); 260 if (selection < 0) { 261 fSoundFontStatus->SetText( 262 B_TRANSLATE("Please select a SoundFont.")); 263 return; 264 } 265 fSoundFontStatus->SetText(""); 266 } 267 268 269 void 270 MidiSettingsView::_WatchFolders() 271 { 272 BStringList paths; 273 BPathFinder().FindPaths(B_FIND_PATH_DATA_DIRECTORY, "synth", paths); 274 for (int32 i = 0; i < paths.CountStrings(); i++) { 275 BEntry entry(paths.StringAt(i)); 276 node_ref nref; 277 entry.GetNodeRef(&nref); 278 279 watch_node(&nref, B_WATCH_ALL, this); 280 } 281 } 282