Add an fd param to set the file descriptor as an int
[platform/upstream/gstreamer.git] / plugins / elements / gstfdsrc.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstfdsrc.c: 
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29
30 #include <gstfdsrc.h>
31
32
33 GstElementDetails gst_fdsrc_details = {
34   "Disk Source",
35   "Source/File",
36   "LGPL",
37   "Synchronous read from a file",
38   VERSION,
39   "Erik Walthinsen <omega@cse.ogi.edu>",
40   "(C) 1999",
41 };
42
43
44 /* FdSrc signals and args */
45 enum {
46   /* FILL ME */
47   LAST_SIGNAL
48 };
49
50 enum {
51   ARG_0,
52   ARG_LOCATION,
53   ARG_BYTESPERREAD,
54   ARG_OFFSET,
55   ARG_FD,
56 };
57
58
59 static void             gst_fdsrc_class_init    (GstFdSrcClass *klass);
60 static void             gst_fdsrc_init          (GstFdSrc *fdsrc);
61
62 static void             gst_fdsrc_set_property  (GObject *object, guint prop_id, 
63                                                  const GValue *value, GParamSpec *pspec);
64 static void             gst_fdsrc_get_property  (GObject *object, guint prop_id, 
65                                                  GValue *value, GParamSpec *pspec);
66
67 static GstBuffer *      gst_fdsrc_get           (GstPad *pad);
68
69
70 static GstElementClass *parent_class = NULL;
71 /*static guint gst_fdsrc_signals[LAST_SIGNAL] = { 0 };*/
72
73 GType
74 gst_fdsrc_get_type (void) 
75 {
76   static GType fdsrc_type = 0;
77
78   if (!fdsrc_type) {
79     static const GTypeInfo fdsrc_info = {
80       sizeof(GstFdSrcClass),      NULL,
81       NULL,
82       (GClassInitFunc)gst_fdsrc_class_init,
83       NULL,
84       NULL,
85       sizeof(GstFdSrc),
86       0,
87       (GInstanceInitFunc)gst_fdsrc_init,
88     };
89     fdsrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstFdSrc", &fdsrc_info, 0);
90   }
91   return fdsrc_type;
92 }
93
94 static void
95 gst_fdsrc_class_init (GstFdSrcClass *klass) 
96 {
97   GObjectClass *gobject_class;
98
99   gobject_class = (GObjectClass*)klass;
100
101   parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
102
103   gst_element_class_install_std_props (
104           GST_ELEMENT_CLASS (klass),
105           "location",     ARG_LOCATION,     G_PARAM_WRITABLE,
106           "bytesperread", ARG_BYTESPERREAD, G_PARAM_READWRITE,
107           "offset",       ARG_OFFSET,       G_PARAM_READABLE,
108           NULL);
109
110   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FD,
111     g_param_spec_int ("fd", "fd", "An open file descriptor to read from",
112                       0, G_MAXINT, 0, G_PARAM_READWRITE));
113
114   gobject_class->set_property = gst_fdsrc_set_property;
115   gobject_class->get_property = gst_fdsrc_get_property;
116 }
117
118 static void gst_fdsrc_init(GstFdSrc *fdsrc) {
119   fdsrc->srcpad = gst_pad_new("src",GST_PAD_SRC);
120   gst_pad_set_get_function(fdsrc->srcpad,gst_fdsrc_get);
121   gst_element_add_pad(GST_ELEMENT(fdsrc),fdsrc->srcpad);
122
123   fdsrc->fd = 0;
124   fdsrc->curoffset = 0;
125   fdsrc->bytes_per_read = 4096;
126   fdsrc->seq = 0;
127 }
128
129
130 static void 
131 gst_fdsrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) 
132 {
133   GstFdSrc *src;
134   int fd;
135
136   /* it's not null if we got it, but it might not be ours */
137   g_return_if_fail (GST_IS_FDSRC (object));
138   
139   src = GST_FDSRC (object);
140
141   switch (prop_id) {
142     case ARG_LOCATION:
143       /* the element must not be playing in order to do this */
144       g_return_if_fail (GST_STATE (src) < GST_STATE_PLAYING);
145
146       /* if we get a NULL, consider it to be a fd of 0 */
147       if (g_value_get_string (value) == NULL) {
148         gst_element_set_state (GST_ELEMENT (object), GST_STATE_NULL);
149         src->fd = 0;
150       /* otherwise set the new filename */
151       } else {
152         if (sscanf (g_value_get_string (value), "%d", &fd))
153           src->fd = fd;
154       }
155       break;
156     case ARG_FD:
157       src->fd = g_value_get_int (value);
158       break;
159     case ARG_BYTESPERREAD:
160       src->bytes_per_read = g_value_get_int (value);
161       break;
162     default:
163       break;
164   }
165 }
166
167 static void 
168 gst_fdsrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) 
169 {
170   GstFdSrc *src;
171
172   /* it's not null if we got it, but it might not be ours */
173   g_return_if_fail (GST_IS_FDSRC (object));
174   
175   src = GST_FDSRC (object);
176
177   switch (prop_id) {
178     case ARG_BYTESPERREAD:
179       g_value_set_int (value, src->bytes_per_read);
180       break;
181     case ARG_OFFSET:
182       g_value_set_int64 (value, src->curoffset);
183       break;
184     case ARG_FD:
185       g_value_set_int (value, src->fd);
186       break;
187     default:
188       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
189       break;
190   }
191 }
192
193 static GstBuffer *
194 gst_fdsrc_get(GstPad *pad)
195 {
196   GstFdSrc *src;
197   GstBuffer *buf;
198   glong readbytes;
199
200   g_return_val_if_fail (pad != NULL, NULL);
201   src = GST_FDSRC(gst_pad_get_parent (pad));
202
203   /* create the buffer */
204   /* FIXME: should eventually use a bufferpool for this*/
205   buf = gst_buffer_new ();
206   g_return_val_if_fail (buf, NULL);
207
208   /* allocate the space for the buffer data */
209   GST_BUFFER_DATA(buf) = g_malloc(src->bytes_per_read);
210   g_return_val_if_fail(GST_BUFFER_DATA(buf) != NULL, NULL);
211
212   /* read it in from the file */
213   readbytes = read(src->fd,GST_BUFFER_DATA(buf),src->bytes_per_read);
214   /* if nothing was read, we're in eos */
215   if (readbytes == 0) {
216     gst_element_set_eos (GST_ELEMENT (src));
217     return GST_BUFFER (gst_event_new (GST_EVENT_EOS));
218   }
219
220   GST_BUFFER_OFFSET(buf) = src->curoffset;
221   GST_BUFFER_SIZE(buf) = readbytes;
222   src->curoffset += readbytes;
223
224   /* we're done, return the buffer */
225   return buf;
226 }