www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.stream.File help required (and classes)

reply "akaz" <nemo utopia.com> writes:
Hi all,

  I am trying to port some application based on a library called 
mediastreamer2, part of linphone software.

  The basic software component built on top of mediastreamer2 is 
called a "filter".

  Basically, it is a C structure with parameters and some methods 
(pointers to functions). Ammong the latter: a kind of constructor 
(.init), a kind of destructor (.uninit), some setters and a sort 
of "run method" (.process).

  The "run method" is called by an independent thread (a time 
ticker). It reads some queues, extract messages (packaged data) 
from there and process this data.

  Now, I implemented a filter which basically takes packaged data 
(messages) from an input queue and *should* write this data into 
a file.

  This is built around a std.stream.File class.

  Now, the questions:

  1. why there is std.stdio.File, but also std.stream.File? This 
gives a conflict and explicit names must then be used to avoid 
conflict.

  2. is the std.stream.File the correct choice here? Should I use 
std.file instead? Then, why so many file classes (count 
std.stdio.File too).

  3. std.stream.File does not have, apparently, some 
easy-to-interogate properties to know the name (path) and the 
state of the associated file. Are there any?

  4. the "run method" seems to lose knowledge about the file. The 
file is opened in a setter and then it should remain seekable and 
writeable. However, into the "run method" it appears as 
unseekable and unwriteable. More, trying to access .toString() 
property of the std.stream.File variable or to write some data 
into the file triggers a segmentation fault error.

  Here is the file msf_sinker_binaryfile.d, but if required, then 
I will post other files too. I am not sure how to extract a 
simpler test case.

//========================msf_sinker_binaryfile.d==========================
module msf_sinker_binaryfile;
import std.stream;
import std.stdio;

import mediastreamer2_layer;
import msf_commons;

const uint MSF_SINKER_BINARYFILE_OPEN = 
MS_FILTER_METHOD!(byte)(cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID,0);
const uint MSF_SINKER_BINARYFILE_CLOSE = 
MS_FILTER_METHOD_NO_ARG(cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID,1);

private struct _MSF_State{
	__gshared std.stream.File filedesc; //file descriptor
};
private alias _MSF_State MSF_State;

private void msf_init(MSFilter* f){ //a constructor
     
printf("msf_binfile_init-start\n============================\n");
	MSF_State* s=ms_new!(MSF_State)(1);
	s.filedesc = new std.stream.File;
	printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc);
	writef("s.filedesc.seekable=%b+++++++++++++++++++++\n",s.filedesc.seekable);
     
writef("s.filedesc.readable=%b+++++++++++++++++++++\n",s.filedesc.readable);
     
writef("s.filedesc.writeable=%b+++++++++++++++++++++\n",s.filedesc.writeable);
     
writef("s.filedesc.toString=%b+++++++++++++++++++++\n",s.filedesc.toString);
	f.data=s;
	printf("msf_binfile_init-stop\n============================\n");
}

private int msf_open(MSFilter* f, void* arg){ //a setter
     
printf("msf_binfile_open-start\n============================\n");
	MSF_State* s=cast(MSF_State*)f.data;
	ms_mutex_lock(&(f.lock));
     printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc);
	writef("s.filedesc.seekable=%b+++++++++++++++++++++\n",s.filedesc.seekable);
     
writef("s.filedesc.readable=%b+++++++++++++++++++++\n",s.filedesc.readable);
     
writef("s.filedesc.writeable=%b+++++++++++++++++++++\n",s.filedesc.writeable);
	writef("s.filedesc.toString=%b+++++++++++++++++++++\n",s.filedesc.toString);
	s.filedesc.open(*(cast(string*)arg),FileMode.OutNew);
	printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc);
	writef("s.filedesc.seekable=%b+++++++++++++++++++++\n",s.filedesc.seekable);
     
writef("s.filedesc.readable=%b+++++++++++++++++++++\n",s.filedesc.readable);
     
writef("s.filedesc.writeable=%b+++++++++++++++++++++\n",s.filedesc.writeable);
	writef("s.filedesc.toString=%b+++++++++++++++++++++\n",s.filedesc.toString);
     ms_mutex_unlock(&(f.lock));
	printf("msf_binfile_open-stop\n============================\n");
	return 0;
}

