GCC suport for Objective-C [Was: NSSound Reimplementation]

2009-07-18 Thread Fred Kiefer
David Chisnall schrieb:
 On 16 Jul 2009, at 18:34, Riccardo Mottola wrote:
 Sorry, I just haven't had a chance to look at installing a
 new/different compiler and working with that yet, though it really IS
 something I'd like to be playing with.

 However, it doesn't really have any bearing on this issue because we
 have to develop code for the existing compiler and will need to do so
 as long as we continue to support it (gcc).

 Yes, I remember a caveat: that was it, no gcc support. As a GNU
 project I'd be quite waey to drop gcc support.
 
 As a GNU project, I'd hope that the GNU compiler collection would put
 some effort into supporting us!  Someone at Apple sent them patches for
 supporting declared properties over a year ago, and yet GCC still does
 not support any of the extensions added in OS X 10.5, which was released
 two years ago.
 
 Snow Leopard is going to make heavy use of blocks and declared
 properties in the API, and if we want to remain compatible, we are going
 to need a compiler that supports these.  It would be really great if GCC
 would, but I have yet to see any evidence that anyone is still actively
 working on Objective-C support in GCC.  In the last two years, Clang has
 gone from having no Objective-C support to supporting most of
 Objective-C 2 on the GNU runtime, while GCC has not gained a single new
 Objective-C feature.

David,

your mail got me thinking, I wont switch to Clang and I don't hope
GNUstep as a project will. So the only option forward is to start
working on better Objective-C support in gcc. I surely wont have time
for this beside my maintainer task on GNUstep, but this seems currently
the more important task. I will have a look at the code in gcc that
supports Objective-C and if I am able to make any sense of it, I might
switch over to work on that.

Cheers
Fred


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: GCC suport for Objective-C [Was: NSSound Reimplementation]

2009-07-18 Thread David Chisnall

Hi Fred,

On 18 Jul 2009, at 19:23, Fred Kiefer wrote:


your mail got me thinking, I wont switch to Clang and I don't hope
GNUstep as a project will. So the only option forward is to start
working on better Objective-C support in gcc. I surely wont have time
for this beside my maintainer task on GNUstep, but this seems  
currently

the more important task. I will have a look at the code in gcc that
supports Objective-C and if I am able to make any sense of it, I might
switch over to work on that.


That would be great.  It's not a task for the faint hearted though.   
You can find all of the GCC Objective-C code in this file:


http://gcc.gnu.org/viewcvs/trunk/gcc/objc/objc-act.c?revision=149722view=markup

There seem to be two functions in this file related to ivar access /  
assignment, so it ought to be relatively easy for anyone familiar with  
GCC internals to add non-fragile ivar support.  You also need to  
modify the ivar structure initialiser to contain negative values for  
the offsets (this is the hint I give to the runtime to indicate that  
this compilation unit provides support for non-fragile ivars and needs  
the offsets updated accordingly).


David


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-17 Thread Jamie Ramone
On Thu, Jul 16, 2009 at 10:37 AM, David Chisnallthera...@sucs.org wrote:
 On 16 Jul 2009, at 14:23, Jamie Ramone wrote:

 I'd like to chime in here and say that this approach IS actually a
 good idea as :

 1 ) it does solve the ABI change breakdown problem and

 Except that it doesn't, it just hides it.  Now people subclassing and
 referencing variables in the superclass need to explicitly cast a pointer to
 a structure.  If this structure changes, they need to manually update their
 private copy of the ivars and if they don't thing break in exciting ways.

 2 ) it is actually much easier to read because it's a prime example of
 encapsulation and abstraction, so complexity is hidden.

 It is not easier to read, because now you need a separate structure
 definition, every ivar access has to go via a macro which will look
 something like this:

 #define ivar (((struct private_ivars*)_private)-ivar)

 In no possible way is that clearer code.

 So locality of reference is gone. It gets replaced by messaging an
 object. OK. So what? Why depend on locality? Again, I'm hard pressed
 to find an objective way to choose one over the other. If the API of
 the messaged object is well defined then I find both forms of the code
 to be equally understandable. But that's my opinion, some may agree
 and others disagree. So this reasoning is also a bad one for judging
 the approach.

 Clearly you have no idea what locality of reference means.  See here:

 http://en.wikipedia.org/wiki/Locality_of_reference

 In summary, for good performance you want data that is accessed together to
 be close together in memory.  Both CPUs (via their cache architecture) and
 operating systems (via their paging strategy) optimise heavily for this
 case.

 Having ivars dangled off on a separate structure means that we now need two
 cache lines per object instead of one.  Actually, it's worse if you also
 factor in subclasses doing this because you need one cache line for the
 object and one for each of the subclass structures.  This will increase
 cache churn considerably.  This is very difficult to identify in a
 microbenchmark, but it affect performance in larger programs quite
 noticeably.  These structures, being separately allocated and of different
 sizes, may well be on different pages meaning that you will end up with a
 lot of more swapping when you are low on memory, which completely cripples
 performance.

 The correct solution is to declare no ivars other than ones you are willing
 to commit to maintaining in the future in the header, declare them all in
 the implementation file, and use non-fragile ivar support in the runtime,
 but this requires people to actually test my patch which adds this.

 At the very least, we should just add an unused pointer for future expansion
 so that we can add new ivars later and not use this for ivars that are
 likely to remain stable for several releases.

 David


I see where you were going, sorry for the mix-up. I do understand what
locality means, I just thought you were talking about scope. My bad,
just an honest mistake so don't have a cow man :-P

Now, if the compiler optimized in such a way that small enough ivars
are packed together as one single piece of data, and the needed one is
accessed once loaded into a register then there would be a locality
problem by separating them. If not, the cache use increases by one
piece of data: the pointer to the object. The individual fields would
be accessed separately anyway in this case, whether whitin the object
or in two separate ones. So there is an increase it is only limited to
the ammount of different classes using the approach.

You say there's a problem if subclasses do the same, but that wouldn't
happen. The separate object for containing the ivars would only be in
the public classes of the library in question. There's no reason for a
programmer who makes use of that library to do so in any subclass,
except maby in those subclasses that are part of some other api API
and it's implementation is based on the former.

Now, one could optimize it by moving ivars up the hierarchy. But if
the superclasses are also public the ABI would break, and on the other
ones (non-public ones) the risk of having potentialy usless ivars,
thus increasing memory usage.

If the separate-object is used as proposed (not with the
non-optimization previously pointed out), the object's creation could
be delayed until one of those ivar's are needed i.e. a lazy approach.
This way the memory usage is minimal, as far as this aproach allows.

That macro puzzles me. Why would you have a macro to access and ivar
that way? Because if the code is a method then it is accessed as if it
were a global variable. If not then you should use an accessor method.
Trying to access them directly punches a hole in the OOP paradigm. If
you have to, then maybe you shouldn't use an OOP approach at all, but
rather wrap procedural code with an object layer.

Oh, one more thing, could you post a 

Re: NSSound Reimplementation

2009-07-17 Thread Stefan Bidigaray
The discussion seems to have settled a little, so I'll go ahead and ask the
question... what approach should I be taking here?  I really do not have the
know-how to chime in, and because of that will go with whatever is decided.
What Richard did with NSOperations seems easy enough, is that the direction
we're going with?  I'm hearing a lot of stuff but nothing seems to be
definite/written in stone.

David:
It's not that I don't want to try llvm/clang out, it's just that I don't
have time!  Start in September I'll have even less time (starting grad
school).  I'm trying my best to get this code out so I can at least have 1 -
1.5 months of bug hunting until I will be forced into a maintenance mode.
I'd really like to be able to try a lot of this stuff out, but I just can't,
sorry.

Thanks
Stefan
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread Richard Frith-Macdonald


On 28 Jun 2009, at 19:14, Stefan Bidigaray wrote:

As promised, here's the latest code.  Feel free to poke as many  
holes in it as possible.  I'm going to use this, almost completely  
unchanged, for NSSound.m.  The bundle/plug-in stuff will go in 100%  
unchanged.


Sorry that I just haven't found time to look at this.

But ... going back to the issue of avoiding changes to ivars breaking  
ABI in future releases ... the approach I currently favor is having a  
*single* ivar in the public class.  This is a private id variable  
referring to an instance of a private class which is used to hold the  
real ivars.


So the implementation file contains this private class (whose ivars  
are all declared public so that any code in the implementation file  
can access them freely), and the -init and -dealloc methods of the  
public class create/destroy an instance of the private class.  Look at  
the code for NSOperation.m in the current svn trunk version of the  
base library for the simplest example around.






___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread David Chisnall

On 16 Jul 2009, at 09:30, Richard Frith-Macdonald wrote:

But ... going back to the issue of avoiding changes to ivars  
breaking ABI in future releases ... the approach I currently favor  
is having a *single* ivar in the public class.  This is a private id  
variable referring to an instance of a private class which is used  
to hold the real ivars.


