Showing posts with label c. Show all posts
Showing posts with label c. Show all posts

Friday, January 30, 2009

boilerplate

When I read a blog about boilerplate in Qt, I tried to remember how to write boilerplate code with Gobject. The following code is a frame that I took from 1 year ago I wrote. It is not really hard to understand or write, just need to copy & paste, or use simple tool to auto generate the code. It always need to write more lines in C (GObject) than using C++ for OO. But I don't feel the goodness. I am not feel that is the benifit of C, so I am not sure OO is really good for a Unix developer, so if I can avoid I would avoid the idea of OO in unix platform. (Linux Kernel is not written in OO)


/* macros*/
G_BEGIN_DECLS

#define GST_TYPE_MIDISRC (gst_my_midisrc_get_type())
#define GST_MIDISRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MIDISRC,GstMidisrc))
#define GST_MIDISRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MIDISRC,GstMidisrcClass))
#define GST_IS_MIDISRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MIDISRC))
#define GST_IS_MIDISRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MIDISRC))

/* standard function returning type information */
GType gst_my_midisrc_get_type (void);


/* definition a class of this element */
typedef struct _GstMidisrc GstMidisrc;
struct _GstMidisrc
{
GstBaseSrc parent;
[...]
};

typedef struct _GstMidisrcClass GstMidisrcClass;

struct _GstMidisrcClass
{
GstBaseSrcClass parent_class;
};

G_END_DECLS


Now we can make the boilerplate:

GST_BOILERPLATE (GstMidisrc, gst_my_midisrc, GstBaseSrc, GST_TYPE_BASE_SRC);


After that is the element details.


static GstElementDetails midisrc_details = {
"A Gstreamer Plug-in",
"Src/Audio",
"audio src for GStreamer Plug-in",
""
};

/* set detail with _base_init function when register the plugin */
static void
gst_my_midisrc_base_init (gpointer klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);

gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_factory));

gst_element_class_set_details (element_class, &midisrc_details);

}


Then implementation:



/* create the class, here we define which function need to be re-implmented from the base class, and add property for the class */
static void
gst_my_midisrc_class_init (GstMidisrcClass *klass)
{

GObjectClass *gobject_class;
GstBaseSrcClass *basesrc_class;
gobject_class = G_OBJECT_CLASS (klass);
basesrc_class = GST_BASE_SRC_CLASS (klass);
gobject_class->set_property = gst_midisrc_set_property;
gobject_class->get_property = gst_midisrc_get_property;


/* basesrc_class->get_caps = gst_midisrc_get_caps;
basesrc_class->set_caps = gst_midisrc_set_caps; */
basesrc_class->start = gst_midisrc_start;
basesrc_class->stop = gst_midisrc_stop;
basesrc_class->create = gst_midisrc_create;

/* install a property for the class as an example */
g_object_class_install_property (
gobject_class, ARG_LOCATION,
g_param_spec_string ("location", "File Location",
"Location of the file to read", NULL, G_PARAM_READWRITE));



}

/* create the object */
static void
gst_my_midisrc_init (GstMidisrc *midisrc, GstMidisrcClass *klass)
{
[...]
}



Now the reset part:


/* set property sample */
static gboolean
gst_midisrc_set_location (GstMidisrc * src, const gchar * location)
{
/* the element must be stopped in order to do this */
GST_STATE_LOCK (src);
{
GstState state;

state = GST_STATE (src);
if (state != GST_STATE_READY && state != GST_STATE_NULL)
goto wrong_state;
}
GST_STATE_UNLOCK (src);

g_free (src->filename);
g_free (src->uri);

/* clear the filename if we get a NULL (is that possible?) */
if (location == NULL) {
src->filename = NULL;
src->uri = NULL;
} else {
src->filename = g_strdup (location);
}
return TRUE;

/* ERROR */
wrong_state:
{
GST_DEBUG_OBJECT (src, "setting location in wrong state");
GST_STATE_UNLOCK (src);
return FALSE;
}
}
static void
gst_midisrc_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec)
{
GstMidisrc *midisrc;
int tmp = 0;
g_return_if_fail (GST_IS_MIDISRC (object));
midisrc = GST_MIDISRC (object);

switch (prop_id) {
case ARG_LOCATION:
gst_midisrc_set_location(midisrc, g_value_get_string (value));
printf("set location done!\n");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}

static void
gst_midisrc_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec)
{
GstMidisrc *midisrc;

g_return_if_fail (GST_IS_MIDISRC (object));
midisrc = GST_MIDISRC (object);

switch (prop_id) {
case ARG_LOCATION:
g_value_set_string(value, midisrc->filename);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}

static gboolean
gst_midisrc_start (GstBaseSrc * src)
{
GstMidisrc *midisrc = GST_MIDISRC (src);
[...]
}

static GstFlowReturn
gst_midisrc_create (GstBaseSrc * src,
guint64 offset,
guint length,
GstBuffer ** buffer)
{
GstMidisrc *midisrc = GST_MIDISRC (src);
if (midisrc->eos_reached)
return GST_FLOW_UNEXPECTED;
return( gst_midisrc_get_read (src, buffer));
}

static GstFlowReturn
gst_midisrc_get_read (GstBaseSrc * basesrc, GstBuffer ** buffer)
{
GstFlowReturn res;
GstMidisrc *midisrc = GST_MIDISRC (basesrc);
[...]

[...]
}


I would like to put my time on learning Git (I was heard git is written by a Unix kernal developer), for desktops, such as gnome or KDE I don't have a lot of interests, I may feel KDE is better since it is written in C++, but who knows.

Monday, August 25, 2008

fpos_t

When compile with gcc, it prompt "cannot convert fpos_t to long int".

Here is the solution:


long dataOffset;
fpos_t filepos;
...
dataOffset = filepos.__pos;

Monday, May 12, 2008

utils - ti memory data conversion

The ccs IDE provides a function to save memory data to a file, here is a saved file:

1651 1 10032238 0 300
0x00000000
0x00000000
0x00000000
0x00000000
....


It is a text file, with the first line, contains the memory address, the data length etc. From the next line, comes the data. Since the output is still the text file, I need to convert it to actual binary data. So I develop a little application to do the conversion. Not good on awk, or with sed, I use c programming language directly. C is such powerful.


#include < stdio.h>
#include < string.h>

#define LINE_MAX 256
char my_asc2hex(char a, char b)
{
char o;
if (a >= '0' && a <='9') a = a - '0';
if (a >= 'a' && a <='f') a = a - 'a' + 10;
if (a >= 'A' && a <='F') a = a - 'A' + 10;
if (b >= '0' && b <='9') b = b - '0';
if (b >= 'a' && b <='f') b = b - 'a' + 10;
if (b >= 'A' && b <='F') b = b - 'A' + 10;
o = a + b * 16;
return (o);
}
int main(int argc, char* argv[])
{
char line_buf[LINE_MAX];
char* lp;
FILE* fp, *fp_out;
char aa,bb,cc,dd;

if (argc < 3){
printf("%s ti_input_file output_file", argv[0]);
return 1;
}

fp = fopen(argv[1], "r");
if (fp == NULL) return 1;
fp_out = fopen(argv[2], "w+b");
if (fp_out == NULL) {
fclose(fp);
return 1;
}

for(;;) {
lp = fgets(line_buf, LINE_MAX, fp);
if (lp == NULL) goto main_exit;
if (*lp++ == '0' && *lp++ == 'x' && strlen(lp) >= 8) {
aa = my_asc2hex(*lp++, *lp++);
bb = my_asc2hex(*lp++, *lp++);
cc = my_asc2hex(*lp++, *lp++);
dd = my_asc2hex(*lp++, *lp++);

fwrite(&dd, 1, sizeof(char), fp_out);
fwrite(&cc, 1, sizeof(char), fp_out);
fwrite(&bb, 1, sizeof(char), fp_out);
fwrite(&aa, 1, sizeof(char), fp_out);
}
}

main_exit:
fclose(fp);
fclose(fp_out);
return 0;
}


I just need to pay attention to the byte order, for example, if it is "0x00004F99" from the input, the output will be "99 4F 00 00". BUT the confusing part is here:

if (*lp++ == '0' && *lp++ == 'x'...)
....
my_asc2hex(*lp++, *lp++);

In "if" condition, the evaluating is one by one, the first item "evaluate" first, then is the next, while in function, the "evaluation" of parameters is, the last item first (put on the stack first), and moves on previous items. so that is why the first parameter to my_asc2hex is the latter one. kind of confusing using pointer!