initial checkin
[platform/upstream/gstreamer.git] / gst / elements / gstfdsrc.c
1 /* Gnome-Streamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23
24 #include <gstfdsrc.h>
25
26
27 GstElementDetails gst_fdsrc_details = {
28   "Disk Source",
29   "Source/File",
30   "Synchronous read from a file",
31   VERSION,
32   "Erik Walthinsen <omega@cse.ogi.edu>",
33   "(C) 1999",
34 };
35
36
37 /* FdSrc signals and args */
38 enum {
39   /* FILL ME */
40   LAST_SIGNAL
41 };
42
43 enum {
44   ARG_0,
45   ARG_LOCATION,
46   ARG_BYTESPERREAD,
47   ARG_OFFSET,
48 };
49
50
51 static void gst_fdsrc_class_init(GstFdSrcClass *klass);
52 static void gst_fdsrc_init(GstFdSrc *fdsrc);
53 static void gst_fdsrc_set_arg(GtkObject *object,GtkArg *arg,guint id);
54 static void gst_fdsrc_get_arg(GtkObject *object,GtkArg *arg,guint id);
55
56 static void gst_fdsrc_push(GstSrc *src);
57 static void gst_fdsrc_push_region(GstSrc *src,gulong offset,gulong size);
58
59
60 static GstSrcClass *parent_class = NULL;
61 static guint gst_fdsrc_signals[LAST_SIGNAL] = { 0 };
62
63 GtkType
64 gst_fdsrc_get_type(void) {
65   static GtkType fdsrc_type = 0;
66
67   if (!fdsrc_type) {
68     static const GtkTypeInfo fdsrc_info = {
69       "GstFdSrc",
70       sizeof(GstFdSrc),
71       sizeof(GstFdSrcClass),
72       (GtkClassInitFunc)gst_fdsrc_class_init,
73       (GtkObjectInitFunc)gst_fdsrc_init,
74       (GtkArgSetFunc)gst_fdsrc_set_arg,
75       (GtkArgGetFunc)gst_fdsrc_get_arg,
76       (GtkClassInitFunc)NULL,
77     };
78     fdsrc_type = gtk_type_unique(GST_TYPE_SRC,&fdsrc_info);
79   }
80   return fdsrc_type;
81 }
82
83 static void
84 gst_fdsrc_class_init(GstFdSrcClass *klass) {
85   GtkObjectClass *gtkobject_class;
86   GstSrcClass *gstsrc_class;
87
88   gtkobject_class = (GtkObjectClass*)klass;
89   gstsrc_class = (GstSrcClass*)klass;
90
91   parent_class = gtk_type_class(GST_TYPE_SRC);
92
93   gtk_object_add_arg_type("GstFdSrc::location", GTK_TYPE_STRING,
94                           GTK_ARG_WRITABLE, ARG_LOCATION);
95   gtk_object_add_arg_type("GstFdSrc::bytesperread", GTK_TYPE_INT,
96                           GTK_ARG_READWRITE, ARG_BYTESPERREAD);
97   gtk_object_add_arg_type("GstFdSrc::offset", GTK_TYPE_INT,
98                           GTK_ARG_READWRITE, ARG_OFFSET);
99
100   gtkobject_class->set_arg = gst_fdsrc_set_arg;
101   gtkobject_class->get_arg = gst_fdsrc_get_arg;
102
103   gstsrc_class->push = gst_fdsrc_push;
104   /* we nominally can't (won't) do async */
105   gstsrc_class->push_region = NULL;
106 }
107
108 static void gst_fdsrc_init(GstFdSrc *fdsrc) {
109   fdsrc->srcpad = gst_pad_new("src",GST_PAD_SRC);
110   gst_element_add_pad(GST_ELEMENT(fdsrc),fdsrc->srcpad);
111
112   fdsrc->fd = 0;
113   fdsrc->curoffset = 0;
114   fdsrc->bytes_per_read = 4096;
115   fdsrc->seq = 0;
116 }
117
118
119 static void gst_fdsrc_set_arg(GtkObject *object,GtkArg *arg,guint id) {
120   GstFdSrc *src;
121   int fd;
122
123   /* it's not null if we got it, but it might not be ours */
124   g_return_if_fail(GST_IS_FDSRC(object));
125   src = GST_FDSRC(object);
126
127   switch(id) {
128     case ARG_LOCATION:
129       /* the element must be stopped in order to do this */
130       g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING));
131
132       /* if we get a NULL, consider it to be a fd of 0 */
133       if (GTK_VALUE_STRING(*arg) == NULL) {
134         src->fd = 0;
135         gst_element_set_state(GST_ELEMENT(object),~GST_STATE_COMPLETE);
136       /* otherwise set the new filename */
137       } else {
138         if (sscanf(GTK_VALUE_STRING(*arg),"%d",&fd))
139           src->fd = fd;
140         gst_element_set_state(GST_ELEMENT(object),GST_STATE_COMPLETE);
141       }
142       break;
143     case ARG_BYTESPERREAD:
144       src->bytes_per_read = GTK_VALUE_INT(*arg);
145       break;
146     default:
147       break;
148   }
149 }
150
151 static void gst_fdsrc_get_arg(GtkObject *object,GtkArg *arg,guint id) {
152   GstFdSrc *src;
153
154   /* it's not null if we got it, but it might not be ours */
155   g_return_if_fail(GST_IS_FDSRC(object));
156   src = GST_FDSRC(object);
157
158   switch (id) {
159     case ARG_BYTESPERREAD:
160       GTK_VALUE_INT(*arg) = src->bytes_per_read;
161       break;
162     case ARG_OFFSET:
163       GTK_VALUE_INT(*arg) = src->curoffset;
164       break;
165     default:
166       arg->type = GTK_TYPE_INVALID;
167       break;
168   }
169 }
170
171 void gst_fdsrc_push(GstSrc *src) {
172   GstFdSrc *fdsrc;
173   GstBuffer *buf;
174   glong readbytes;
175
176   g_return_if_fail(src != NULL);
177   g_return_if_fail(GST_IS_FDSRC(src));
178   fdsrc = GST_FDSRC(src);
179
180   /* create the buffer */
181   // FIXME: should eventually use a bufferpool for this
182   buf = gst_buffer_new();
183   g_return_if_fail(buf);
184
185   /* allocate the space for the buffer data */
186   GST_BUFFER_DATA(buf) = g_malloc(fdsrc->bytes_per_read);
187   g_return_if_fail(GST_BUFFER_DATA(buf) != NULL);
188
189   /* read it in from the file */
190   readbytes = read(fdsrc->fd,GST_BUFFER_DATA(buf),fdsrc->bytes_per_read);
191   if (readbytes == 0) {
192     gst_src_signal_eos(GST_SRC(fdsrc));
193     return;
194   }
195
196   /* if we didn't get as many bytes as we asked for, we're at EOF */
197   if (readbytes < fdsrc->bytes_per_read) {
198     // FIXME: set the buffer's EOF bit here
199   }
200   GST_BUFFER_OFFSET(buf) = fdsrc->curoffset;
201   GST_BUFFER_SIZE(buf) = readbytes;
202   fdsrc->curoffset += readbytes;
203
204   /* we're done, push the buffer off now */
205   gst_pad_push(fdsrc->srcpad,buf);
206 }