I really don't like this approach.  It makes the code difficult to  
read, destroys locality of reference, and hurts performance.


Please, please, please, can other people test my non-fragile ivars  
patch so that we can get rid of ugly hacks like this and just not  
declare any ivars in the headers.  I posted it months ago and have had  
absolutely no reports of testing yet.


David


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread Jamie Ramone
I'd like to chime in here and say that this approach IS actually a
good idea as :

1 ) it does solve the ABI change breakdown problem and

2 ) it is actually much easier to read because it's a prime example of
encapsulation and abstraction, so complexity is hidden.

The use here of encapsulation and abstraction are precisely (among
other reasons) why the object oriented paradigm exists. Leveraging
these concepts allow one to concentrate on a specific problem by
hiding away the details of the rest behind an API, that of the other
objects you're using from within whichever one you're working on. If
the code is hard to read then that api is not well defined, so the
real problem would be to redefine it so as to make it understandable
(read: actually usable). Depending on being able to see all (or most)
of the details at once is not a good idea. Another thing I might add
is that readability is something rather subjective (though there are
generalities like statistics to allow it to be an objective
measurement), so it shouldn't be used to choose or dismiss a program
writing method.

So locality of reference is gone. It gets replaced by messaging an
object. OK. So what? Why depend on locality? Again, I'm hard pressed
to find an objective way to choose one over the other. If the API of
the messaged object is well defined then I find both forms of the code
to be equally understandable. But that's my opinion, some may agree
and others disagree. So this reasoning is also a bad one for judging
the approach.

The performance hurting one I like. This is something that CAN
actually be measured, so it's perfect for considering this approach.
Now, why exactly does it hurt performance? Is the amount lost so much
greater than the amount achieved by the overall algorithm used that it
performs slower than if that algorithm wasn't used? How fast does the
code need to be, minimally? These are the questions one should ask
(and answer) in order to move ahead here.

So I agree with Richard here. However, if no one else changes the code
and you do, and submit a patch as you did, and it does solve the
problems you're looking to solve, then I don't see why your patch
wouldn't be accepted.

-- 
Besos, abrazos, confeti y aplausos.
Jamie Ramone
El Vikingo


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread David Chisnall

On 16 Jul 2009, at 14:23, Jamie Ramone wrote:


I'd like to chime in here and say that this approach IS actually a
good idea as :

1 ) it does solve the ABI change breakdown problem and


Except that it doesn't, it just hides it.  Now people subclassing and  
referencing variables in the superclass need to explicitly cast a  
pointer to a structure.  If this structure changes, they need to  
manually update their private copy of the ivars and if they don't  
thing break in exciting ways.



2 ) it is actually much easier to read because it's a prime example of
encapsulation and abstraction, so complexity is hidden.


It is not easier to read, because now you need a separate structure  
definition, every ivar access has to go via a macro which will look  
something like this:


#define ivar (((struct private_ivars*)_private)-ivar)

In no possible way is that clearer code.


So locality of reference is gone. It gets replaced by messaging an
object. OK. So what? Why depend on locality? Again, I'm hard pressed
to find an objective way to choose one over the other. If the API of
the messaged object is well defined then I find both forms of the code
to be equally understandable. But that's my opinion, some may agree
and others disagree. So this reasoning is also a bad one for judging
the approach.


Clearly you have no idea what locality of reference means.  See here:

http://en.wikipedia.org/wiki/Locality_of_reference

In summary, for good performance you want data that is accessed  
together to be close together in memory.  Both CPUs (via their cache  
architecture) and operating systems (via their paging strategy)  
optimise heavily for this case.


Having ivars dangled off on a separate structure means that we now  
need two cache lines per object instead of one.  Actually, it's worse  
if you also factor in subclasses doing this because you need one cache  
line for the object and one for each of the subclass structures.  This  
will increase cache churn considerably.  This is very difficult to  
identify in a microbenchmark, but it affect performance in larger  
programs quite noticeably.  These structures, being separately  
allocated and of different sizes, may well be on different pages  
meaning that you will end up with a lot of more swapping when you are  
low on memory, which completely cripples performance.


The correct solution is to declare no ivars other than ones you are  
willing to commit to maintaining in the future in the header, declare  
them all in the implementation file, and use non-fragile ivar support  
in the runtime, but this requires people to actually test my patch  
which adds this.


At the very least, we should just add an unused pointer for future  
expansion so that we can add new ivars later and not use this for  
ivars that are likely to remain stable for several releases.


David


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread Richard Frith-Macdonald


On 16 Jul 2009, at 11:24, David Chisnall wrote:


On 16 Jul 2009, at 09:30, Richard Frith-Macdonald wrote:

But ... going back to the issue of avoiding changes to ivars  
breaking ABI in future releases ... the approach I currently favor  
is having a *single* ivar in the public class.  This is a private  
id variable referring to an instance of a private class which is  
used to hold the real ivars.


I really don't like this approach.  It makes the code difficult to  
read, destroys locality of reference, and hurts performance.


Please, please, please, can other people test my non-fragile ivars  
patch so that we can get rid of ugly hacks like this and just not  
declare any ivars in the headers.  I posted it months ago and have  
had absolutely no reports of testing yet.


Sorry, I just haven't had a chance to look at installing a new/ 
different compiler and working with that yet, though it really IS  
something I'd like to be playing with.


However, it doesn't really have any bearing on this issue because we  
have to develop code for the existing compiler and will need to do so  
as long as we continue to support it (gcc).


I honestly can't see gcc being dropped any time soon (in the first  
place we would want all GNUstep to have been working flawlessly with  
clang for a good long time... perhaps a year) before we could  
reasonably think of making Clang the preferred compiler, let alone  
deprecating or removing support for gcc, and in the second place there  
may be political considerations preventing it (though I think most of  
the core developers are less likely to be bothered about that than in  
many free software projects ).


I think we have to live within the limitations of gcc as long as we  
haven't deprecated it.


The nice thing about this particular scheme (a single instance  
variable in the public class pointing to another class containing the  
actual variables) is that it's clean and simple enough to make it  
*very* easy to change if/when we change compilers at a later date.




___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread Richard Frith-Macdonald


On 16 Jul 2009, at 14:37, David Chisnall wrote:


On 16 Jul 2009, at 14:23, Jamie Ramone wrote:


I'd like to chime in here and say that this approach IS actually a
good idea as :

1 ) it does solve the ABI change breakdown problem and


Except that it doesn't, it just hides it.  Now people subclassing  
and referencing variables in the superclass need to explicitly cast  
a pointer to a structure.  If this structure changes, they need to  
manually update their private copy of the ivars and if they don't  
thing break in exciting ways.


No ... people subclassing NEVER reference any variables of the  
superclass, because the superclass only contains a single instance  
variable, and that's declared @private.  Because the superclass only  
ever contains the single instance variable, it never changes with  
impementation details, and the ABI doesn't change.


2 ) it is actually much easier to read because it's a prime example  
of

encapsulation and abstraction, so complexity is hidden.


It is not easier to read, because now you need a separate structure  
definition, every ivar access has to go via a macro which will look  
something like this:


#define ivar (((struct private_ivars*)_private)-ivar)


Actually it's

#define private ((PrivateClass*)_private)

Then

   private-ivar = ...

Which can easily be converted to 'self-ivar' or just 'ivar' by a  
global replace when we want to change because we have non-fragile  
ivars available.




___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread Lars Sonchocky-Helldorf


Am 16.07.2009 um 12:24 schrieb David Chisnall:


On 16 Jul 2009, at 09:30, Richard Frith-Macdonald wrote:

But ... going back to the issue of avoiding changes to ivars  
breaking ABI in future releases ... the approach I currently favor  
is having a *single* ivar in the public class.  This is a private  
id variable referring to an instance of a private class which is  
used to hold the real ivars.


I really don't like this approach.  It makes the code difficult to  
read, destroys locality of reference, and hurts performance.


Please, please, please, can other people test my non-fragile ivars  
patch so that we can get rid of ugly hacks like this and just not  
declare any ivars in the headers.  I posted it months ago and have  
had absolutely no reports of testing yet.


Maybe it's not clear to everybody what benefits your patch  
introduces. So maybe it would be a good idea to give a short  
enumeration of all the gains to the broader public (I know you're  
good at writing technical articles since I read quite a few off  
them :-)).




David


thanks,

Lars


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread Richard Frith-Macdonald


On 16 Jul 2009, at 14:53, Richard Frith-Macdonald wrote:



On 16 Jul 2009, at 14:37, David Chisnall wrote:


On 16 Jul 2009, at 14:23, Jamie Ramone wrote:


I'd like to chime in here and say that this approach IS actually a
good idea as :

1 ) it does solve the ABI change breakdown problem and


Except that it doesn't, it just hides it.  Now people subclassing  
and referencing variables in the superclass need to explicitly cast  
a pointer to a structure.  If this structure changes, they need to  
manually update their private copy of the ivars and if they don't  
thing break in exciting ways.