private void msf_process(MSFilter* f){ //a run() method
     
printf("msf_binfile_process-start\n============================\n");
	MSF_State* s=cast(MSF_State*)f.data;
	mblk_t* m;
	while((m=ms_queue_get(f.inputs[0]))!=null){ //reading samples 
from input
		ms_mutex_lock(&(f.lock));
		int len=cast(int)((m.b_wptr-m.b_rptr)); //length of message 
data block
		byte* p=cast(byte*)m.b_rptr;
		/*printf("----------------------------\n");
         for(int idx=0; idx<len; idx++){
             printf("d_data[%d]=%d\n",idx,d_data[idx]);
         }
		printf("----------------------------\n");*/
		//File filedesc;
		//filedesc.open("newfile.bin","w+b");
		printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc);
         
writef("s.filedesc.seekable=%b+++++++++++++++++++++\n",s.filedesc.seekable);
         
writef("s.filedesc.readable=%b+++++++++++++++++++++\n",s.filedesc.readable);
         
writef("s.filedesc.writeable=%b+++++++++++++++++++++\n",s.filedesc.writeable);
         
writef("s.filedesc.toString=%b+++++++++++++++++++++\n",s.filedesc.toString);
		//s.filedesc.writeString("This writes a string to the file. ");
		//s.filedesc.writeBlock(p,len);
		//filedesc.close();
		ms_mutex_unlock(&(f.lock));
		freemsg(m);
	}
     
printf("msf_binfile_process-start\n============================\n");
}

private int msf_close(MSFilter* f, void* arg){ //an unsetter
	MSF_State* s=cast(MSF_State*)f.data;
	ms_mutex_lock(&(f.lock));
     s.filedesc.close();
	ms_mutex_unlock(&(f.lock));
	return 0;
}

private void msf_uninit(MSFilter* f){ //a destructor
	MSF_State* s=cast(MSF_State*)f.data;
     msf_close(f, null);
	ms_free(s);
}

private immutable MSFilterMethod[3] msf_methods=[
	{id:MSF_SINKER_BINARYFILE_OPEN,method:cast(MSFilterMethodFunc)&msf_open},
	{id:MSF_SINKER_BINARYFILE_CLOSE,method:cast(MSFilterMethodFunc)&msf_close},
	{0,null}
];

immutable MSFilterDesc msf_sinker_binaryfile_desc={
	id:cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID,
	name:"MSFileSink",
	text:"File sink",
	category:MSFilterCategory.MS_FILTER_OTHER,
	ninputs:1,
	noutputs:0,
	init:cast(MSFilterFunc)&msf_init,
	process:cast(MSFilterFunc)&msf_process,
	uninit:cast(MSFilterFunc)&msf_uninit,
	methods:cast(MSFilterMethod*)&msf_methods[0]
};

//========================================================================


