xref: /haiku/src/add-ons/media/media-add-ons/multi_audio/MultiAudioAddOn.cpp (revision d5cd5d63ff0ad395989db6cf4841a64d5b545d1d)
1 /*
2  * multiaudio replacement media addon for BeOS
3  *
4  * Copyright (c) 2002, Jerome Duval (jerome.duval@free.fr)
5  *
6  * All rights reserved.
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted provided that the following conditions are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright notice,
13  *   this list of conditions and the following disclaimer in the documentation
14  *   and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 #include <MediaDefs.h>
29 #include <MediaAddOn.h>
30 #include <Errors.h>
31 #include <Node.h>
32 #include <Mime.h>
33 #include <StorageDefs.h>
34 #include <Path.h>
35 #include <Directory.h>
36 #include <Entry.h>
37 #include <FindDirectory.h>
38 
39 #include "MultiAudioNode.h"
40 #include "MultiAudioAddOn.h"
41 #include "MultiAudioDevice.h"
42 
43 #include <limits.h>
44 #include <stdio.h>
45 #include <string.h>
46 
47 #include "debug.h"
48 
49 #define MULTI_SAVE
50 
51 // instantiation function
52 extern "C" _EXPORT BMediaAddOn * make_media_addon(image_id image) {
53 	CALLED();
54 	return new MultiAudioAddOn(image);
55 }
56 
57 // -------------------------------------------------------- //
58 // ctor/dtor
59 // -------------------------------------------------------- //
60 
61 MultiAudioAddOn::~MultiAudioAddOn()
62 {
63 	CALLED();
64 
65 	void *device = NULL;
66 	for ( int32 i = 0; (device = fDevices.ItemAt(i)); i++ )
67 		delete device;
68 
69 	SaveSettings();
70 }
71 
72 MultiAudioAddOn::MultiAudioAddOn(image_id image) :
73 	BMediaAddOn(image),
74 	fDevices()
75 {
76 	CALLED();
77 	fInitCheckStatus = B_NO_INIT;
78 
79 	if(RecursiveScan("/dev/audio/multi/")!=B_OK)
80 		return;
81 
82 	LoadSettings();
83 
84 	fInitCheckStatus = B_OK;
85 }
86 
87 // -------------------------------------------------------- //
88 // BMediaAddOn impl
89 // -------------------------------------------------------- //
90 
91 status_t MultiAudioAddOn::InitCheck(
92 	const char ** out_failure_text)
93 {
94 	CALLED();
95 	return B_OK;
96 }
97 
98 int32 MultiAudioAddOn::CountFlavors()
99 {
100 	CALLED();
101 	return fDevices.CountItems();
102 }
103 
104 status_t MultiAudioAddOn::GetFlavorAt(
105 	int32 n,
106 	const flavor_info ** out_info)
107 {
108 	CALLED();
109 	if (out_info == 0) {
110 		fprintf(stderr,"<- B_BAD_VALUE\n");
111 		return B_BAD_VALUE; // we refuse to crash because you were stupid
112 	}
113 	if (n < 0 || n > fDevices.CountItems() - 1) {
114 		fprintf(stderr,"<- B_BAD_INDEX\n");
115 		return B_BAD_INDEX;
116 	}
117 
118 	MultiAudioDevice *device = (MultiAudioDevice *) fDevices.ItemAt(n);
119 
120 	flavor_info * infos = new flavor_info[1];
121 	MultiAudioNode::GetFlavor(&infos[0], n);
122 	infos[0].name = device->MD.friendly_name;
123 	(*out_info) = infos;
124 	return B_OK;
125 }
126 
127 BMediaNode * MultiAudioAddOn::InstantiateNodeFor(
128 				const flavor_info * info,
129 				BMessage * config,
130 				status_t * out_error)
131 {
132 	CALLED();
133 	if (out_error == 0) {
134 		fprintf(stderr,"<- NULL\n");
135 		return 0; // we refuse to crash because you were stupid
136 	}
137 
138 	MultiAudioDevice *device = (MultiAudioDevice*)fDevices.ItemAt(info->internal_id);
139 	if(device == NULL) {
140 		*out_error = B_ERROR;
141 		return NULL;
142 	}
143 
144 #ifdef MULTI_SAVE
145 	if(fSettings.FindMessage(device->MD.friendly_name, config)==B_OK) {
146 		fSettings.RemoveData(device->MD.friendly_name);
147 	}
148 #endif
149 
150 	MultiAudioNode * node
151 		= new MultiAudioNode(this,
152 						  device->MD.friendly_name,
153 						  device,
154 						  info->internal_id,
155 						  config);
156 	if (node == 0) {
157 		*out_error = B_NO_MEMORY;
158 		fprintf(stderr,"<- B_NO_MEMORY\n");
159 	} else {
160 		*out_error = node->InitCheck();
161 	}
162 	return node;
163 }
164 
165 status_t
166 MultiAudioAddOn::GetConfigurationFor(BMediaNode * your_node, BMessage * into_message)
167 {
168 	CALLED();
169 #ifdef MULTI_SAVE
170 	if (into_message == 0) {
171 		into_message = new BMessage();
172 		MultiAudioNode * node = dynamic_cast<MultiAudioNode*>(your_node);
173 		if (node == 0) {
174 			fprintf(stderr,"<- B_BAD_TYPE\n");
175 			return B_BAD_TYPE;
176 		}
177 		if(node->GetConfigurationFor(into_message)==B_OK) {
178 			fSettings.AddMessage(your_node->Name(), into_message);
179 		}
180 		return B_OK;
181 	}
182 #endif
183 	// currently never called by the media kit. Seems it is not implemented.
184 	if (into_message == 0) {
185 		fprintf(stderr,"<- B_BAD_VALUE\n");
186 		return B_BAD_VALUE; // we refuse to crash because you were stupid
187 	}
188 	MultiAudioNode * node = dynamic_cast<MultiAudioNode*>(your_node);
189 	if (node == 0) {
190 		fprintf(stderr,"<- B_BAD_TYPE\n");
191 		return B_BAD_TYPE;
192 	}
193 	return node->GetConfigurationFor(into_message);
194 }
195 
196 
197 bool MultiAudioAddOn::WantsAutoStart()
198 {
199 	CALLED();
200 	return false;
201 }
202 
203 status_t MultiAudioAddOn::AutoStart(
204 				int in_count,
205 				BMediaNode ** out_node,
206 				int32 * out_internal_id,
207 				bool * out_has_more)
208 {
209 	CALLED();
210 	return B_OK;
211 }
212 
213 status_t
214 MultiAudioAddOn::RecursiveScan(char* rootPath, BEntry *rootEntry = NULL)
215 {
216 	CALLED();
217 
218 	BDirectory root;
219 	if(rootEntry!=NULL)
220 		root.SetTo(rootEntry);
221 	else if(rootPath!=NULL) {
222 		root.SetTo(rootPath);
223 	} else {
224 		PRINT(("Error in MultiAudioAddOn::RecursiveScan null params\n"));
225 		return B_ERROR;
226 	}
227 
228 	BEntry entry;
229 
230 	while(root.GetNextEntry(&entry) > B_ERROR) {
231 
232 		if(entry.IsDirectory()) {
233 			RecursiveScan(rootPath, &entry);
234 		} else {
235 			BPath path;
236 			entry.GetPath(&path);
237 			MultiAudioDevice *device = new MultiAudioDevice(path.Path() + strlen(rootPath), path.Path());
238 			if(device && device->InitCheck() == B_OK)
239 				fDevices.AddItem(device);
240 		}
241 	}
242 
243 	return B_OK;
244 }
245 
246 
247 void
248 MultiAudioAddOn::SaveSettings(void)
249 {
250 	CALLED();
251 	BPath path;
252 	if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
253 		path.Append(SETTINGS_FILE);
254 		BFile file(path.Path(),B_READ_WRITE|B_CREATE_FILE|B_ERASE_FILE);
255 		if(file.InitCheck()==B_OK)
256 			fSettings.Flatten(&file);
257 	}
258 }
259 
260 
261 void
262 MultiAudioAddOn::LoadSettings(void)
263 {
264 	CALLED();
265 	fSettings.MakeEmpty();
266 
267 	BPath path;
268 	if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
269 		path.Append(SETTINGS_FILE);
270 		BFile file(path.Path(),B_READ_ONLY);
271 		if((file.InitCheck()==B_OK)&&(fSettings.Unflatten(&file)==B_OK))
272 		{
273 			PRINT_OBJECT(fSettings);
274 		} else {
275 			PRINT(("Error unflattening settings file %s\n",path.Path()));
276 		}
277 	}
278 }