No ... people subclassing NEVER reference any variables of the  
superclass, because the superclass only contains a single instance  
variable, and that's declared @private.  Because the superclass only  
ever contains the single instance variable, it never changes with  
impementation details, and the ABI doesn't change.


2 ) it is actually much easier to read because it's a prime  
example of

encapsulation and abstraction, so complexity is hidden.


It is not easier to read, because now you need a separate structure  
definition, every ivar access has to go via a macro which will look  
something like this:


#define ivar (((struct private_ivars*)_private)-ivar)


Actually it's

#define private ((PrivateClass*)_private)

Then

  private-ivar = ...

Which can easily be converted to 'self-ivar' or just 'ivar' by a  
global replace when we want to change because we have non-fragile  
ivars available.


Thinking about it, this is actually very short/easy to do with the  
preprocessor to support both gcc and clang (though I think we'd need  
to comment it well) ...


eg.

#if clang
#define private self
@interface  MyClass
{
#else
#define private ((MyClassPrivate*)_private)
@interface  MyClassPrivate : NSObject
{
  @public
#endif
  // instance variables here
}
@end

#if !clang
@implementation MyClassPrivate
@end
#endif

@implementation MyClass
- (id) init
{
#if !clang
  _private = [MyPrivateClass new];
#endif
  // ivar initialisation here
  return self;
}
...
@end

So if we are building with clang then we use non-fragile ivars, but if  
we are building with gcc then we use the private class instance to  
store our ivars.
To make it even simpler when using the same model repeatedly, we could  
use macros and end up writing code like this:


GSBEGINPRIVATEIVARS(MyClass)
int var1;
charvar2;
GSENDPRIVATEIVARS(MyClass)

@implementation MyClass
- (id) init
{
  GSCREATEPRIVATEIVARS(MyClass)
 ...
  return self;
}





___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread David Chisnall

On 16 Jul 2009, at 17:41, Richard Frith-Macdonald wrote:



On 16 Jul 2009, at 14:53, Richard Frith-Macdonald wrote:



On 16 Jul 2009, at 14:37, David Chisnall wrote:


On 16 Jul 2009, at 14:23, Jamie Ramone wrote:


I'd like to chime in here and say that this approach IS actually a
good idea as :

1 ) it does solve the ABI change breakdown problem and


Except that it doesn't, it just hides it.  Now people subclassing  
and referencing variables in the superclass need to explicitly  
cast a pointer to a structure.  If this structure changes, they  
need to manually update their private copy of the ivars and if  
they don't thing break in exciting ways.


No ... people subclassing NEVER reference any variables of the  
superclass, because the superclass only contains a single instance  
variable, and that's declared @private.  Because the superclass  
only ever contains the single instance variable, it never changes  
with impementation details, and the ABI doesn't change.


2 ) it is actually much easier to read because it's a prime  
example of

encapsulation and abstraction, so complexity is hidden.


It is not easier to read, because now you need a separate  
structure definition, every ivar access has to go via a macro  
which will look something like this:


#define ivar (((struct private_ivars*)_private)-ivar)


Actually it's

#define private ((PrivateClass*)_private)

Then

 private-ivar = ...

Which can easily be converted to 'self-ivar' or just 'ivar' by a  
global replace when we want to change because we have non-fragile  
ivars available.


Thinking about it, this is actually very short/easy to do with the  
preprocessor to support both gcc and clang (though I think we'd need  
to comment it well) ...


eg.

#if clang
#define private self
@interface  MyClass
{
#else
#define private ((MyClassPrivate*)_private)
@interface  MyClassPrivate : NSObject
{
 @public
#endif
 // instance variables here
}
@end

#if !clang
@implementation MyClassPrivate
@end
#endif

@implementation MyClass
- (id) init
{
#if !clang
 _private = [MyPrivateClass new];
#endif
 // ivar initialisation here
 return self;
}
...
@end

So if we are building with clang then we use non-fragile ivars, but  
if we are building with gcc then we use the private class instance  
to store our ivars.
To make it even simpler when using the same model repeatedly, we  
could use macros and end up writing code like this:


GSBEGINPRIVATEIVARS(MyClass)
int var1;
charvar2;
GSENDPRIVATEIVARS(MyClass)

@implementation MyClass
- (id) init
{
 GSCREATEPRIVATEIVARS(MyClass)
...
 return self;
}


Looks sensible.  Is anyone interested in adding non-fragile ABI  
support to GCC?  The initial implementation is in clang because GCC  
code hurts my brain, but I'd like to see both compilers support this.


David



___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread David Chisnall

On 16 Jul 2009, at 17:26, Lars Sonchocky-Helldorf wrote:

Maybe it's not clear to everybody what benefits your patch  
introduces. So maybe it would be a good idea to give a short  
enumeration of all the gains to the broader public (I know you're  
good at writing technical articles since I read quite a few off  
them :-)).


As I wrote in my first email, it provides the same benefits as Apple's  
non-fragile ABI:


You can add or re-arrange instance variables in a class without  
breaking the ABI.  You can also remove private instance variables.   
Instance variable offsets are now stored in a global variable, rather  
than being hard-coded, and are set when the class is loaded by the  
runtime.  This needs a small amount of compiler and runtime support.   
The runtime support was in the diff I sent to this list, the compiler  
support is in clang (and hopefully someone will add equivalent support  
to GCC).


Unlike the Apple implementation, it does not require the superclass to  
be compiled with the non-fragile ABI, so you can still compile GNUstep  
with the old ABI and then create subclasses of GNUstep classes  
compiled with the non-fragile ABI.  If you rearrange or add ivars in a  
GNUstep class, then the subclass will still work correctly, as long as  
it was compiled with -fnonfragile-abi.


David


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread Riccardo Mottola

Hey,


But ... going back to the issue of avoiding changes to ivars breaking 
ABI in future releases ... the approach I currently favor is having a 
*single* ivar in the public class.  This is a private id variable 
referring to an instance of a private class which is used to hold the 
real ivars.


I really don't like this approach.  It makes the code difficult to 
read, destroys locality of reference, and hurts performance.


I don't like it either! I think it was discussed quite a bit and we did 
not agree that it was the way to go! The discussion didn't come to a 
conclusion (I remember we also discussed it at FOSDEM), but many agreed 
that this opaque single-ivar solution was bad.


I personally would prefer just breaking the ABI if other solutions are a 
too big effort. Second place of course is David's. I cannot remember now 
why i didn't try it though... did your patch have some prerequisites?


Riccardo



___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread Riccardo Mottola

Hi,




At the very least, we should just add an unused pointer for future 
expansion so that we can add new ivars later and not use this for 
ivars that are likely to remain stable for several releases.


Agreed.

--R



___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread Riccardo Mottola

Hi,


Sorry, I just haven't had a chance to look at installing a 
new/different compiler and working with that yet, though it really IS 
something I'd like to be playing with.


However, it doesn't really have any bearing on this issue because we 
have to develop code for the existing compiler and will need to do so 
as long as we continue to support it (gcc).


Yes, I remember a caveat: that was it, no gcc support. As a GNU project 
I'd be quite waey to drop gcc support.
As for testing the patch, clang is not available as a package in gentoo, 
thus I was too lazy to install it in another way. This also marks the 
diffusion of clang up to now though.



Riccardo


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread Richard Frith-Macdonald


On 16 Jul 2009, at 18:00, David Chisnall wrote:


On 16 Jul 2009, at 17:26, Lars Sonchocky-Helldorf wrote:

Maybe it's not clear to everybody what benefits your patch  
introduces. So maybe it would be a good idea to give a short  
enumeration of all the gains to the broader public (I know you're  
good at writing technical articles since I read quite a few off  
them :-)).


As I wrote in my first email, it provides the same benefits as  
Apple's non-fragile ABI:


You can add or re-arrange instance variables in a class without  
breaking the ABI.  You can also remove private instance variables.   
Instance variable offsets are now stored in a global variable,  
rather than being hard-coded, and are set when the class is loaded  
by the runtime.  This needs a small amount of compiler and runtime  
support.  The runtime support was in the diff I sent to this list,  
the compiler support is in clang (and hopefully someone will add  
equivalent support to GCC).


Unlike the Apple implementation, it does not require the superclass  
to be compiled with the non-fragile ABI, so you can still compile  
GNUstep with the old ABI and then create subclasses of GNUstep  
classes compiled with the non-fragile ABI.  If you rearrange or add  
ivars in a GNUstep class, then the subclass will still work  
correctly, as long as it was compiled with -fnonfragile-abi.


One thing I don't understand about the whole issue of adding ivars is  
how it is supposed to work with key value coding since, in KVC you can  
get/set the value of an ivar by name, but with non-fragile ivars you  
can presumably have multiple ivars with the same name.  What does KVC  
do in that situation?