The segmentation fault appears on line 68 (the line 
"writef("s.filedesc.toString=%b+++++++++++++++++++++\n",s.filedesc.toString);" 
inside the msf_process() function (there are several lines like 
that - debug messages).

The output of the software is:

warning: GDB: Failed to set controlling terminal: Operation not 
permitted
-------START PROGRAM-------
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0
ALSA lib control.c:951:(snd_ctl_open_noupdate) Invalid CTL 
default:0
ortp-warning-Could not attach mixer to card: Invalid argument
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:0
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:0
ortp-warning-Strange, sound card HDA Intel does not seems to be 
capable of anything, retrying with plughw...
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1
ALSA lib control.c:951:(snd_ctl_open_noupdate) Invalid CTL 
default:1
ortp-warning-Could not attach mixer to card: Invalid argument
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:1
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:1
ortp-warning-Strange, sound card HDA ATI HDMI does not seems to 
be capable of anything, retrying with plughw...
ortp-warning-Strange, sound card HDA ATI HDMI seems totally 
unusable.
msf_binfile_init-start
============================
s.filedesc=0x7ffff7ebcf40+++++++++++++++++++++
s.filedesc.seekable=0+++++++++++++++++++++
s.filedesc.readable=0+++++++++++++++++++++
s.filedesc.writeable=0+++++++++++++++++++++
s.filedesc.toString=[1110011, 1110100, 1100100, 101110, 1110011, 
1110100, 1110010, 1100101, 1100001, 1101101, 101110, 1000110, 
1101001, 1101100, 1100101]+++++++++++++++++++++
msf_binfile_init-stop
============================
msf_set_freq-start
============================
msf_set_freq-stop
============================
msf_set_rate-start
============================
msf_set_rate-stop
============================
msf_binfile_open-start
============================
s.filedesc=0x7ffff7ebcf40+++++++++++++++++++++
s.filedesc.seekable=0+++++++++++++++++++++
s.filedesc.readable=0+++++++++++++++++++++
s.filedesc.writeable=0+++++++++++++++++++++
s.filedesc.toString=[1110011, 1110100, 1100100, 101110, 1110011, 
1110100, 1110010, 1100101, 1100001, 1101101, 101110, 1000110, 
1101001, 1101100, 1100101]+++++++++++++++++++++
s.filedesc=0x7ffff7ebcf40+++++++++++++++++++++
s.filedesc.seekable=1+++++++++++++++++++++
s.filedesc.readable=0+++++++++++++++++++++
s.filedesc.writeable=1+++++++++++++++++++++
s.filedesc.toString=[1110011, 1110100, 1100100, 101110, 1110011, 
1110100, 1110010, 1100101, 1100001, 1101101, 101110, 1000110, 
1101001, 1101100, 1100101]+++++++++++++++++++++
msf_binfile_open-stop
============================
msf_sinusoid_process-start
============================
s.rate=4000.000000============================
msf_sinusoid_process-stop
============================
msf_split_process-start
============================
msf_split_process-stop
============================
msf_dbl2int16_process-start
============================
msf_dbl2int16_process-stop
============================
ortp-warning-alsa_set_params: periodsize:0 Using 64
ortp-warning-alsa_set_params: period:8 Using 8
msf_binfile_process-start
============================
s.filedesc=0x7ffff7ebcf40+++++++++++++++++++++
s.filedesc.seekable=0+++++++++++++++++++++
s.filedesc.readable=0+++++++++++++++++++++
s.filedesc.writeable=0+++++++++++++++++++++
Segmentation fault (core dumped)

Strangely, the file is writeable and seekable in the msf_open() 
function, but it becomes unseekable and unwriteable in the 
msf_process() function. Do I lose my file descriptor when exiting 
the msf_open() function? If yes, how to keep it? It is because of 
the TLS variables?

Thank you.
Mar 27 2012
next sibling parent "akaz" <nemo utopia.com> writes:
I should at that the "__gshared" attribute was added in distress, 
but changed nothing. With or without it, the program still 
crashes.
Mar 27 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Mar 27, 2012 at 01:58:03PM +0200, akaz wrote:
[...]
  Now, the questions:
 
  1. why there is std.stdio.File, but also std.stream.File? This
 gives a conflict and explicit names must then be used to avoid
 conflict.
[...] This is a design flaw that will be fixed eventually. There's a std.io module in the works that will eventually replace std.stream and std.stdio. Unfortunately it's at a roadblock right now. For the conflicts, you could try using 'alias' to disambiguate between them, or any of the various import aliasing tools. T -- The early bird gets the worm. Moral: ewww...
Mar 27 2012
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 27 Mar 2012 10:46:08 -0400, H. S. Teoh <hsteoh quickfur.ath.cx>  
wrote:

 On Tue, Mar 27, 2012 at 01:58:03PM +0200, akaz wrote:
 [...]
  Now, the questions:

  1. why there is std.stdio.File, but also std.stream.File? This
 gives a conflict and explicit names must then be used to avoid
 conflict.
[...] This is a design flaw that will be fixed eventually. There's a std.io module in the works that will eventually replace std.stream and std.stdio. Unfortunately it's at a roadblock right now.
I just want to correct some inaccuracies: 1. std.io will *not* replace std.stdio, it will replace std.stream. std.stdio.File will be able to use std.io's objects as implementation, but this will be transparent to existing code. 2. There is not a roadblock, I'm working on it very slowly is all :) I'm hoping to have something more concrete soon. I just got RefCounted to work with classes, and that was a major issue, since std.io is interface/class based. -Steve
Mar 27 2012
parent "akaz" <nemo utopia.com> writes:
Thank you. But why do I lose access to my std.stream.File file? 
Somehow, the variable gets unallocated, thus the file is closed 
back?

With pointers of C it used to be so simple... variable remained 
allocated untel the corresponding free().

I do not quite grasp this (a bit) awkward mix between pointers 
and classes (references?). Sometimes is like C/C++, sometimes is 
like Java...
Mar 27 2012
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/27/2012 04:58 AM, akaz wrote:

 2. is the std.stream.File the correct choice here? Should I use std.file
 instead? Then, why so many file classes (count std.stdio.File too).
