Am Donnerstag, 25. Januar 2007 18:38 schrieb Troman:
> ----- Original Message -----
> From: "Troman" <[EMAIL PROTECTED]>
> To: "Troman" <[EMAIL PROTECTED]>
> Sent: Thursday, January 25, 2007 5:57 PM
> Subject: temp
>
> > Am Donnerstag, 25. Januar 2007 15:46 schrieb Giel van Schijndel:
> >> On Thu, 25 Jan 2007 07:31:25 +0100, Dennis Schridde <[EMAIL PROTECTED]>
> >
> > wrote:
> >> > Am Donnerstag, 25. Januar 2007 01:21 schrieb Troman:
> >> >> ----- Original Message -----
> >> >> From: "Dennis Schridde" <[EMAIL PROTECTED]>
> >> >> To: <[email protected]>
> >> >> Sent: Thursday, January 25, 2007 12:26 AM
> >> >> Subject: Re: [Warzone-dev] Music playlists
> >> >>
> >> >>> Am Mittwoch, 24. Januar 2007 22:42 schrieb Troman:
> >> >>>> ----- Original Message -----
> >> >>>> From: "Dennis Schridde" <[EMAIL PROTECTED]>
> >> >>>> To: "Development list" <[email protected]>
> >> >>>> Sent: Wednesday, January 24, 2007 8:43 PM
> >> >>>> Subject: Re: [Warzone-dev] Music playlists
> >> >>>>
> >> >>>>> Am Mittwoch, 24. Januar 2007 18:46 schrieb Per Inge Mathisen:
> >> >>>>>> On 1/18/07, Troman <[EMAIL PROTECTED]> wrote:
> >> >>>>>>> I had some musings about the way this should work. Playlist
> >> >>>>>>> script
> >> >>>>>>> interface will be most used by scriptors I assume. I see two
> >> >>>>>>> main occasions when such an interface might be used:
> >> >>>>>>>
> >> >>>>>>> 1) when it is time to interrupt any background music that might
> >> >>>>>>> be
> >> >>>>>>> played and kick in some moody piece to create atmosphere, like
> >> >>>>>>> it is usually done in campaigns.
> >> >>>>>>>
> >> >>>>>>> 2) when someone wants to attach a custom playlist to his map,
> >> >>>>>>> the way it is done with Unreal Tournament maps for example.
> >> >>>>>>
> >> >>>>>> Agreed.
> >> >>>>>>
> >> >>>>>>> As for the implementation, looks like wz uses 'tracks' to store
> >> >>>>>>> songs. Track 2 corresponds to menu, track 1 to the in-game
> >> >>>>>>> music.
> >> >>>>>>
> >> >>>>>> I do not think we should let that get in the way of a decent API.
> >> >>>>>> We can change the way Warzone stores songs, if necessary.
> >> >>>>
> >> >>>> Since i'm not the one to program it it's fine with me. ;-)
> >> >>>>
> >> >>>>>>> When modder wants his custom playlist to be played when someone
> >> >>>>>>> is using his map he either loads all songs manually to the user
> >> >>>>>>> track using scripts, like
> >> >>>>>>>
> >> >>>>>>> playlistAddUserSong("mySong1.ogg");
> >> >>>>>>> playlistAddUserSong("mySong2.ogg");
> >> >>>>>>
> >> >>>>>> Sounds good.
> >> >>>>>>
> >> >>>>>>> Since this is not the most convenient approach it might be a
> >> >>>>>>> better idea to load playlist from an external playlist file,
> >> >>>>>>> which will come with the mod
> >> >>>>>>
> >> >>>>>> Well, to me the in-script version above seems more convenient
> >> >>>>>> than adding yet another file, since the number of songs will
> >> >>>>>> probably never be high.
> >>
> >> I agree, I think it's better to simply stick with creating the playlist
> >> through scripted functions. Also since I believe the scripts support an
> >> `#include' style directive, you don't have to clutter all your scripts
> >> with
> >> playlist-append calls.
> >>
> >> >>>>>>> In case of a map with custom playlist it is simple, just call
> >> >>>>>>> something like playlistPlayUserTrack(); from within the scripts
> >> >>>>>>> (or again we can make wz start playing user track automatically
> >> >>>>>>> if a map comes with a user playlist) for wz to switch from
> >> >>>>>>> player playlist to the custom map playlist.
> >> >>>>>>
> >> >>>>>> I think starting the script-supplied playlist automatically seems
> >> >>>>>> like the simpler and better way.
> >> >>>>
> >> >>>> What if the user doesn't want any music to be played at the
> >> >>>> beginning?
> >> >>>> It's probably better to let the modder decide this.
> >> >>>
> >> >>> I think what Per meant is that there should be an initPlaylist
> >> >>> function
> >> >>> in the scripts, which is called upon mission start. If the modder
> >> >>> doesn't want that, he must not provide that function.
> >> >>
> >> >> I don't know how we jumped from playback to initialization. Anyway,
> >> >> for
> >> >> the initialization of the playlist you just place the necessary code
> >> >> into the script callback that gets called whenever a map is loaded.
> >>
> >> I think we should just allow the creation of multiple playlists, and
> >> then have some function to select the current active one (like
> >> bindPlaylist below). Then when you select a playlist to be active it
> >> should simply start
> >> playing automatically. If you would want nothing to play then just
> >> select playlist NULL or something similar, meaning no playlist is
> >> active.
> >
> > When everything starts you must have the state playing=no/stoped=yes,
> > because
> > you don't even have a playlist to play from.
> > Your idea would imply that bindPlaylist doesn't only bind the playlist,
> > but
> > also implicitly advises the soundengine to play it.
> > Doesn't sound too nice to me. 1st that function does several things
> > instead of
> > only one and 2nd the modder might not want to start it immediately for
> > whatever reason.
>
> Ditto. I don't know why we would want to force playback, let the modder
> decide.
>
> > Eg. in GL the texture you bind is also not immediately painted on the
> > screen.
> > Or if AL uses a similar way, I don't think every sound-source you bind is
> > immediately played. (But I have _no_ idea of AL, I must admit.)
> > So my advice would be to let bindPlaylist bind the playlist and let
> > startPlaylist/resumePlaylist handle the beginning playback.
> > (Maybe we should have start/stop and pause/resume functions, where
> > start/stop
> > start from the beginning or stop entirely and pause/resume only ... pause
> > and
> > resume. Would save us from weird double namings (start and resume being
> > the
> > same thing) and would also add some functionality for no fees.)
> >
> >> >>>>>>> In cases when some music must kick in from time to time
> >> >>>>>>> depending on some in-game conditions it is a bit more
> >> >>>>>>> complicated.
> >> >>>>>>
> >> >>>>>> There are probably two different needs here:
> >> >>>>>> 1) Scripter wants to play a short song to set the theme of some
> >> >>>>>> event, then resume the playlist as normal. The new song should
> >> >>>>>> then
> >> >>>>>> not be in the playlist afterwards.
> >> >>>>>> 2) Scripter wants to change the whole theme of a level by playing
> >> >>>>>> a new song or songs throughout the remaining time (or until it
> >> >>>>>> changes again). So we need a way to reset the playlist; then the
> >> >>>>>> scripter can add the new songs.
> >> >>>>>>
> >> >>>>>> So how about an API like this:
> >> >>>>>> playlistReset() -- deletes existing playlist (eg to remove game
> >> >>>>>> supplied playlist)
> >> >>>>>> playlistAdd(song) -- adds song to top of playlist (eg to add to
> >> >>>>>> game's supplied playlist)
> >> >>>>>> playlistInterruptWith(song) -- play a song once, then resume
> >> >>>>>> playing playlist (eg for event)
> >> >>>>
> >> >>>> Makes sense to me.
> >> >>>
> >> >>> Didn't say that it doesn't to me.
> >> >>> Just the naming is not my favourite...
> >> >>> playlistReset -> clearPlaylist
> >> >>> playlistInteruptWith -> playTrack
> >> >>> That was my idea... Maybe not ideal, either.
> >>
> >> This can be accomplished by my proposal above.
> >
> > ??
> >
> >> That way you would have to provide a single song playlist though. This
> >> could be done by a wrapping function though: * creating a playlist
> >>  * add the one song to it
> >>  * hook some kind of playlistFinished event on it (as a callback
> >> function)
> >>  * add the ID of the currently playing playlist to a member var of the
> >> new
> >> playlist * make the new playlist active
> >> Then upon raising of playlistFinished event (i.e. through callback
> >> function): * make previous playlist active again
> >>  * destroy one-track playlist
>
> Almost exactly what I had in mind. Seems to be very flexible to me.
>
> > With the bound playlists (GL style architecture) I don't think we need
> > the play-one-track and resume function anymore. I don't even think that
> > we should
> > provide a wrapper for that purpose... More work for us for something the
> > modder can easily achive by himself. Additionaly we need to do some magic
> > with our temporary playlists in the background, which might bring
> > confusion.
> > We would need to find out who created the playlist which just ended to
> > know
> > if we need to inform the scripts or handle it ourselves.
> > (Otherwise we might
> > do some harm to the modders playlist or he might to ours.)
> > So IMO lots of work for little benefit.
>
> Scripts should be notified about all playlists/songs events, not only those
> created by scripts.
> For that matter I mentioned handles in the first post. After the creation
> of playlists and/or songs some handles could be returned to the scripts.
> Then when playlistFinished/songFinished callbacks occur they would return
> playlist/song ID. I don't think we can harm the modder in any way.
Well, then go with that wrapper...
I just thought it might be a bit too much magic. But if it's not, it's ok for 
me...

> >> >>>>> My proposal:
> >> >>>>>
> >> >>>>> Function to set a playlist.
> >>
> >> Could by accomplished by multiple playlistAdd(song) calls.
> >
> > Well, I understood that now. This function would have been a merge of
> > createPlaylist and bindPlaylist. (Remember: I came up with those bound
> > playlists after thinking about all this.)
> >
> >> >>>>> Function to immediately play one track.
> >>
> >> As explained above.
> >>
> >> >>>>> Function to stop playlist playback and one function to resume
> >> >>>>> playback.
> >>
> >> Probably would apply to all playlists? I.e. no playlists should be
> >> played from at all.
> >>
> >> That way some `static bool playing;' could accomplish this (i.e. global
> >> across all playlists).
> >
> > ?
> > start/stop, pause/resume would advise the sound engine to
> > start/stop/pause/resume the current playlist, not one single playlist...
> >
> >> >>>>> Function to set playback-modes, like repeat_all, shuffle, fadein,
> >> >>>>> fadeout, crossfade.
> >>
> >> Repeat-all and shuffle shouldn't be to hard to implement.
> >>
> >> The fading functions however might be a bit though. This because it
> >> would basically require you to set AL_GAIN on your playlist ALsource a
> >> lot (to achieve a good fading resolution). AFAIK OpenAL does not provide
> >> any feature for fading.
> >>
> >> So it's either setting AL_GAIN a lot, or somehow manipulating the
> >> decoded PCM data stream.
> >>
> >> As for cross fading. This would basically require two ALsources on the
> >> moment of switching songs. (You can only send one PCM stream through an
> >> ALsource at a time.) Or again manipulating the PCM stream by mixing on
> >> the
> >> software level. (Rather than using the hardware mixer)
> >
> > Actually I didn't think of that yet...
> >
> >> >>> Those effects (not shuffle, but .*fade.*) would also affect
> >> >>> playTrack(). If the modder wants something different, he can switch
> >> >>> modes before and after his custom track. (Reacting to events.)
> >> >>>
> >> >>>> This all can surely be usefull to the end user/scriptor. Crossfades
> >> >>>> for 'insertations' especially in campaigns etc.
> >> >>>>
> >> >>>>> Clearing the playlist is simply supplying an empty playlist.
> >> >>>>> I don't think there is any need to dynamically attach a track to
> >> >>>>> the
> >> >>>>> playlist, am I correct? Why would one attach a song if he doesn't
> >> >>>>> know when it will be played...
> >> >>>>
> >> >>>> You never know what's going on inside of a modder's head, it
> >> >>>> doesn't take much affort to provide this functionality, besides I
> >> >>>> don't see how else we would want to re-fill the list (see below).
> >> >>>
> >> >>> If there is technically no other way, yes. In my idea you could
> >> >>> re-fill
> >> >>> the list simply by setting the playlist to a list of different
> >> >>> songs...
> >> >>> But addTrack should have a switch so you can choose whether to
> >> >>> append to the front or the back... (Or maybe better 2 functions
> >> >>> addTrackFront
> >> >>> addTrackBack, or appendTrack prependTrack, or similarly named.)
> >> >>>
> >> >>> I just got the idea of Open*L style functions... OMG... crazy...
> >> >>> createPlaylist(Playlist*); // New, empty playlist
> >> >>> deletePlaylist(Playlist*); // Trash it, mark pointer invalid
> >> >>> bindPlaylist(Playlist*); // Switch to another playlist
> >> >>> addTrack(Playlist*,Track*); // Append Track
> >>
> >> Wel the functions on their own look quite good to me.
> >> Their prototypes however... Let's just say that I don't like the idea of
> >> passing pointers into the scripting engine.
>
> Why not? That's the way most of the scripting stuff works right now.
> Scripts currently work with a lot of pointers passed from WZ, although from
> the scriptor's point of view there's no difference between integers/bools
> or pointers to some internal wz structures.
> Not that it really matters to me. If we just work with integer ids, that
> would mean we have less different types to define for scripts (I don't
> really like the idea of flooding scripts with dozens of new types, unless
> really needed, but i'm not yet sure what would be optimal for us).
>
> > This was _not_ a proposal for the scripting engine, but for the C-API...
> > The scripting engine would get some integer IDs or similar...
> >
> >> >>> Hmmm... Actually the idea is not that bad...
> >> >>> Would make it easy to handle multiple playlists, eg. one for the
> >> >>> menu and for the game, or when The Modder wants to interupt the game
> >> >>> with a
> >> >>> few different songs to acompany his cutscenes or the attack of the
> >> >>> clones... (And wants to switch back to the usual theme afterwards.)
> >> >>>
> >> >>> Implementation for createPlaylist:
> >> >>> New item of a playlist-linked-list. All pointers NULL. (next, prev,
> >> >>> thisTrack).
> >> >>>
> >> >>> addTrack:
> >> >>> Walk to the end of Playlist*, check if thisTrack is NULL, yes-> set
> >> >>> thisTrack to Track*, no-> append another empty item, link it in, set
> >> >>> it's thisTrack.
> >>
> >> That implementation would have to require that the same piece of code
> >> that
> >> manages the playlist also manages the tracks. Because a pointer in that
> >> playlist would become invalid as soon as someone removed/destroyed/freed
> >> the track without first searching *all* playlists and deleting it from
> >> them.
> >
> > I thought the current resource handler would keep track of who wants some
> > resource. If it doesn't I'll fix that together with the rest of it next
> > month.
> >
> >> >>> bindPlaylist:
> >> >>> Set sound engine's nextTrack pointer to 1st item of the given list,
> >> >>> and
> >> >>> advise it to skipTrack() so it plays nextTrack.
> >> >>>
> >> >>> The linked list would perhaps become a bit unhandy when it comes to
> >> >>> shuffling and repeating, but it seems very handy when binding,
> >> >>> adding or switching to the next track...
> >> >>>
> >> >>> What do you think about this? Opinions, objections?
> >> >>
> >> >> I don't know if linked list is best suitable for this or about other
> >> >> implementation details but the idea itself sounds good, this approach
> >> >> is
> >> >> more flexible than current one. For just the in-game playlists it may
> >> >> be
> >> >> too much, but could be usefull when scripts get involved.
> >> >
> >> > I just don't know what else could be used. There are no dynamic arrays
> >> > in
> >> > C, at least none that I know of. And I don't have another idea how
> >> > several dynamic-sized playlists could be handled. (I am lacking
> >> > experience and probably I didn't read my C book till the end.)
> >>
> >> In fact I think dynamic arrays (std::vector or std::list) are probably
> >> the
> >> best way to solve this. Then once your using C++ anyway you might as
> >> well use a smartpointer to hold the `track' object which will fix the
> >> problem I
> >> mentioned above.
> >>
> >> Such a small usage of C++ should be rather easy to contain/manage in a
> >> single (e.g. `lib/sound/playlist.cpp') source file.
> >
> > Well, C doesn't have std::vector, so I had no other idea...
> > What I just thought about was some selfmade dynamic array:
> > struct Playlist { meta-info; Track[]; }
> > malloc( sizeof(meta-info) + sizeof(Track*) * playlistSize );
> > or realloc( ... );
> > Doesn't look nice, but would be an option...
>
> While surely not as elegant as dynamic arrays we can as well just use fixed
> arrays if those are only used to hold pointers to playlists, to be honest I
> doubt anyone would want more than, say, 20 playlists at a time (i'm being
> rather generous).
>
> >> > And the initial idea why I proposed an implementation was that I
> >> > thought
> >> > that createPlaylist needs to return a pointer to something which we
> >> > can see is empty and which first gets filled when we add a track.
> >> > Probably the solution would have been obvious to everyone, but I had
> >> > to think about it for a second, so I thought it's better if I write it
> >> > down. Then
> >> > I got the idea how simple bindPlaylist could be (I first thought that
> >> > it
> >> > might be very complicated, because the playback needs to be stopped
> >> > and buffers need to be cleared and and and...) so I wrote that down,
> >> > too.
> >>
> >> Simply said, you only need two buffers per playlist.
> >>
> >> The simplicity of stopping/pausing playback would depend on wether you
> >> use
> >> one ALsource/playlist or one for all playlists. In the case of one per
> >> playlist you could simply set the source to paused on deactivating the
> >> current playlist, then upon reactivation set it to play again. (number
> >> of ALsources is limited by OpenAL.)
> >
> > One buffer/source per playlist sounds good. If the playlist is stoped
> > (not paused) we could destroy the buffer and the source.
> >
> > Why are 2 buffers needed? Only case I can imagine is when crossfading,
> > but in
> > that case each playlist has it's buffers it will play from and we only
> > have
> > to adjust the gain between them.
> >
> >> If you were to use one for all playlists however then you have about two
> >> (or three) options:
> >>
> >> one bufferset for all playlists (I believe OpenAL limits the amount of
> >> them
> >> to 64?): 1) * on pausing: stop the ALsource
> >>     * deattach all ALbuffers from it, destroy them
> >>     * remember the last playing track (as playlist position)
> >>     * then upon resuming simply restart playback from that song
> >>
> >> one bufferset per playlist.
> >>  2) * on pausing: stop the ALsource
> >>     * retrieve the order of the currently attached (non-finished)
> >> ALbuffers
> >>     * deattach all ALbuffers from it (but don't destroy them)
> >>     * upon resuming reattach all non-finished ALbuffers to the ALsource
> >> in
> >> the correct order * start the ALsource again
> >>
> >> variation on 2, one bufferset for all playlists:
> >>  3) * on pausing: stop the ALsource
> >>     * retrieve the amount of time of unplayed sound from the buffers
> >> (through buffer size/count?) * deattach all ALbuffers from it, destroy
> >> them
> >>     * upon resuming somehow calculate a new position to start decoding
> >> from
> >> (should be a bit back if buffers where full) * recreate buffers, decode
> >> data to fill them up
> >>     * attach them to the ALsource
> >>     * start the ALsource again
> >>
> >> Of these 1 and 3 have the best resource efficiency (e.g. memory, amount
> >> of
> >> active ALsources/ALbuffers). 1 will probably be even more efficient (in
> >> terms of big O), 3 will have better accuracy on time position to resume
> >> playing. 2 will probably be the easiest to implement, might have better
> >> timing accuracy than 3 and will most certainly have better big O
> >> efficiency
> >> than 3.
> >>
> >> >>>>> Stopping and resuming the playlist may be interesting to create
> >> >>>>> moments of total silence or when cutscenes are played.
> >> >>>>>
> >> >>>>> C-Functions:
> >> >>>>> WZSound_setPlaylist( Song * song1, ... );
> >> >>>>> WZSound_playTrack( Track interuptionTrack );
> >> >>>>> WZSound_stopPlaylist();
> >> >>>>> WZSound_resumePlaylist();
> >> >>>>> WZSound_setPlaylistMode( PlaylistMode newMode );
> >> >>>>>
> >> >>>>> typedef PlaylistMode UInt8;
> >> >>>>> #define PLAYLIST_SHUFFLE 0x1
> >> >>>>> #define PLAYLIST_REPEAT_ALL 0x2
> >> >>>>> #define PLAYLIST_CROSSFADE 0x4
> >> >>>>> ...
> >>
> >> What about an enum instead?
> >
> > Doesn't go well with bitwise or...
> > ( PLAYLIST_SHUFFLE | PLAYLIST_CROSSFADE ) will not be defined in the
> > enum.
> >
> >> >>>>> C-Function examples:
> >> >>>>> WZSound_setPlaylist( song1, song2, song3 );
> >> >>>>> WZSound_setPlaylist( NULL );
> >> >>>>> WZSound_setPlaylistMode( PLAYLIST_SHUFFLE | PLAYLIST_CROSSFADE );
> >> >>>>>
> >> >>>>> Script-Function examples:
> >> >>>>> WZSound_setPlaylist( "song1.ogg", "song2.ogg", "song3.ogg" );
> >> >>>>
> >> >>>> Variadic functions won't work, we'll have to fall back to something
> >> >>>> like playlistAddSong(song);
> >> >>>
> >> >>> Ok, then I'm fine with Per's playlistAdd and playlistClear
> >> >>> functions.
> >> >>>
> >> >>>>> WZSound_setPlaylist( "none" );
> >> >>>>> WZSound_playTrack( "event1.ogg" );
> >> >>>>> WZSound_setPlaylistMode( "shuffle", "fadein" );
> >> >>>>> WZSound_setPlaylistMode( "repeat_all", "crossfade", "fadeout" );
> >> >>>>> WZSound_setPlaylistMode( "none" );
> >>
> >> Lets not use Cstrings (or any piece of rope for that matter; i.e.
> >> strings)
> >> to indicate play modes.
> >
> > This was for the scripting engine. I don't think it supports bitflags,
> > does
> > it? So the first and possibly easiest option was concatenating strings.
> > Maybe we could also provide the C-defines (PLAYLIST_SHUFFLE,...) as
> > constants
> > to the scripting engine and add them on another...
>
> Sure, best way to solve this is to provide constants predefined by wz,
> works like a charm.
>
> >> >>>> Any particular reason not to use playlistSetMode() instead of
> >> >>>> WZSound_setPlaylistMode()? It's shorter while preserving the same
> >> >>>> meaning.
> >> >>>
> >> >>> For the scripts I don't care.
> >> >>
> >> >> For the scripts, yes.
> >>
> >> I think scripts should indeed have functions without the WZSound in
> >> front of it.
> >>
> >> >>> For the code I think we should develop some unique and sane naming
> >> >>> convention to prevent name clashes and provide a clear and
> >> >>> consistent API. That's why I came up with WZSound_. Other engine (->
> >> >>> lib/) parts might be called WZScript, WZIvis  (what does ivis
> >> >>> actually mean/stand for?) or WZGrahics...
> >>
> >> In the codebase itself I really like this idea.
> >
> > Other idea would be to do it GL style:
> > wzBindPlaylist(), wzAddTrack(), ...
> > This wouldn't make it obvious out of which engine part the function
> > comes, though. Dunno if that is aceptable.
> > LIBNAME_function() is commonly used, I think, so I came up with it 1st.
> >
> >> >>>>> Additionally I would sent following events to the scripts (and
> >> >>>>> over the internal event-bus), namings are currently very bad:
> >> >>>>> playlist_stop
> >> >>>>> playlist_resume
> >> >>>>> playlist_nextTrack
> >> >>>>> playlist_customTrack
> >> >>>>> playlist_customTrackEnd
> >> >>>>> playlist_modeChange
> >> >>>>> playlist_new
> >> >>>>> playlist_end
> >> >>>>>
> >> >>>>> --Dennis
> >> >>>>
> >> >>>> Script events would be usefull. Those would end up being named
> >> >>>> CALL_PLAYLISTEND, CALL_SONGEND etc following wz convention. But
> >> >>>> those
> >> >>>> are details, provide me playlist functionality I'll take care of
> >> >>>> the rest, probably not until mid february though.
> >> >>>
> >> >>> 2.1 won't be released in February and probably not in March or
> >> >>> anytime
> >> >>> soon. So this currently doesn't matter that much. ;)
> >>
> >> In that case lets haul the code over entirely ;-).
> >>
> >> >>>> PS: geez am I the only one having trouble replying to attached
> >> >>>> files?
> >> >>>
> >> >>> Apparently: Yes...
> >> >>
> >> >> Wouldn't have asked if it was apparent. I was refering to those '>'
> >> >> markers actually. Don't see a way how to add them with outlook
> >> >> express,
> >> >> which forces me to make a small detour.
> >> >
> >> > Outlook doesn't give you those '>' if you press reply on a mail which
> >> > has
> >> > an attached file???
> >>
> >> Of course I can advise you to take and use Thunderbird instead ;-) .
> >> It's more powerful than Outlook (e.g. in case of low level access, mem
> >> footprint, etc).
>
> Might as well do this someday, for now I think I'll give Outlook a try and
> see if it offers enough functionality (using Outlook Express right now).
>
> BTW why don't we just use forums for such discussions? This starts to look
> a bit awkward to me. Maybe we can ask Kamaze to set up some protected area
> for the developers and those participating in the mailinglist discussion?
> Personally i'd also be fine with a public forum, not sure if this would
> work well though.
I think most of us are going well with a mailinglist and prefer it this way.
At least to me it's much simpler to fire up my mail client and watch several 
threaded discussions. Forums have that flat, time-related style (lost the 
words... Allready getting late. I mean they only have one direction, you 
can't split of a discussion as easily) which makes the inconvenient IMO...

--Dennis

Attachment: pgpUYD9JoKWSz.pgp
Description: PGP signature

_______________________________________________
Warzone-dev mailing list
[email protected]
https://mail.gna.org/listinfo/warzone-dev

Reply via email to