___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread David Chisnall

On 16 Jul 2009, at 18:59, Richard Frith-Macdonald wrote:

One thing I don't understand about the whole issue of adding ivars  
is how it is supposed to work with key value coding since, in KVC  
you can get/set the value of an ivar by name, but with non-fragile  
ivars you can presumably have multiple ivars with the same name.   
What does KVC do in that situation?


Break, probably.  It will find the first ivar with that name, which  
will be the one in the subclass.  You can, of course, avoid this  
problem by creating explicit accessors which KVC will find in  
preference to direct ivar access.


David


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-07-16 Thread David Chisnall


On 16 Jul 2009, at 18:34, Riccardo Mottola wrote:


Hi,


Sorry, I just haven't had a chance to look at installing a new/ 
different compiler and working with that yet, though it really IS  
something I'd like to be playing with.


However, it doesn't really have any bearing on this issue because  
we have to develop code for the existing compiler and will need to  
do so as long as we continue to support it (gcc).


Yes, I remember a caveat: that was it, no gcc support. As a GNU  
project I'd be quite waey to drop gcc support.


As a GNU project, I'd hope that the GNU compiler collection would put  
some effort into supporting us!  Someone at Apple sent them patches  
for supporting declared properties over a year ago, and yet GCC still  
does not support any of the extensions added in OS X 10.5, which was  
released two years ago.


Snow Leopard is going to make heavy use of blocks and declared  
properties in the API, and if we want to remain compatible, we are  
going to need a compiler that supports these.  It would be really  
great if GCC would, but I have yet to see any evidence that anyone is  
still actively working on Objective-C support in GCC.  In the last two  
years, Clang has gone from having no Objective-C support to supporting  
most of Objective-C 2 on the GNU runtime, while GCC has not gained a  
single new Objective-C feature.


As for testing the patch, clang is not available as a package in  
gentoo, thus I was too lazy to install it in another way. This also  
marks the diffusion of clang up to now though.


Building clang from source is pretty trivial.  It is the system  
compiler for FreeBSD 8 and is in packages for a number of Linux  
distributions and Free/OpenBSD.  Not sure about Solaris.  Clang 1.0 is  
being released with the next LLVM release (2.6, due in September).


David


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-30 Thread Richard Frith-Macdonald


On 30 Jun 2009, at 07:36, Wolfgang Lux wrote:

There is a subtle difference between OS X and GNUstep: As far as I  
understand the code, threadInfo-inputFd is not even checked if the  
run loop has no event sources and no timer and it is just added  
implicitly to the event sources in -pollUntil:within: in  
GSRunLoopCtxt. On OS X, on the other hand, (the equivalent of)  
threadInfo-inputFd automatically becomes an input source once the  
thread starts a new thread. So, if you call NSRunLoop's - 
runMode:beforeDate: in GNUstep after starting a new thread without  
adding a timer or an input source, it returns immediately with NO  
and it does not perform an invocation scheduled by the secondary  
thread, whereas on OS X -runMode:beforeDate: performs the scheduled  
invocation and then returns YES. If I find time, I'll try to make up  
a test case.


Yes please ... sounds like one of those cases where GNUstep does what  
the documentation says rather than what OSX actually does.  It's  
always good to mirror the OSX  behavior for compatibility (and note  
things in our documentation).  We can probably mimic that behavior  
fairly easily.



___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-29 Thread Richard Frith-Macdonald


On 28 Jun 2009, at 21:46, Wolfgang Lux wrote:


Stefan Bidigaray wrote:

I tried setting waitUntilDone to YES, still no luck!  The - 
_finished method still doesn't get called when calling - 
performSelectorOnMainThread:..., for now I've just made that a - 
performSelector:withObject:, which works, but is not what I want  
done.  I guess my next question here is: is - 
performSelectorOnMainThread:withObject:waitUntilDone: working?   
Maybe I built -base incorrectly?


I don't think so. The problem with - 
performSelectorOnMainThread:withObject:waitUntilDone: is that the  
call is only scheduled to be executed by the run loop of the main  
thread. Thus, the call will not be executed before the next event is  
received or the next timer expires on the main thread.


Not exactly ... calling - 
performSelectorOnMainThread:withObject:waitUntilDone:  also triggers  
an event in the run loop of the main thread (by writing to a pipe that  
the thread is listening to), so as the pipe will wake up a sleeping  
thread, the call should be executed pretty much immediately (though  
after any other work already in progress, or waiting to execute) as  
long as the loop is running.


This is indeed different from Mac OS X, where the scheduled call  
seems to be executed immediately if the run loop is idle.


OSX is supposed to behave the same way as GNUstep... it should handle  
the perform on the next run loop iteration, so if the loop is not  
being run the perform should be held up  until it is.


Maybe the runloop is not running, or  maybe it's running, but not in  
the mode that was specified for the method to be performed in?




___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-29 Thread Stefan Bidigaray
On Mon, Jun 29, 2009 at 12:59 AM, Richard Frith-Macdonald 
rich...@tiptree.demon.co.uk wrote:

 Maybe the runloop is not running, or  maybe it's running, but not in the
 mode that was specified for the method to be performed in?


This would probably explain it!  I don't have a run loop on that
test... it's just a straight shot.  I went back to the Apple doc on it,
reread it and realized I completely missed the paragraph that said it queued
the message on the run loop!

Thanks
Stefan
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-28 Thread Wolfgang Lux
I had a look at the code you posted yesterday and I've found two  
dubious points in NSSound_test.m:


and here is a third, minor point:

In the -dealloc method of NSSound you check whether self is still an  
element of the dictionary nameDict. This is completely unnecessary  
since the dictionary retains its elements and therefore if a sound  
object is deallocated and the test self == [nameDict  
objectForKey:_name] succeeds this would mean that self has been  
incorrectly released too often.


Wolfgang



___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-28 Thread Stefan Bidigaray
Thanks Wolfgang, this stuff really helps.

On Sat, Jun 27, 2009 at 4:32 PM, Wolfgang Lux wolfgang@gmail.comwrote:

 I had a look at the code you posted yesterday and I've found two dubious
 points in NSSound_test.m:

 First, there is a retain/release error in NSSound's
 -initWithContentsOfFile:byRef: method. The NSData object returned from
 dataWithContentsOfMappedFile: is already autoreleased, but you release that
 object after calling -initWithData: (recall that you should only release
 objects that you own, which in general are only objects that you have
 allocated yourself either with alloc or copy).


I went ahead and made this change.  Is the reason I wasn't getting a seg
fault due to the TEST_RELEASE instead of a normal RELEASE?


 Second, I noticed that you call -performSelectorOnMainThread... with
 waitUntilDone = NO. I think you should use waitUntilDone = YES here. Note
 that if waitUntilDone = NO and you call -performSelectorOnMainThread... from
 the main thread the call is scheduled to be run at the next iteration of the
 run loop and not performed immediately. In addition, if you really use
 waitUntilDone = NO on purpose you should make sure that the sound object is
 retained until the scheduled method is actually run (i.e., you probably
 should retain self before calling performSelectorOnMainThread and
 autorelease self in _finished). Otherwise, there is a chance that the thread
 which calls the _stream method releases the sound object too early and the
 run loop invokes _finished for an already released object.


I tried setting waitUntilDone to YES, still no luck!  The -_finished method
still doesn't get called when calling -performSelectorOnMainThread:..., for
now I've just made that a -performSelector:withObject:, which works, but is
not what I want done.  I guess my next question here is: is
-performSelectorOnMainThread:withObject:waitUntilDone: working?  Maybe I
built -base incorrectly?

As for the check in -dealloc, it was inherited from the original
implementation, I'll go ahead and remove it.  This probably explains why I
used to get a crash whenever -dealloc was called.

On related news I've implemented the bundle/plug-in loading code, and so
far it works flawlessly.  There's still a lot that needs to be done, but I
think I might have this fully implemented by mid July.

I'm also having issues with -setCurrentTime:, I'm now using sf_seek() in
SndfileSource.m and the tool will crash either on that call or on
sf_read_short() in -_stream.  The best I've come up with is that sf_seek()
and sf_read_short() are trying to access the same data, at the same time
(sf_seek() is called from the main thread and sf_read_short() from the
stream thread) and blowing up.  I thought adding a lock in NSSound's
-setCurrentTime: would fix this problem but it did not.  Hopefully I'll get
some more stuff done today and will post the latest version of the test tool
for you guys to take a look.

Thanks
Stefan
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-28 Thread Stefan Bidigaray
As promised, here's the latest code.  Feel free to poke as many holes in it
as possible.  I'm going to use this, almost completely unchanged, for
NSSound.m.  The bundle/plug-in stuff will go in 100% unchanged.