std.file is more about files and directories, not file contents. I've abandoned std.stream.File some time ago. I just use std.stdio.File partly because stdio, stdout, and stderr are of that type anyway. It works with ranges as well.
 3. std.stream.File does not have, apparently, some easy-to-interogate
 properties to know the name (path) and the state of the associated file.
std.stdio.File provides name() for the name and getFP() if you want to access the underlying FILE*.
 private void msf_init(MSFilter* f){ //a constructor
 printf("msf_binfile_init-start\n============================\n");
 MSF_State* s=ms_new!(MSF_State)(1);
 s.filedesc = new std.stream.File;
[...]
 f.data=s;
We are assuming that f never goes away and that f.data is not assigned anything else, right? Otherwise the garbage collector will destroy that MSF_State and reclaim its memory at an indeterminate time. Is it possible that you use the MSF_State object longer than you should, after it's lifetime ended? If you did, the object would look usable for a while until the GC collects it. Ali
Mar 27 2012
parent reply "akaz" <nemo utopia.com> writes:
 std.file is more about files and directories, not file 
 contents. I've abandoned std.stream.File some time ago. I just 
 use std.stdio.File partly because stdio, stdout, and stderr are 
 of that type anyway. It works with ranges as well.
should be re-named std.folder, then, or std.filesystem. having another "file" there is quite confusing. Oh, no! there is also a... std.cstream!
 std.stdio.File provides name() for the name and getFP() if you 
 want to access the underlying FILE*.
I understand that std.stdio.File is the newer approach. OK, I will try to use that instead. BUT: what is the equivalent of std.stream.File.writeBlock(const void* buffer, size_t size)? I see there is a std.stdio.rawWrite(T)(in T[] buffer); But, my data is: a (byte*) pointer and a length. How do I write something like std.stream.File.writeblock(cast(byte*)p,cast(int)len) using std.stdio.File.rawWrite? And why std.stream.File is not marked as deprecated if a better (newer) alternative exists?
 private void msf_init(MSFilter* f){ //a constructor
 
printf("msf_binfile_init-start\n============================\n");
 MSF_State* s=ms_new!(MSF_State)(1);
 s.filedesc = new std.stream.File;
[...]
 f.data=s;
We are assuming that f never goes away and that f.data is not assigned anything else, right? Otherwise the garbage collector will destroy that MSF_State and reclaim its memory at an indeterminate time. Is it possible that you use the MSF_State object longer than you should, after it's lifetime ended? If you did, the object would look usable for a while until the GC collects it.
Yes, that should be the case. f is the mother structure (a pointer towards a MSFilter structure) that should never disappear and f.data should not be assigned somewhere else. I have several other "filters" implemented using the same schema and they seem to work quite well, except that they do not use files or... classes (I still cannot grasp that fundamental thing when a class instance is a variable and when it is a pointer; when is T x; and when is T* x = new T(); or, when is T* x=(T*)calloc(1,sizeof(T));) For the record, here is the "main.d" filter: =========================main.d=========================== import std.stdio; import core.thread; import std.math; import mediastreamer2_layer; import msf_sourcer_sinusoid; import msf_converter_double2int16_t; import msf_sinker_binaryfile; import msf_processor_split; import msf_sinker_void; int main(char[][] args) { MSTicker* ticker; MSFilter* src_sinus; MSFilter* cnv_dbl2int16_t; MSFilter* snk_sndcrd; MSFilter* snk_binfile; MSFilter* prc_split1; MSFilter* prc_split2; MSFilter* snk_void; printf("-------START PROGRAM-------\n"); ms_init(); src_sinus=ms_filter_new_from_desc(&msf_sourcer_sinusoid_desc); cnv_dbl2int16_t=ms_filter_new_from_desc(&msf_converter_double2int16_t_desc); snk_sndcrd=ms_snd_card_create_writer(ms_snd_card_manager_get_default_card(ms_snd_card_manager_get())); snk_binfile=ms_filter_new_from_desc(&msf_sinker_binaryfile_desc); prc_split1=ms_filter_new_from_desc(&msf_processor_split_desc); prc_split2=ms_filter_new_from_desc(&msf_processor_split_desc); snk_void=ms_filter_new_from_desc(&msf_sinker_void_desc); double f0=1000.0; ms_filter_call_method(src_sinus,MSF_SOURCER_SINUSOID_SET_FREQ,&f0); double fe=4000.0; ms_filter_call_method(src_sinus,MSF_SOURCER_SINUSOID_SET_RATE,&fe); int fe_int=cast(int)round(fe); ms_filter_call_method(snk_sndcrd,MS_FILTER_SET_SAMPLE_RATE,&fe_int); string numefisier="file_givenname.bin"; ms_filter_call_method(snk_binfile,MSF_SINKER_BINARYFILE_OPEN,cast(void*)&numefisier); ms_filter_link(src_sinus,0,prc_split1,0); ms_filter_link(prc_split1,0,cnv_dbl2int16_t,0); ms_filter_link(prc_split1,1,snk_binfile,0); ms_filter_link(cnv_dbl2int16_t,0,snk_sndcrd,0); ticker=ms_ticker_new(); ms_ticker_attach(ticker,src_sinus); //START Thread.sleep(dur!("seconds")(3)); ms_ticker_detach(ticker,src_sinus); //STOP ms_ticker_destroy(ticker); ms_filter_call_method_noarg(snk_binfile,MSF_SINKER_BINARYFILE_CLOSE); ms_exit(); printf("-------STOP PROGRAM-------\n"); return 0; } ============================================================== Finally: thank you very much for your help! I expected D to be a sort of "better C with *facultative* classes" but I find it to be
Mar 27 2012
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/27/2012 02:20 PM, akaz wrote:

 what is the equivalent of
 std.stream.File.writeBlock(const void* buffer, size_t size)? I see there
 is a std.stdio.rawWrite(T)(in T[] buffer);

 But, my data is: a (byte*) pointer and a length. How do I write
 something like
 std.stream.File.writeblock(cast(byte*)p,cast(int)len) using
 std.stdio.File.rawWrite?
D has this helpful syntax of treating a raw pointer as a slice. Note p[0..length] below: import std.stdio; void main() { byte[] bytes = [ 81, 82, 83, 84, 85 ]; byte * p = &(bytes[1]); size_t length = 3; auto file = File("raw_written_bytes", "w"); file.rawWrite(p[0..length]); }
 Yes, that should be the case. f is the mother structure (a pointer
 towards a MSFilter structure) that should never disappear and f.data
 should not be assigned somewhere else.
How is all that memory allocated?
 I still cannot grasp
 that fundamental thing when a class instance is a variable and when it
 is a pointer
If you don't mind, your code has way too many pointers. :) As a person coming from C++, here is how I made sense of it: auto var = new MyClass(); The line above has two entities: 1) An anonymous MyClass object on the right-hand side which belongs to the runtime. It will be garbage collected later. 2) The 'class variable' on the left-hand side. This is the handle to that object. You can think of this as being implemented as a pointer behind the scene, but there is no pointer in D with classes. To complicate matters, you can spell out the type of 'var': MyClass var = new MyClass(); Very confusing, but the actual types of the left-hand and right-hand sides are still different: "class variable" vs. "class object".
 ; when is T x;
Prefer that one until it doesn't compile. :)
 and when is T* x = new T();
That is needed when T is a value type (e.g. a struct) and that you want to handle its lifetime manually.
 or, when is T* x=(T*)calloc(1,sizeof(T));)
Since calloc() is a C library function, you must use a T* there. Speaking of which, is f.data in such a memory that GC is not aware of? Then your class reference in there will not keep the File object alive. You must call GC.addRange() to let GC know that you have pointers into the GC's memory. A better thing to do may be to call GC.calloc() from the core.memory module. (Hmmm. Maybe I will translate this chapter next: http://ddili.org/ders/d/bellek_yonetimi.html )
 I expected D to be a sort of

 Is my vision correct?
from many languages. :) Ali
Mar 27 2012
prev sibling parent reply "akaz" <nemo utopia.com> writes:
OK, I converted into using the std.stdio.File. Without success, 
the programs till crashes.

However, in the meantime:

A) why there is no parameter-less constructor for std.stdio.File? 
I would like to have into my "init" function: s.filedesc=new 
File() and, then, in my setter "open" method 
s.filedesc.open(name,mode). Because I have no such constructor, I 
am forced to have in the "init": s.filedesc=null; and in the 
"open": s.filedesc=new File(name,mode). However, in that case, 
what use for the std.stdio.File.open method? If the name and the 
mode *must* be known at the construction time, then why ask those 
once more for the std.stdio.File.open() method? I am forced to 
open, first, a dummy file (in the constructor), only to be able 
to call, later, the std.stdio.File.open() method with the correct 
file name?

