2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include <sys/types.h>
24 #include <gstdisksrc.h>
27 GstElementDetails gst_disksrc_details = {
30 "Synchronous read from a file",
32 "Erik Walthinsen <omega@cse.ogi.edu>",
37 /* DiskSrc signals and args */
51 static void gst_disksrc_class_init(GstDiskSrcClass *klass);
52 static void gst_disksrc_init(GstDiskSrc *disksrc);
53 static void gst_disksrc_set_arg(GtkObject *object,GtkArg *arg,guint id);
54 static void gst_disksrc_get_arg(GtkObject *object,GtkArg *arg,guint id);
56 static void gst_disksrc_push(GstSrc *src);
57 static void gst_disksrc_push_region(GstSrc *src,gulong offset,gulong size);
58 static gboolean gst_disksrc_change_state(GstElement *element,
59 GstElementState state);
62 static GstSrcClass *parent_class = NULL;
63 static guint gst_disksrc_signals[LAST_SIGNAL] = { 0 };
66 gst_disksrc_get_type(void) {
67 static GtkType disksrc_type = 0;
70 static const GtkTypeInfo disksrc_info = {
73 sizeof(GstDiskSrcClass),
74 (GtkClassInitFunc)gst_disksrc_class_init,
75 (GtkObjectInitFunc)gst_disksrc_init,
76 (GtkArgSetFunc)gst_disksrc_set_arg,
77 (GtkArgGetFunc)gst_disksrc_get_arg,
78 (GtkClassInitFunc)NULL,
80 disksrc_type = gtk_type_unique(GST_TYPE_SRC,&disksrc_info);
86 gst_disksrc_class_init(GstDiskSrcClass *klass) {
87 GtkObjectClass *gtkobject_class;
88 GstElementClass *gstelement_class;
89 GstSrcClass *gstsrc_class;
91 gtkobject_class = (GtkObjectClass*)klass;
92 gstelement_class = (GstElementClass*)klass;
93 gstsrc_class = (GstSrcClass*)klass;
95 parent_class = gtk_type_class(GST_TYPE_SRC);
97 gtk_object_add_arg_type("GstDiskSrc::location", GTK_TYPE_STRING,
98 GTK_ARG_READWRITE, ARG_LOCATION);
99 gtk_object_add_arg_type("GstDiskSrc::bytesperread", GTK_TYPE_INT,
100 GTK_ARG_READWRITE, ARG_BYTESPERREAD);
101 gtk_object_add_arg_type("GstDiskSrc::offset", GTK_TYPE_INT,
102 GTK_ARG_READWRITE, ARG_OFFSET);
104 gtkobject_class->set_arg = gst_disksrc_set_arg;
105 gtkobject_class->get_arg = gst_disksrc_get_arg;
107 gstelement_class->change_state = gst_disksrc_change_state;
109 gstsrc_class->push = gst_disksrc_push;
110 /* we nominally can't (won't) do async */
111 gstsrc_class->push_region = NULL;
114 static void gst_disksrc_init(GstDiskSrc *disksrc) {
115 disksrc->srcpad = gst_pad_new("src",GST_PAD_SRC);
116 gst_element_add_pad(GST_ELEMENT(disksrc),disksrc->srcpad);
118 disksrc->filename = NULL;
120 disksrc->curoffset = 0;
121 disksrc->bytes_per_read = 4096;
126 static void gst_disksrc_set_arg(GtkObject *object,GtkArg *arg,guint id) {
129 /* it's not null if we got it, but it might not be ours */
130 g_return_if_fail(GST_IS_DISKSRC(object));
131 src = GST_DISKSRC(object);
135 /* the element must be stopped in order to do this */
136 // g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING));
138 if (src->filename) g_free(src->filename);
139 /* clear the filename if we get a NULL (is that possible?) */
140 if (GTK_VALUE_STRING(*arg) == NULL) {
141 src->filename = NULL;
142 gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE);
143 /* otherwise set the new filename */
145 src->filename = g_strdup(GTK_VALUE_STRING(*arg));
146 gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE);
149 case ARG_BYTESPERREAD:
150 src->bytes_per_read = GTK_VALUE_INT(*arg);
157 static void gst_disksrc_get_arg(GtkObject *object,GtkArg *arg,guint id) {
160 /* it's not null if we got it, but it might not be ours */
161 g_return_if_fail(GST_IS_DISKSRC(object));
162 src = GST_DISKSRC(object);
166 GTK_VALUE_STRING(*arg) = src->filename;
168 case ARG_BYTESPERREAD:
169 GTK_VALUE_INT(*arg) = src->bytes_per_read;
172 GTK_VALUE_INT(*arg) = src->curoffset;
175 arg->type = GTK_TYPE_INVALID;
180 void gst_disksrc_push(GstSrc *src) {
185 g_return_if_fail(src != NULL);
186 g_return_if_fail(GST_IS_DISKSRC(src));
187 g_return_if_fail(GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN));
188 disksrc = GST_DISKSRC(src);
190 /* create the buffer */
191 // FIXME: should eventually use a bufferpool for this
192 buf = gst_buffer_new();
193 g_return_if_fail(buf);
195 /* allocate the space for the buffer data */
196 GST_BUFFER_DATA(buf) = g_malloc(disksrc->bytes_per_read);
197 g_return_if_fail(GST_BUFFER_DATA(buf) != NULL);
199 /* read it in from the file */
200 readbytes = read(disksrc->fd,GST_BUFFER_DATA(buf),disksrc->bytes_per_read);
201 if (readbytes == 0) {
202 gst_src_signal_eos(GST_SRC(disksrc));
206 /* if we didn't get as many bytes as we asked for, we're at EOF */
207 if (readbytes < disksrc->bytes_per_read)
208 GST_BUFFER_FLAG_SET(buf,GST_BUFFER_EOS);
209 GST_BUFFER_OFFSET(buf) = disksrc->curoffset;
210 GST_BUFFER_SIZE(buf) = readbytes;
211 disksrc->curoffset += readbytes;
213 /* we're done, push the buffer off now */
214 gst_pad_push(disksrc->srcpad,buf);
218 /* open the file, necessary to go to RUNNING state */
219 static gboolean gst_disksrc_open_file(GstDiskSrc *src) {
220 g_return_if_fail(!GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN));
223 src->fd = open(src->filename,O_RDONLY);
226 gst_element_error(GST_ELEMENT(src),"opening file");
229 GST_FLAG_SET(src,GST_DISKSRC_OPEN);
234 static void gst_disksrc_close_file(GstDiskSrc *src) {
235 g_return_if_fail(GST_FLAG_IS_SET(src,GST_DISKSRC_OPEN));
240 /* zero out a lot of our state */
245 GST_FLAG_UNSET(src,GST_DISKSRC_OPEN);
248 static gboolean gst_disksrc_change_state(GstElement *element,
249 GstElementState state) {
250 g_return_if_fail(GST_IS_DISKSRC(element));
253 case GST_STATE_RUNNING:
254 if (!gst_disksrc_open_file(GST_DISKSRC(element)))
257 case ~GST_STATE_RUNNING:
258 gst_disksrc_close_file(GST_DISKSRC(element));
264 if (GST_ELEMENT_CLASS(parent_class)->change_state)
265 return GST_ELEMENT_CLASS(parent_class)->change_state(element,state);