To build this, you'll need to go into the bundles/ directory to build and
install the 2 bundles/plug-ins before hand.  The plug-ins are not required,
the NSSound object will simply be destroyed (see -initWithData:) if suitable
plug-ins are not found.  There are a few FIXME tags in NSSound_test.m,
these are there to remind me that I need to fix that before going any
further (suggestions are welcome).  The FIXME in -soundNamed: however, is
not mine and I really do not know what to do there.

Thanks
Stefan


nssoundtest.tar.gz
Description: GNU Zip compressed data
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-28 Thread Wolfgang Lux

Stefan Bidigaray wrote:

I tried setting waitUntilDone to YES, still no luck!  The - 
_finished method still doesn't get called when calling - 
performSelectorOnMainThread:..., for now I've just made that a - 
performSelector:withObject:, which works, but is not what I want  
done.  I guess my next question here is: is - 
performSelectorOnMainThread:withObject:waitUntilDone: working?   
Maybe I built -base incorrectly?


I don't think so. The problem with - 
performSelectorOnMainThread:withObject:waitUntilDone: is that the  
call is only scheduled to be executed by the run loop of the main  
thread. Thus, the call will not be executed before the next event is  
received or the next timer expires on the main thread. This is indeed  
different from Mac OS X, where the scheduled call seems to be  
executed immediately if the run loop is idle. As a workaround, you  
could schedule a timer that regularly invokes an empty method in your  
NSSound class on the main thread, e.g.,

  [NSTimer scheduledTimerWithTimeInterval: 1.0
   target: self
 selector: @selector(_heartBeat:)
 userInfo: nil
  repeats: YES];
and
  - (void)_heartBeat:(NSTimer *) { }

Wolfgang



___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-27 Thread Stefan Bidigaray
I know I'm replying a lot to my own posts, but that's just it's me.

Anyway, I've been doing some more testing and the
-performSelectorOnMainThread:withObject:waitUntilDone: call in -_stream is
not really getting executed, as far as I can tell.  I moved the
DESTROY(lock) stuff into -_finished: and was getting a seg fault later down
the line.  I set a break point inside -_finished:, but gdb never got to it,
which leads me to believe the method is not being called.  I then replaced
that call with -performSelector:withObject:, which the way understand simply
does the same thing but on the secondary thread, and it worked.  Is
-performSelectorOnMainThread:... not working?

Thanks
Stefan
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-27 Thread Wolfgang Lux


Am 27.06.2009 um 18:06 schrieb Stefan Bidigaray:


I know I'm replying a lot to my own posts, but that's just it's me.

Anyway, I've been doing some more testing and the - 
performSelectorOnMainThread:withObject:waitUntilDone: call in - 
_stream is not really getting executed, as far as I can tell.  I  
moved the DESTROY(lock) stuff into -_finished: and was getting a  
seg fault later down the line.  I set a break point inside - 
_finished:, but gdb never got to it, which leads me to believe the  
method is not being called.  I then replaced that call with - 
performSelector:withObject:, which the way understand simply does  
the same thing but on the secondary thread, and it worked.  Is - 
performSelectorOnMainThread:... not working?


I had a look at the code you posted yesterday and I've found two  
dubious points in NSSound_test.m:


First, there is a retain/release error in NSSound's - 
initWithContentsOfFile:byRef: method. The NSData object returned from  
dataWithContentsOfMappedFile: is already autoreleased, but you  
release that object after calling -initWithData: (recall that you  
should only release objects that you own, which in general are only  
objects that you have allocated yourself either with alloc or copy).


Second, I noticed that you call -performSelectorOnMainThread... with  
waitUntilDone = NO. I think you should use waitUntilDone = YES here.  
Note that if waitUntilDone = NO and you call - 
performSelectorOnMainThread... from the main thread the call is  
scheduled to be run at the next iteration of the run loop and not  
performed immediately. In addition, if you really use waitUntilDone =  
NO on purpose you should make sure that the sound object is retained  
until the scheduled method is actually run (i.e., you probably should  
retain self before calling performSelectorOnMainThread and  
autorelease self in _finished). Otherwise, there is a chance that the  
thread which calls the _stream method releases the sound object too  
early and the run loop invokes _finished for an already released object.


Wolfgang