B) In my function:
private int msf_open(MSFilter* f, void* arg){ //a setter
     
printf("msf_binfile_open-start\n============================\n");
	MSF_State* s=cast(MSF_State*)f.data;
	ms_mutex_lock(&(f.lock));
	s.filedesc = new File(*(cast(string*)arg),"w+b");
	printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc);
	writef("s.filedesc.isOpen=%b+++++++++++++++++++++\n",s.filedesc.isOpen);
     
writef("s.filedesc.name=%s+++++++++++++++++++++\n",s.filedesc.name);
     
writef("s.filedesc.size=%d+++++++++++++++++++++\n",s.filedesc.size);
     ms_mutex_unlock(&(f.lock));
	printf("msf_binfile_open-stop\n============================\n");
	return 0;
}

can you tell me if the line s.filedesc=new 
File(*(cast(string*)arg),"w+b"); PROPAGATES the change into 
f.data? (recall that MSF_State* s=cast(MSF_State*)f.data;). I 
should also force, at the end of the function (just before 
return), something like: free(f.data); f.data=s; to propagate 
this?

As dumb as it may seem: is my "s" variable in MSF_State* 
s=cast(MSF_State*)f.data; a POINTER or a VALUE? I should write 
s->filedesc? Or, maybe, (*s).filedesc? I am a bit lost between 
pointers (s->x or (*s).x) and values (s.x). For structures there 
are pointers, for classes there are no pointers?

