1#include <support/Autolock.h>
2#include <media/MediaDefs.h>
3
4#include <stdio.h>
5#include <string.h>
6#include <unistd.h>
7
8#include <media/MediaAddOn.h>
9
10#include <Autolock.h>
11#include <Directory.h>
12#include <Entry.h>
13#include <Path.h>
14#include <String.h>
15
16
17#include "LegacyMediaAddOn.h"
18
19#include "LegacyAudioConsumer.h"
20#include "LegacyAudioProducer.h"
21
22#define LEGACY_DEVICE_PATH_BASE "/dev/audio/old"
23
24LegacyMediaAddOn::LegacyMediaAddOn( image_id imid )
25	: BMediaAddOn( imid )
26	, fInternalIds( 0 )
27	, fListsLock( "LegacyMediaAddOn:ListLock" )
28{
29	fInitStatus = B_NO_INIT;
30
31	fMediaFormat.type = B_MEDIA_RAW_AUDIO;
32	fMediaFormat.u.raw_audio = media_raw_audio_format::wildcard;
33
34	fInitStatus = RecursiveScanForDevices();
35	//consumer = new LegacyAudioConsumer( this, "ymf744/1", 0 );
36	//producer = new LegacyAudioProducer( "maestro2/1" );
37
38}
39
40
41LegacyMediaAddOn::~LegacyMediaAddOn()
42{
43	//delete consumer;
44	//delete producer;
45	LegacyDevice *dev;
46	while ((dev = (LegacyDevice *)fConsumers.RemoveItem((int32)0))) {
47		delete dev->consumer;
48		//delete dev->producer;
49		delete dev;
50	}
51	while ((dev = (LegacyDevice *)fProducers.RemoveItem((int32)0))) {
52		//delete dev->consumer;
53		//delete dev->producer;
54		delete dev;
55	}
56
57
58}
59
60
61status_t
62LegacyMediaAddOn::InitCheck( const char **out_failure_text )
63{
64	return fInitStatus;
65}
66
67
68int32
69LegacyMediaAddOn::CountFlavors()
70{
71	int32 count;
72	BAutolock al(fListsLock);
73
74	count = fConsumers.CountItems() + fProducers.CountItems();
75	return count;
76}
77
78
79status_t
80LegacyMediaAddOn::GetFlavorAt( int32 n, const flavor_info **out_info )
81{
82	BAutolock al(fListsLock);
83	LegacyDevice *dev;
84	if (n < 0)
85		return EINVAL;
86	for (n = fConsumers.CountItems() - 1; n >= 0; n--) {
87		dev = (LegacyDevice *)fConsumers.ItemAt(n);
88		if (dev->flavor.internal_id != n)
89			continue;
90		*out_info = &dev->flavor;
91		return B_OK;
92	}
93	for (n = fProducers.CountItems() - 1; n >= 0; n--) {
94		dev = (LegacyDevice *)fProducers.ItemAt(n);
95		if (dev->flavor.internal_id != n)
96			continue;
97		*out_info = &dev->flavor;
98		return B_OK;
99	}
100	return B_ERROR;
101}
102
103
104BMediaNode *
105LegacyMediaAddOn::InstantiateNodeFor( const flavor_info *info, BMessage *config, status_t *out_error )
106{
107	BAutolock al(fListsLock);
108	LegacyDevice *dev;
109	int32 n;
110	int32 consumerCount = fConsumers.CountItems();
111	for (n = consumerCount - 1; n >= 0; n--) {
112		dev = (LegacyDevice *)fConsumers.ItemAt(n);
113		//if (info != &dev->flavor) // XXX memcmp?
114		if (info->internal_id != dev->flavor.internal_id)
115			continue;
116		if (dev->inuse) // EBUSY!
117			return NULL;
118		dev->consumer = new LegacyAudioConsumer( this, dev->name.String(), n );
119		if (!dev->consumer)
120			return NULL;
121		dev->inuse = true;
122		return dev->consumer;
123	}
124/*
125	for (n = fProducers.CountItems() - 1; n >= 0; n--) {
126		dev = (LegacyDevice *)fProducers.ItemAt(n);
127		if (info != &dev->flavor) // XXX memcmp?
128			continue;
129		if (dev->inuse) // EBUSY!
130			return NULL;
131		dev->producer = new LegacyAudioProducer( this, dev->name.String(), consumerCount + n );
132		if (!dev->producer)
133			return NULL;
134		dev->inuse = true;
135		return dev->producer;
136	}
137*/
138	return NULL;
139}
140
141status_t
142LegacyMediaAddOn::RecursiveScanForDevices(const char *path)
143{
144	BDirectory d(path ? path : LEGACY_DEVICE_PATH_BASE);
145	if (d.InitCheck() < B_OK)
146		return d.InitCheck();
147	BEntry ent;
148	while (d.GetNextEntry(&ent) == B_OK) {
149		struct stat st;
150		char name[B_FILE_NAME_LENGTH];
151		ent.GetName(name);
152		if (d.GetStatFor(name, &st) < 0)
153			continue;
154		BPath p(&ent);
155		// we're only interested in folders...
156		if (S_ISDIR(st.st_mode)) {
157			RecursiveScanForDevices(p.Path());
158			// discard error
159			continue;
160		}
161		// and (char) devices
162		if (!S_ISCHR(st.st_mode))
163			continue;
164
165		// we want relative path
166		BString s(p.Path());
167		s.RemoveFirst(LEGACY_DEVICE_PATH_BASE"/");
168
169		// XXX: should check first for consumer or producer...
170		LegacyDevice *dev = new LegacyDevice;
171		dev->name = s.String();
172		dev->flavor.name = (char *)/*WTF*/dev->name.String();
173		dev->flavor.info = (char *)dev->name.String();
174		dev->flavor.kinds = B_BUFFER_CONSUMER | /*B_CONTROLLABLE |*/ B_PHYSICAL_OUTPUT;
175		dev->flavor.flavor_flags = 0; //B_FLAVOR_IS_GLOBAL;
176		dev->flavor.internal_id = fInternalIds++;
177		dev->flavor.possible_count = 1;
178		dev->flavor.in_format_count = 1;
179		dev->flavor.in_format_flags = 0;
180		dev->flavor.in_formats = &fMediaFormat;
181		dev->flavor.out_format_count = 0;
182		dev->flavor.out_format_flags = 0;
183		dev->flavor.out_formats = NULL;
184		dev->inuse = false;
185		dev->consumer = NULL;
186		//dev->producer = NULL;
187		fConsumers.AddItem((void *)dev);
188		//XXX: only cons for now
189		//fProducers.AddItem(s.String());
190	}
191	return B_OK;
192}
193
194#if 0
195
196struct flavor_info {
197        char *                          name;
198        char *                          info;
199        uint64                          kinds;                  /* node_kind */
200        uint32                          flavor_flags;
201        int32                           internal_id;    /* For BMediaAddOn internal use */
202        int32                           possible_count; /* 0 for "any number" */
203
204        int32                           in_format_count;        /* for BufferConsumer kinds */
205        uint32                          in_format_flags;        /* set to 0 */
206        const media_format *    in_formats;
207
208        int32                           out_format_count;       /* for BufferProducer kinds */
209        uint32                          out_format_flags;       /* set to 0 */
210        const media_format *    out_formats;
211
212        uint32                          _reserved_[16];
213
214private:
215        flavor_info & operator=(const flavor_info & other);
216};
217#endif
218
219
220BMediaAddOn *
221make_media_addon( image_id imid )
222{
223	return new LegacyMediaAddOn( imid );
224}
225