___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-26 Thread Stefan Bidigaray
In case you guys didn't know, my weekends start of Fridays (4 day a week
work schedule).  I actually started testing last night and, to my suprise,
it worked pretty well (I've attached my test tool).  It would be really
great to get some input on the code itself.  It's missing quite a bit or
functionality but the over all play, stop, etc stuff is working.

Here's what I know isn't working:

* -isPlaying is still kind of weird because I'm using the NSConditionLock's
condition to figure out if it's playing but that doesn't get destroyed when
the sound naturally reaches the end of the line (would appreciate some
suggests on how to make sure this happens).

* -stop destroys the NSConditionLock, but to make sure it doesn't before
-_stream is done with it I put a sleep() there.  This is related to the
-isPlaying thing above... I'm think the best thing for me to do here is have
-_stream destroy the lock, is that a good idea?

* -currentTime and -setCurrentTime are screwy.  I need to go back in
SndfileSource.m and have those method use sndfile's tell and seek function.
It's real funny watching .ogg and .flac files play and the output of
-currentTime is 1/3 of the actual play time.

* Like I mentioned before, still no bundle loading stuff!  I'm just
including SndfileSource.m and AudioOutputSink.m in the NSSound_test.m
file... just a real quick and dirty workaround for now.

I also have a question: how can I find out if I have any objects that are
not getting deallocated?  In case you didn't catch from my previous stuff
I'm pretty bad a memory management.

Thanks
Stefan


nssoundtest.tar.gz
Description: GNU Zip compressed data
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-19 Thread Richard Frith-Macdonald


On 19 Jun 2009, at 08:05, Fred Kiefer wrote:


Stefan Bidigaray wrote:

It would really help if I attached the file...



I don't understand the general concept here, so just a few detail
comments on the code itself.

Hiding the implementation details in the header is a good thing, but  
it

makes the code in the implementation harder to read. This could be
improved by using local variables (or even Macros). For example


- (BOOL) pause
{
 NSConditionLock *lock = (NSConditionLock*)_private[2];

 if ([lock condition] == SOUND_SHOULD_PAUSE)
   {
 return NO;
   }
 if ([lock tryLock] == NO)
   {
 return NO;
   }
 [lock unlockWithCondition: SOUND_SHOULD_PAUSE];
 return YES;
}



I would go further and ask what the point of the _private array is?

By convention all the instance variables are private (that's what the  
leading underscore in the variable name means), so if all that's  
required is to inform developers that they should not use the ivars  
directly, there's no point in having the array, but maybe it would be  
worth using a @private declaration.


On the other hand, if the idea is to hide the implementation details  
so that ivar layouts won't need to change with future revisions  
(something I think we should all be doing), my preference would be to  
have a single pointer to a structure containing the required data.

eg.

struct  _NSSoundInternal;

@interface NSSound : NSObject NSCoding, NSCopying
{   
@private
  struct _NSSoundInternal   *_internal;
}

Then the designated initialiser allocates memory for the structure,  
clears it, and assigns the pointer when an instance is initialised,  
and -dealloc frees the memory at the end, and all internal references  
to ivars just go indirect from that pointer.  The implementation is  
completely hidden/private and can be changed in subsequent releases  
without breaking the ABI.






___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-19 Thread Stefan Bidigaray
On Fri, Jun 19, 2009 at 2:05 AM, Fred Kiefer fredkie...@gmx.de wrote:

 I don't understand the general concept here, so just a few detail
 comments on the code itself.


I'll try to explain this the best I can, it might be a little long,
though...

As I explained on my previous e-mails, I'm streaming the data to the sink.
In order to do so without blocking the main thread I'm using a separate
thread (spawned using -detachNewThreadSelector:toTarget:withObject:)... this
will happen in -play and the selector is -_stream.  The stream uses 2
objects, one conforms to GSSoundSource and the other to GSSoundSink, the
former outputs the data in a standard format so that the latter can send it
to the audio device.  To pause and resume the stream I use an
NSConditionLock, which is what _private[2] is, if the condition is
SOUND_SHOULD_PAUSE the while loop waits until it's SOUND_SHOULD_PLAY.  The
hardest part, at least for me, is finding out if the thread is already
running in -play and -stop and taking the appropiate action.  The -pause and
-resume methods are pretty straight forward.


 Hiding the implementation details in the header is a good thing, but it
 makes the code in the implementation harder to read. This could be
 improved by using local variables (or even Macros). For example


Sounds good!

When releasing the conditional lock, you should rather destroy it, as it
 could otherwise just be reused, although it has been freed.


Wouldn't this cause a bit of a problem in -_stream since I keep checking the
NSConditionLock's condition?  My plan was to initialize it in -play and
free/destroy it in -stop and use it as the way to find out if the audio data
is being streamed.

Shouldn't the condition of the while loop read something like this?
  while ((!_shouldExit)  (bytesRead  0)  success)


Yes!  Oops...

I've attached a copy of GSSoundSource.h and GSSoundSink.h, these two header
files define the protocols and give you an idea of what exactly I'm going
for.  I've also gone ahead and added documention as well.  I'll also go
ahead and attach the first two classes that implement these protocols.  As
before, I haven't had time to test them, so I'm sure there are typos
everywhere.  I do plan on testing them later today, make sure they actually
do what they're supposed to before finishing the NSSound implentation.

Thanks
Stefan
/* 
   GSSoundSink.h

   Sink audio data.

   Copyright (C) 2009 Free Software Foundation, Inc.

   Written by:  Stefan Bidigaray stefanb...@gmail.com
   Date: Jun 2009
   
   This file is part of the GNUstep GUI Library.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; see the file COPYING.LIB.
   If not, see http://www.gnu.org/licenses/ or write to the 
   Free Software Foundation, 51 Franklin Street, Fifth Floor, 
   Boston, MA 02110-1301, USA.
*/ 

#ifndef _GNUstep_H_GSSoundSink
#define _GNUstep_H_GSSoundSink

@protocol GSSoundSink NSObject

/** init/
 *  Initializes the receiver for output using the defined parameters.
 *  pbWARNING:/b This method does not open the device, see -open./p
 */
- (id)initWithEncoding: (int)encoding
  channels: (NSUInteger)channelCount
sampleRate: (NSUInteger)sampleRate
 byteOrder: (NSByteOrder)byteOrder;
/** Opens the device for output, called by [NSSound-play].
 */
- (BOOL)open;
/** Closes the device, called by [NSSound-stop].
 */
- (void)close;
/** Writes/Plays the data in bytes to the device.  Data imust/i be in 
 *  the same format as specified in
 *  -initWithEncoding:channels:sampleRate:byteOrder:.
 */
- (BOOL)writeBytes: (void *)bytes length: (NSUInteger)length;

/** Called by [NSSound-setVolume:], and corresponds to it.  Parameter volume
 *  is between the values 0.0 and 1.0.
 */
- (void)setVolume: (float)volume;
/** Called by [NSSound-volume].
 */
- (float)volume;
/** Called by [NSSound-setPlaybackDeviceIdentifier:].
 */
- (void)setPlaybackDeviceIdentifier: (NSString *)playbackDeviceIdentifier;
/** Called by [NSSound-playbackDeviceIdentifier].
 */
- (NSString *)playbackDeviceIdentifier;
/** Called by [NSSound-setChannelMapping:].
 */
- (void)setChannelMapping: (NSArray *)channelMapping;
/** Called by [NSSound-channelMapping].
 */
- (NSArray *)channelMapping;

@end

#endif // _GNUstep_H_GSSoundSink

/* 
   GSSoundSource.h

   Load and read sound data.

   Copyright (C) 2009 Free Software Foundation, Inc.

   Written by:  Stefan Bidigaray stefanb...@gmail.com

Re: NSSound Reimplementation

2009-06-19 Thread Stefan Bidigaray
On Fri, Jun 19, 2009 at 4:26 AM, Richard Frith-Macdonald 
rich...@tiptree.demon.co.uk wrote:

 I would go further and ask what the point of the _private array is?


Well, the only reason I could come up with right now is that I didn't want
to have to include GSSoundSink.h and GSSoundSource.h.  The guy writing an
application really doesn't care if these two protocols exist, so I figured
it was best to hide the fact that I used them, and a NSCondtionLock, all
together.

That's why I put this out there before continuing, I wanted to make sure it
was a good decision.

By convention all the instance variables are private (that's what the
 leading underscore in the variable name means), so if all that's required is
 to inform developers that they should not use the ivars directly, there's no
 point in having the array, but maybe it would be worth using a @private
 declaration.

 On the other hand, if the idea is to hide the implementation details so
 that ivar layouts won't need to change with future revisions (something I
 think we should all be doing), my preference would be to have a single
 pointer to a structure containing the required data.
 eg.

 struct  _NSSoundInternal;

 @interface NSSound : NSObject NSCoding, NSCopying
 {
 @private
  struct _NSSoundInternal   *_internal;
 }

 Then the designated initialiser allocates memory for the structure, clears
 it, and assigns the pointer when an instance is initialised, and -dealloc
 frees the memory at the end, and all internal references to ivars just go
 indirect from that pointer.  The implementation is completely hidden/private
 and can be changed in subsequent releases without breaking the ABI.


Should I do this instead?  Fact of the matter is, I'm not sure if the way
I'm going about this is the best way forward, so chances are it'll
eventually change (hence why I created an array of 4 (void *) but am only
using 3 pointers).  I would gladly go this route, specially since, like
everyone else here, I'm all for ABI compatibility.

Thanks
Stefan
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-18 Thread Stefan Bidigaray
It would really help if I attached the file...
@interface NSSound : NSObject NSCoding, NSCopying
{   
  NSString *_name;
  NSData   *_data;
  NSString *_playbackDeviceIdentifier; // Currently unused
  NSArray  *_channelMapping; // Currently unused
  BOOL _onlyReference;
  id   _delegate;
  NSTimeInterval _duration;
  
  // Private info:
  //   0 - input bundle (idGSSoundSource)
  //   1 - output bundle (idGSSoundSink)
  //   2 - lock (NSConditionLock *)
  void *_private[4];
  BOOL _shouldStop;
}



- (void)_stream
{
  NSUInteger bytesRead;
  BOOL bytesWereWritten;
  BOOL success;
  void *bytes;
  
  bytes = NSZoneMalloc(NSDefaultMallocZone(), BUFFER_SIZE);
  bytesRead = [(idGSSoundSource)_private[0] readBytes: bytes length: 
BUFFER_SIZE];
  while ((!_shouldExit) || (bytesRead  0) || (!success))
{
  /* FIXME */
  if ([(NSConditionLock*)_private[2] condition] == SOUND_SHOULD_PAUSE)
{
  [(NSConditionLock*)_private[2] lockWhenCondtion: SOUND_SHOULD_PLAY];
  [(NSConditionLock*)_private[2] unlock];
}
  success = [(idGSSoundSink)_private[1] writeBytes: bytes length: 
bytesRead];
  bytesRead = [(idGSSoundSource)_private[0] readBytes: bytes length: 
BUFFER_SIZE];
}
  
  [self performSelectorOnMainThread: @selector(_finished:)
 withObject: [NSNumber numberforBool: success]
  waitUntilDone: NO];
}

- (BOOL) pause 
{
  if ([(NSConditionLock*)_private[2] condition] == SOUND_SHOULD_PAUSE)
{
  return NO;
}
  if ([(NSConditionLock*)_private[2] tryLock] == NO)
{
  return NO;
}
  [(NSConditionLock*)_private[2] unlockWithCondition: SOUND_SHOULD_PAUSE];
  return YES;
}

- (BOOL) play
{
  // If the NSCondtionLock exists it's because NSSound is either playing or 
paused
  if ((NSConditionLock*)_private[2] != nil)
{
  return NO;
}
  
  _private[2] = (void *)[NSCondtionLock initWithCondition: SOUND_SHOULD_PAUSE];
  /* FIXME */
  if ([(NSConditionLock*)_private[2] tryLock] != YES)
{
  return NO;
}
  
  [[(NSConditionLock*)_private[2] unlockWithCondition: SHOUND_SHOULD_PLAY];
  return YES;
}

- (BOOL) resume
{
  if ([(NSConditionLock*)_private[2] condition] == SOUND_SHOULD_PLAY)
{
  return NO;
}
  if ([(NSConditionLock*)_private[2] tryLock] == NO)
{
  return NO;
}
  [(NSConditionLock*)_private[2] unlockWithCondition: SOUND_SHOULD_PLAY];
  return YES;
}

- (BOOL) stop
{
  if ((NSConditionLock*)_private[2] == nil)
{
  return NO;
}
  /* FIXME */
  _shouldStop = YES;
  
  RELEASE((NSConditionLock*)_private[2]);
  
  return YES;
}

- (BOOL) isPlaying
{
  if ([(NSConditionLock*)_private[2] condition] == SOUND_SHOULD_PLAY)
{
  return YES;
}
  return NO;
}
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


NSSound Reimplementation

2009-06-18 Thread Stefan Bidigaray
OK, I started working on the NSSound side of of the reimplementation
(already finished the Source and Sink protocols) today.  I'm pretty much
implementing this in the manner I explained in my previous e-mails.  I've
attached a text file with some excerpts from NSSound.h and NSSound.m.  I'd
like the maintainers to take a look at the ivar setup, I saw something like
this in the Apple docs and thought it was a good way to mask some of the
interworking of the implementation.  Another thing to look into is the way
I'm using the NSConditionLock to block the streaming thread.

PS: Please note all the FIXME tags I just started working on this and
have not even checked to see if it compiles, I just need to know I'm going
in the right direction before going further.

Thanks
Stefan
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-13 Thread Stefan Bidigaray
OK, this is the architecture design I've come up with...

FYI: I deviated slightly from what I was originally thinking.  I'm going to
start a thread using NSThread's
-detachNewThreadWithSelector:toTarget:withObject: which will have a while
loop in it that streams the audio data.  I figured the playback methods
should just command the thread... -play starts the thread, -stop cancels it,
-pause blocks it, and -resume unblocks it (I'm still not sure how I'll
manage to do this).

So here's what I have, as far as interfaces go (i'm only presenting relevant
methods):