Finally, the program crash on the same line, when trying to write 
something in the file. Irony is that the s.filedesc.isOpen 
shows... 1.

Here is my new "msf_sinker_binaryfile.d file:

=======================msf_sinker_binaryfile.d======================
module msf_sinker_binaryfile;
import std.stdio;

import mediastreamer2_layer;
import msf_commons;

const uint MSF_SINKER_BINARYFILE_OPEN = 
MS_FILTER_METHOD!(byte)(cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID,0);
const uint MSF_SINKER_BINARYFILE_CLOSE = 
MS_FILTER_METHOD_NO_ARG(cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID,1);

private struct _MSF_State{
	File* filedesc; //file descriptor
};
private alias _MSF_State MSF_State;

private void msf_init(MSFilter* f){ //a constructor
     
printf("msf_binfile_init-start\n============================\n");
	MSF_State* s=ms_new!(MSF_State)(1);
	s.filedesc = null;
	f.data=s;
	printf("msf_binfile_init-stop\n============================\n");
}

private int msf_open(MSFilter* f, void* arg){ //a setter
     
printf("msf_binfile_open-start\n============================\n");
	MSF_State* s=cast(MSF_State*)f.data;
	ms_mutex_lock(&(f.lock));
	s.filedesc = new File(*(cast(string*)arg),"w+b");
	printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc);
	writef("s.filedesc.isOpen=%b+++++++++++++++++++++\n",s.filedesc.isOpen);
     
writef("s.filedesc.name=%s+++++++++++++++++++++\n",s.filedesc.name);
     
writef("s.filedesc.size=%d+++++++++++++++++++++\n",s.filedesc.size);
     ms_mutex_unlock(&(f.lock));
	printf("msf_binfile_open-stop\n============================\n");
	return 0;
}

private void msf_process(MSFilter* f){ //a run() method
     
printf("msf_binfile_process-start\n============================\n");
	MSF_State* s=cast(MSF_State*)f.data;
	mblk_t* m;
	while((m=ms_queue_get(f.inputs[0]))!=null){ //reading samples 
from input
		ms_mutex_lock(&(f.lock));
		int len=cast(int)((m.b_wptr-m.b_rptr)); //length of message 
data block
		byte* p=cast(byte*)m.b_rptr;
		/*printf("----------------------------\n");
         for(int idx=0; idx<len; idx++){
             printf("d_data[%d]=%d\n",idx,d_data[idx]);
         }
		printf("----------------------------\n");*/
		//File filedesc;
		//filedesc.open("newfile.bin","w+b");
		printf("s.filedesc=%p+++++++++++++++++++++\n",s.filedesc);
         
writef("s.filedesc.isOpen=%b+++++++++++++++++++++\n",s.filedesc.isOpen);
         
//writef("s.filedesc.name=%s+++++++++++++++++++++\n",s.filedesc.name); 
//SEGFAULT
         
//writef("s.filedesc.size=%d+++++++++++++++++++++\n",s.filedesc.size); 
//SEGFAULT
		s.filedesc.writefln("This writes a string to the file."); 
//SEGFAULT
		//s.filedesc.writeBlock(p,len);
		//filedesc.close();
		ms_mutex_unlock(&(f.lock));
		freemsg(m);
	}
     
printf("msf_binfile_process-start\n============================\n");
}

private int msf_close(MSFilter* f, void* arg){ //an unsetter
	MSF_State* s=cast(MSF_State*)f.data;
	ms_mutex_lock(&(f.lock));
     s.filedesc.close();
	ms_mutex_unlock(&(f.lock));
	return 0;
}

private void msf_uninit(MSFilter* f){ //a destructor
	MSF_State* s=cast(MSF_State*)f.data;
     msf_close(f, null);
	ms_free(s);
}

private immutable MSFilterMethod[3] msf_methods=[
	{id:MSF_SINKER_BINARYFILE_OPEN,method:cast(MSFilterMethodFunc)&msf_open},
	{id:MSF_SINKER_BINARYFILE_CLOSE,method:cast(MSFilterMethodFunc)&msf_close},
	{0,null}
];

immutable MSFilterDesc msf_sinker_binaryfile_desc={
	id:cast(MSFilterId)MSFilterIdNew.MSF_SINKER_BINARYFILE_ID,
	name:"MSFileSink",
	text:"File sink",
	category:MSFilterCategory.MS_FILTER_OTHER,
	ninputs:1,
	noutputs:0,
	init:cast(MSFilterFunc)&msf_init,
	process:cast(MSFilterFunc)&msf_process,
	uninit:cast(MSFilterFunc)&msf_uninit,
	methods:cast(MSFilterMethod*)&msf_methods[0]
};
==============================================================

and here is the output of the program:

-------START PROGRAM-------
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0
ALSA lib control.c:951:(snd_ctl_open_noupdate) Invalid CTL 
default:0
ortp-warning-Could not attach mixer to card: Invalid argument
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:0
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 0
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:0
ortp-warning-Strange, sound card HDA Intel does not seems to be 
capable of anything, retrying with plughw...
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1
ALSA lib control.c:951:(snd_ctl_open_noupdate) Invalid CTL 
default:1
ortp-warning-Could not attach mixer to card: Invalid argument
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:1
ALSA lib conf.c:4687:(snd_config_expand) Unknown parameters 1
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default:1
ortp-warning-Strange, sound card HDA ATI HDMI does not seems to 
be capable of anything, retrying with plughw...
ortp-warning-Strange, sound card HDA ATI HDMI seems totally 
unusable.
msf_binfile_init-start
============================
msf_binfile_init-stop
============================
msf_set_freq-start
============================
msf_set_freq-stop
============================
msf_set_rate-start
============================
msf_set_rate-stop
============================
msf_binfile_open-start
============================
s.filedesc=0x7ff83baacff0+++++++++++++++++++++
s.filedesc.isOpen=1+++++++++++++++++++++
s.filedesc.name=file_givenname.bin+++++++++++++++++++++
s.filedesc.size=0+++++++++++++++++++++
msf_binfile_open-stop
============================
msf_sinusoid_process-start
============================
s.rate=4000.000000============================
msf_sinusoid_process-stop
============================
msf_split_process-start
============================
msf_split_process-stop
============================
msf_dbl2int16_process-start
============================
msf_dbl2int16_process-stop
============================
ortp-warning-alsa_set_params: periodsize:0 Using 64
ortp-warning-alsa_set_params: period:8 Using 8
msf_binfile_process-start
============================
s.filedesc=0x7ff83baacff0+++++++++++++++++++++
s.filedesc.isOpen=1+++++++++++++++++++++
Segmentation fault (core dumped)