GSSoundInput:
+ (BOOL)canInitWithSound: (NSSound *)aSound
Will verify this bundle can open the sound (be it raw, wav, ogg, mp3, etc)
- (id)initWithSound: (NSSound *)aSound
Will initialize the sound data for playback
- (NSUInteger)readBytes: (void *)bytes length: (NSUInteger)length
Reads the data
These next few match 1-to-1 with NSSound's methods and will be called by
NSSound...
- (NSTimeInterval)duration
- (void)setCurrentTime: (NSTimeInterval)
- (NSTimeInterval)currentTime
These are straight forward...
- (NSUInteger)bitsPerSample
- (NSUInteger)channelCount
- (NSUInteger)sampleRate
- (NSByteOrder)byteOrder

GSSoundOutput:
- (id) initWithBits: (NSUInteger)bitsPerSample
   channels: (NSUInteger)channelCount
 sampleRate: (NSUInteger)sampleRate
  byteOrder: (NSByteOrder)byteOrder
Initializes the device for playback with this info (see GSSoundInput's
methods)
- (BOOL)open
-initWithBits:... doesn't actually open the device, this does.
- (BOOL)close
Closes the device
- (NSUInteger)writeBytes: (void *)bytes length: (NSUInteger)length
Writes the data to the device (keep in mind the device can be anything that
accepts data, like a NSData object).
These next few match 1-to-1 with NSSound's methods and will be called by
NSSound...
- (void)setVolume: (float)volume
- (float)volume
- (NSString *)playbackDeviceIdentifier
- (void)setPlaybackDeviceIdentifier: (NSString *)playbackDeviceIdentifier
- (NSArray *)channelMapping
- (void)setChannelMapping: (NSArray *)channelMapping

NSSound:
- (id)initWithContentsOfFile:(NSString *)path byReference:(BOOL)byRef
Loads file in path using NSData's -initWithContentsOfMappedFile:
- (id)initWithData:(NSData *)data
Finds GSSoundInput and GSSoundOutput compatible bundles and initializes
them.
- (BOOL)pause
Blocks the thread.
- (BOOL)play
Makes sure there's no stream thread running for this NSSound and starts
one.
- (BOOL)resume
Unblocks/resume the thread.
- (BOOL)stop
Tell the thread to exit.
- (BOOL)isPlaying
If stream thread exists and is unblocked will return YES, otherwise NO.
- (void)_stream
This is where the stream loop actually occurs.

Is this a sensible design? I'm not sure this is the best way to go, but it's
the best I could come up with so far and I'd really like some feedback.
Like I mentioned before, I'm not really sure how to block and unblock the
thread, so I'll need some help there (the Apple docs are really confusing
with the whole thread thing, specially with the this is how you do it...
you can also do it this way with 10.5 but we don't recommend it since it's
new).

Stefan
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-11 Thread Stefan Bidigaray
OK, this has been out for almost a week now and I think it's time to start
responding to some of the comments/suggestions brought up.

CHOOSING INPUT/OUTPUT DEVICE
This is a pretty reasonable request, specially since it's part of the API
(check -setPlaybackDeviceIdentifier:), the problem here is that I'm not sure
what to expect!  I don't have a Mac, and the API only explains that the
input must be a NSString (Unique identifier of a sound output device.).  I
can say right away that Libao doesn't not support this feature.

STREAMING
David, I can see where you're coming from, however, since 10.5 NSSound uses
either CoreAudio or QTKit to play sound (... this class may use either Core
Audio or QuickTime to handle the actual playback.), meaning NSSound can be
used for this purpose.

THREADING
I guess I just want to make sure that I'm allowed to use threading on the
core GNUstep libraries?

I didn't see a single objection to libao and the plug-in based architecture.

In my head, I've split NSSound into 4 different parts: NSSound: will manage
the other 3 modules; GSSoundThread (NSThread subclass): will do the actual
streaming; GSSoundInput: a category that will define a standard interface
to read audio data; GSSoundOutput: same as GSSoundInput but for output.
The attached text file is my first attempt at defining how NSSound will
communicate.

I've been reading up on NSThread and it would seem that since 10.5 NSThread
can be subclassed, override -main and call -start to start the thread.  Will
I be allowed to use this mechanism?

As always, all comments/suggestions are welcome and appreciated.

Stefan


NSSound_arch
Description: Binary data
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-11 Thread David Wetzel


Am 11.06.2009 um 23:13 schrieb Stefan Bidigaray:


CHOOSING INPUT/OUTPUT DEVICE
This is a pretty reasonable request, specially since it's part of  
the API (check -setPlaybackDeviceIdentifier:), the problem here is  
that I'm not sure what to expect!  I don't have a Mac, and the API  
only explains that the input must be a NSString (Unique identifier  
of a sound output device.).  I can say right away that Libao  
doesn't not support this feature.




look at

http://code.google.com/p/telephone/

there is example code.

David



___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: NSSound Reimplementation

2009-06-07 Thread David Chisnall


On 7 Jun 2009, at 02:10, Christopher Armstrong wrote:


Hi Stefan

I don't purport to be an expert on sound APIs, but I've played  
around a lot with asynchronous APIs (marshalling in Java with Swing  
and multithreaded APIs).


On 07/06/2009, at 2:01 AM, gnustep-dev-requ...@gnu.org wrote:


* PulseAudio - Pros: Cross-platform, Powerful/large API, used by  
the GNOME
project, a simple API is available, is a sound server.  Cons:  
Requires a
dedicated mainloop for the asynch API, I still don't understand how  
it works

(the asynch API, the simple API is pretty straight forward).


Calling PulseAudio cross-platform is a stretch.  As far as I can tell,  
it works moderately-well with Ubuntu, less-well with other Linux  
distributions, and is a mess everywhere else.


Looking at pulse audio's documentation, it appears that with the  
asynchronous API, you call some functions which run an exclusive  
event loop for pulseaudio on a separate thread. I'm not sure if you  
will need to spawn a separate thread for them, or if they start a  
thread themselves. You could alternatively integrate with the poll()  
mechanism, which may be simpler or more difficult depending on what  
GNUstep uses.


See NSFileHandle for how to get notifications from file descriptors.

David A. also mentioned the possibility of a streaming  
architecture, which I
like because it makes NSSound a lot more useful.  With current  
NSSound code,
and my original submission, NSSound simply read the file/data  
whole, storing
it in a NSData object and later playing that.  Streaming would  
allow us to
keep nothing but a pointer to the file/data (still in a NSData  
object) and
decoding it as we're playing.  This is the design of all sound  
applications

I've had the pleasure of using.


A streaming architecture sounds like a good idea, even if it  
requires some extra plumbing, like an NSData subclass. This way we  
know we can scale to large files e.g. alot of MP3 music I have is  
whole sets that run upto 2 hours long (~100-300MB), and this would  
be impractical to load completely into memory.


This is what mmap() is for.  NSData already has a subclass on GNUstep  
that wraps mmap(), so you only need 300MB of address space - not  
excessive even on a 32-bit platform - and the OS will handle loading  
and evicting the data when required.


If you need a streaming API, you shouldn't be using NSSound, you  
should be using something like Étoilé's MediaKit or Apple's QTKit.



MY OPINION
No matter what I do, it looks like a separate thread is going to  
have to be
spawned to do the streaming.  Problem there is that I've never  
programmed

with threads before, interesting for me since it'll be a learning
experience.  The easiest library to use is libao, it includes  
output every
thing out there (from ALSA to PulseAudio to WINMM).  OpenAL is also  
very
nice, but it's asynchronous by design and doesn't lend it self very  
well for
streaming.  I also really like the idea of loadable bundles/plug- 
ins, this
would allow quite a bit of flexibility, not only to GNUstep but to  
the
application programmer.  Lastly, moving the code to GNUstep-back,  
like
suggested by David C., seems like a good idea (specially with the  
plug-in
based setup) removing the dependency on the -gui library but  
pushing it over

to -back.



A plugable architecture would be ideal.  On platforms where the kernel  
exposes a sane interface (e.g. FreeBSD, Solaris) you don't have any  
extra dependencies, because the OSS APIs are just open()/read()/ 
write()/ioctl() calls on the device[1].  On platforms with a second- 
rate sound subsystem in the kernel you can fall back to something like  
libao.


David

[1] See: 
http://svn.gna.org/viewcvs/etoile/trunk/Etoile/Frameworks/MediaKit/oss.m?rev=3470

___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev


NSSound Reimplementation

2009-06-06 Thread Stefan Bidigaray
I guess I've been making a lot of noise about this lately, fact is I'm kind
of bored!  Anyway, as most of you know, I've put some code out recently and
got quite a bit of feedback.  Reading some of the comments I realized I
hadn't thought this through as much as I had initially thought.  In this
e-mail I'm going to put forth some ideas for the reimplementation of NSSound
and would really appreciate the community's opinion to make a better
decision on the way to go.  I know it's long, sorry but I do have a tendency
of doing that!

INPUT
I think this one is pretty obvious, I moved the code to libsndfile from
libaudiofile.  Since version 1.12 libsndfile has provided a method to read
directly from memory allowing NSSound to read NSData objects, and since
version 1.18 has supposed Vorbis and FLAC decoding.

Please read OTHER CONSIDERATIONS before commenting on this choice.

OUTPUT
This has probably been my biggest mistake so far.  I'm providing a list of
all possible audio output libraries/servers that I've researched below.
Please keep in mind NSSound is very simple in design, so it does not need an
all powerful output API.

* JACK - Pros: JACK2 is cross-platform, very powerful API, low latency,
plays well with other JACK apps, is a sound server.  Cons: JACK1 (the
current stable release) only works on POSIX systems, is a relatively large
library (many unneeded features), requires floating point data, JACK2 is
still experimental.

* PulseAudio - Pros: Cross-platform, Powerful/large API, used by the GNOME
project, a simple API is available, is a sound server.  Cons: Requires a
dedicated mainloop for the asynch API, I still don't understand how it works
(the asynch API, the simple API is pretty straight forward).

* OpenAL - Pros: Cross-platform, powerful and simple API, asynchronous by
design.  Cons: Asynchronous (I know it's here twice, but it can also be a
bad thing if you're trying to stream data), requires 8 or 16 bit PCM data.

* Libao - Pros: Cross-platform, extremely simple API.  Cons: can only stream
data.

* Rolling our own / gnustep_sndd - Pros: GNUstep has full control of the
API.  Cons: Gnustep_sndd reinvents the wheel, any other approach would
require GNUstep to implement and maintain working code for at least ALSA,
OSS and WINMM/DirectSound.

* Honorable mentions: ESD (UNIX-based systems only, on it's way out), aRts
(on it's way out), PortAudio (David C. has mentioned it's quite unusable
anywhere but Linux), SDL and NAS (seems to be a great sound server and API,
but only works on *nix or requires Cgywin).

REQUIREMENTS
Obviously, the main requirement here is API compatibility with OS X 10.5.

David A. also mentioned the possibility of a streaming architecture, which I
like because it makes NSSound a lot more useful.  With current NSSound code,
and my original submission, NSSound simply read the file/data whole, storing
it in a NSData object and later playing that.  Streaming would allow us to
keep nothing but a pointer to the file/data (still in a NSData object) and
decoding it as we're playing.  This is the design of all sound applications
I've had the pleasure of using.

OTHER CONSIDERATIONS
* Loadable bundles/plug-ins - I thought this would be a great idea.  Allow
for loadable input and output bundles so that we can read from virtually any
file format and output to virtually anything.  Could eventually take us in
the roll our own backend model, but I'm not sure this is a bad thing, yet.

* Raw data reading - This seemed like a popular suggestion, and does sound
useful for anyone trying to play something like a CD using NSSound.  Apple
seems solves this problem by having CoreAudio and QT there to pickup the
slack, but we just don't have that option.

* Per NSSound volume control - This is probably the hardest thing to do.
Most of the libraries mentioned above do not support it.  Some hacking can
be done, but it won't be pretty.

* Fallback if libsndfile not present - This really isn't a problem if a
plug-in method is use.

MY OPINION
No matter what I do, it looks like a separate thread is going to have to be
spawned to do the streaming.  Problem there is that I've never programmed
with threads before, interesting for me since it'll be a learning
experience.  The easiest library to use is libao, it includes output every
thing out there (from ALSA to PulseAudio to WINMM).  OpenAL is also very
nice, but it's asynchronous by design and doesn't lend it self very well for
streaming.  I also really like the idea of loadable bundles/plug-ins, this
would allow quite a bit of flexibility, not only to GNUstep but to the
application programmer.  Lastly, moving the code to GNUstep-back, like
suggested by David C., seems like a good idea (specially with the plug-in
based setup) removing the dependency on the -gui library but pushing it over
to -back.

I appreciate any and all comments/suggestions.
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org

Re: NSSound Reimplementation

2009-06-06 Thread Christopher Armstrong

Hi Stefan

I don't purport to be an expert on sound APIs, but I've played around  
a lot with asynchronous APIs (marshalling in Java with Swing and  
multithreaded APIs).


On 07/06/2009, at 2:01 AM, gnustep-dev-requ...@gnu.org wrote:
I guess I've been making a lot of noise about this lately, fact is  
I'm kind
of bored!  Anyway, as most of you know, I've put some code out  
recently and
got quite a bit of feedback.  Reading some of the comments I  
realized I
hadn't thought this through as much as I had initially thought.  In  
this
e-mail I'm going to put forth some ideas for the reimplementation of  
NSSound

and would really appreciate the community's opinion to make a better
decision on the way to go.  I know it's long, sorry but I do have a  
tendency

of doing that!

* PulseAudio - Pros: Cross-platform, Powerful/large API, used by the  
GNOME
project, a simple API is available, is a sound server.  Cons:  
Requires a
dedicated mainloop for the asynch API, I still don't understand how  
it works

(the asynch API, the simple API is pretty straight forward).


Looking at pulse audio's documentation, it appears that with the  
asynchronous API, you call some functions which run an exclusive event  
loop for pulseaudio on a separate thread. I'm not sure if you will  
need to spawn a separate thread for them, or if they start a thread  
themselves. You could alternatively integrate with the poll()  
mechanism, which may be simpler or more difficult depending on what  
GNUstep uses.


The main GNUstep GUI loop will need to use pulseaudio lock functions  
before calling pulseaudio APIs. Callbacks which send data back to  
GNUstep will need to respect the single-threaded nature of the GNUstep  
GUI thread, which means that the code they call must execute on the  
GNUstep run loop, not the pulseaudio one. The only exception to this  
is passing data back: in the callback function, you may need to copy  
the data that pulseaudio gives you into a GNUstep data structure  
(NSString, NSData, etc) and pass that back to the main GNUstep run  
loop. The GNUstep data structure will obviously need to be  
instantiated in the callback, which means that its one of the thread- 
safe GNUstep APIs.


Reading the pulseaudio documentation, it does appear that you have to  
use its locking functions before calling into its API, but this  
shouldn't pose much of an issue if you follow the rules. For callback  
functions, I would expect you'd use something like NSRunLoop's - 
performSelector:target:argument:order:modes: method to marshall a call  
back into the main GNUstep GUI loop). The dedicated main loop running  
on a separate thread should pose less of a problem than something that  
needs constant access to the main thread. As long as you can post  
messages into its event loop, and the event loop is fairly responsive,  
everything should operate smoothly.


IMHO the most important thing to remember with these sorts of APIs is  
that the other thread can be in an inconsistent state compared to your  
thread, so you just need a little bit of extra state checking e.g. if  
you send a stop command to the other thread whilst it is playing, it  
may not stop synchronously, so if you try sending stop again, make  
sure that the API either ignores it, or make sure you can catch any  
exceptions or error codes if it is already stopped.


David A. also mentioned the possibility of a streaming architecture,  
which I
like because it makes NSSound a lot more useful.  With current  
NSSound code,
and my original submission, NSSound simply read the file/data whole,  
storing
it in a NSData object and later playing that.  Streaming would allow  
us to
keep nothing but a pointer to the file/data (still in a NSData  
object) and
decoding it as we're playing.  This is the design of all sound  
applications

I've had the pleasure of using.


A streaming architecture sounds like a good idea, even if it requires  
some extra plumbing, like an NSData subclass. This way we know we can  
scale to large files e.g. alot of MP3 music I have is whole sets that  
run upto 2 hours long (~100-300MB), and this would be impractical to  
load completely into memory.



MY OPINION
No matter what I do, it looks like a separate thread is going to  
have to be
spawned to do the streaming.  Problem there is that I've never  
programmed

with threads before, interesting for me since it'll be a learning
experience.  The easiest library to use is libao, it includes output  
every
thing out there (from ALSA to PulseAudio to WINMM).  OpenAL is also  
very
nice, but it's asynchronous by design and doesn't lend it self very  
well for
streaming.  I also really like the idea of loadable bundles/plug- 
ins, this

would allow quite a bit of flexibility, not only to GNUstep but to the
application programmer.  Lastly, moving the code to GNUstep-back, like
suggested by David C., seems like a good idea (specially with the  
plug-in
based setup) removing the dependency on