Any help?
Mar 27 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/27/2012 02:57 PM, akaz wrote:

 B) In my function:
 private int msf_open(MSFilter* f, void* arg){ //a setter
 printf("msf_binfile_open-start\n============================\n");
 MSF_State* s=cast(MSF_State*)f.data;
 ms_mutex_lock(&(f.lock));
 s.filedesc = new File(*(cast(string*)arg),"w+b");
Judging from your free(f.data) proposal below, I think the problem is on the previous line: the object is allocated in GC's memory but s.filedesc is in a memory that GC is not scanning. You must call GC.addRange() when you allocate the memory that s.filedesc is living on.
 can you tell me if the line s.filedesc=new
 File(*(cast(string*)arg),"w+b"); PROPAGATES the change into f.data?
Yes. It is the same as in C.
 (recall that MSF_State* s=cast(MSF_State*)f.data;). I should also force,
 at the end of the function (just before return), something like:
 free(f.data); f.data=s; to propagate this?
Not to propagate, but you may have to call free() to avoid a leak.
 As dumb as it may seem: is my "s" variable in MSF_State*
 s=cast(MSF_State*)f.data; a POINTER or a VALUE?
A pointer just like in C.
I should write
 s->filedesc? Or, maybe, (*s).filedesc?
That syntax has been useless even in C. (Although it communicates something to the reader.) The compiler could use the dot operator and do the right thing depending on whether the left-hand side was a pointer or an object. D does not have the -> operator.
 I am a bit lost between pointers
 (s->x or (*s).x) and values (s.x). For structures there are pointers,
 for classes there are no pointers?
Yes. Ali
Mar 27 2012
parent reply "akaz" <nemo utopia.com> writes:
 I am a bit lost between pointers
 (s->x or (*s).x) and values (s.x). For structures there are
pointers,
 for classes there are no pointers?
Yes. Ali
And migrating from std.stream.File (which was a class) to std.stdio.File (which is a structure) lost me completely. Why, in fact, std.stream.File is a structure and not a class? Citing: http://dlang.org/phobos/std_stdio.html struct File; Encapsulates a FILE*. Generally D does not attempt to provide thin wrappers over equivalent functions in the C standard library, but manipulating FILE* values directly is unsafe and error-prone in many ways. The File type ensures safe manipulation, automatic file closing, and a lot of convenience. The underlying FILE* handle is maintained in a reference-counted manner, such that as soon as the last File variable bound to a given FILE* goes out of scope, the underlying FILE* is automatically closed. May I disable that reference counting? I do not get how to use GC.addRange(). Can you, please, direct me towards an example? You seem to be right, the f and f.data variables are allocated into my C code, so they are invisible to the garbage collector. BUT!!! Is there any way to disable that garbage collector straight from the beginning? Maybe a compiler flag? I should also add that I allocated my structure with: (init) s.filedesc = cast(File*)GC.calloc(1,File.sizeof); (open) (*(s.filedesc)).open(*(cast(string*)arg),"w+b"); but without success, since the MSF_State* s=ms_new!(MSF_State)(1); line allocating the memory for s is esentially a C library function (a wrapper around it): extern(C){ //... void* ortp_malloc(size_t sz); T* ortp_new(T)(int count){ return cast(T*)ortp_malloc(T.sizeof*count); } alias ortp_new ms_new; //... } so that allocation is not visible to the garbage collector. My code has so many pointers because I took it from C, directly. Many of those pointers are also imposed by the underlying (C) library. I had no intention to extensively re-write my code, just to port it.
Mar 28 2012
parent reply "akaz" <nemo utopia.com> writes:
 I should also add that I allocated my structure with:

 (init)
 s.filedesc = cast(File*)GC.calloc(1,File.sizeof);

 (open)
 (*(s.filedesc)).open(*(cast(string*)arg),"w+b");
OMG! That solution works! Except that I was making a silly mistake and thought that GC.alloc() prototype is similar to C's calloc (since it has two parameters). I fact, after writing: (init) s.filedesc = cast(File*)GC.calloc(File.sizeof*1); (open) (*(s.filedesc)).open(*(cast(string*)arg),"w+b"); now, my file remains open and I can write inside! (The data inside is not really what it should be, but that, at least, is a debugging problem, not a segfault one). Thank you once again!
Mar 28 2012
parent reply "akaz" <nemo utopia.com> writes:
 (The data inside is not really what it should be, but that, at 
 least, is a debugging problem, not a segfault one).
Just to let you know that I did it. I was writing the good data (as double), but it was my verification test that assumed it to be int... Now I corrected it and it works! Any way to mark this thread as solved?
Mar 28 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/28/2012 05:09 AM, akaz wrote:
 (The data inside is not really what it should be, but that, at least,
 is a debugging problem, not a segfault one).
Just to let you know that I did it. I was writing the good data (as double), but it was my verification test that assumed it to be int... Now I corrected it and it works! Any way to mark this thread as solved?
Glad to hear it! :) I don't think there is a way of marking an NNTP thread as solved. Ali
Mar 28 2012