gstalsa.h 6.95 KB
Newer Older
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1
/*
2
3
4
 * Copyright (C) 2001 CodeFactory AB
 * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
 * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
5
 * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
21
22
23
24

#ifndef __GST_ALSA_H__
#define __GST_ALSA_H__

25
26
27
#define ALSA_PCM_NEW_HW_PARAMS_API
#define ALSA_PCM_NEW_SW_PARAMS_API

28
#include <alsa/asoundlib.h>
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
29
30
#include <gst/gst.h>

31
#define GST_ALSA_MAX_CHANNELS 64 /* we don't support more than 64 channels */
32
33
#define GST_ALSA_MIN_RATE 8000
#define GST_ALSA_MAX_RATE 192000
34
35
36
37
/* max allowed discontinuity in time units between timestamp and playback pointer 
   before killing/inserting samples 
   should be big enough to allow smoothing errors on different video formats */
#define GST_ALSA_DEFAULT_DISCONT (GST_SECOND / 10)
38

Benjamin Otte's avatar
Benjamin Otte committed
39
40
41
42
43
44
#define GST_ALSA(obj)			(G_TYPE_CHECK_INSTANCE_CAST(obj, GST_TYPE_ALSA, GstAlsa))
#define GST_ALSA_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST(klass, GST_TYPE_ALSA, GstAlsaClass))
#define GST_ALSA_GET_CLASS(obj)		(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_ALSA, GstAlsaClass))
#define GST_IS_ALSA(obj)		(G_TYPE_CHECK_INSTANCE_TYPE(obj, GST_TYPE_ALSA))
#define GST_IS_ALSA_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE(klass, GST_TYPE_ALSA))
#define GST_TYPE_ALSA			(gst_alsa_get_type())
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
45

Benjamin Otte's avatar
Benjamin Otte committed
46
47
48
49
50
#define GST_ALSA_SINK(obj)		(G_TYPE_CHECK_INSTANCE_CAST(obj, GST_TYPE_ALSA_SINK, GstAlsaSink))
#define GST_ALSA_SINK_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST(klass, GST_TYPE_ALSA_SINK, GstAlsaSinkClass))
#define GST_IS_ALSA_SINK(obj)		(G_TYPE_CHECK_INSTANCE_TYPE(obj, GST_TYPE_ALSA_SINK))
#define GST_IS_ALSA_SINK_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE(klass, GST_TYPE_ALSA_SINK))
#define GST_TYPE_ALSA_SINK		(gst_alsa_sink_get_type())
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
51

Benjamin Otte's avatar
Benjamin Otte committed
52
53
54
55
56
#define GST_ALSA_SRC(obj)		(G_TYPE_CHECK_INSTANCE_CAST(obj, GST_TYPE_ALSA_SRC, GstAlsaSrc))
#define GST_ALSA_SRC_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST(klass, GST_TYPE_ALSA_SRC, GstAlsaSrcClass))
#define GST_IS_ALSA_SRC(obj)		(G_TYPE_CHECK_INSTANCE_TYPE(obj, GST_TYPE_ALSA_SRC))
#define GST_IS_ALSA_SRC_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE(klass, GST_TYPE_ALSA_SRC))
#define GST_TYPE_ALSA_SRC		(gst_alsa_src_get_type())
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
57

Benjamin Otte's avatar
Benjamin Otte committed
58
59
60
61
62
#define GST_ALSA_CLOCK(obj)		(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_CLOCK,GstAlsaClock))
#define GST_ALSA_CLOCK_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_CLOCK,GstAlsaClockClass))
#define GST_IS_ALSA_CLOCK(obj)		(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_CLOCK))
#define GST_IS_ALSA_CLOCK_CLASS(obj)	(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_CLOCK))
#define GST_TYPE_ALSA_CLOCK		(gst_alsa_clock_get_type())
Benjamin Otte's avatar
Benjamin Otte committed
63

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
64
65
66
67
68
/* I would have preferred to avoid this variety of trickery, but without it i
 * can't tell whether I'm a source or a sink upon creation. */

typedef struct _GstAlsa GstAlsa;
typedef struct _GstAlsaClass GstAlsaClass;
69
70
71
72
typedef struct _GstAlsaSink GstAlsaSink;
typedef struct _GstAlsaSinkClass GstAlsaSinkClass;
typedef struct _GstAlsaSrc GstAlsaSrc;
typedef struct _GstAlsaSrcClass GstAlsaSrcClass;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
73

Benjamin Otte's avatar
Benjamin Otte committed
74
75
76
77
78
typedef struct _GstAlsaClock GstAlsaClock;
typedef struct _GstAlsaClockClass GstAlsaClockClass;

typedef GstClockTime (*GstAlsaClockGetTimeFunc) (GstAlsa *owner);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
79
enum {
80
81
  GST_ALSA_OPEN = GST_ELEMENT_FLAG_LAST,
  GST_ALSA_RUNNING,
Benjamin Otte's avatar
Benjamin Otte committed
82
  GST_ALSA_CAPS_NEGO,
83
  GST_ALSA_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 3,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
84
};
Benjamin Otte's avatar
Benjamin Otte committed
85
86
87
88
89
90
91
92
93
94
95
96
97
98
typedef enum {
  GST_ALSA_CAPS_PAUSE = 0,
  GST_ALSA_CAPS_RESUME,
  GST_ALSA_CAPS_SYNC_START
  /* add more */
} GstAlsaPcmCaps;
#define GST_ALSA_CAPS_IS_SET(obj, flag)		(GST_ALSA (obj)->pcm_caps & (1<<(flag)))
#define GST_ALSA_CAPS_SET(obj, flag, set)	G_STMT_START{  \
  if (set) { \
    (GST_ALSA (obj)->pcm_caps |= (1<<(flag))); \
  } else { \
    (GST_ALSA (obj)->pcm_caps &= ~(1<<(flag))); \
  } \
}G_STMT_END
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
99

Benjamin Otte's avatar
Benjamin Otte committed
100
101
typedef int (*GstAlsaTransmitFunction) (GstAlsa *this, snd_pcm_sframes_t *avail);

Benjamin Otte's avatar
Benjamin Otte committed
102
typedef struct {
103
104
105
  snd_pcm_format_t	format;
  guint			rate;
  gint			channels;  
Benjamin Otte's avatar
Benjamin Otte committed
106
} GstAlsaFormat;
107

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
108
struct _GstAlsa {
109
  GstElement			parent;
110

111
  /* array of GstAlsaPads */
112
  GstPad *			pad[GST_ALSA_MAX_CHANNELS];
113

114
115
116
117
  gchar *			device;
  snd_pcm_t *			handle;
  guint				pcm_caps;	/* capabilities of the pcm device, see GstAlsaPcmCaps */
  snd_output_t *		out;
118

119
120
121
  GstAlsaFormat *		format;		/* NULL if undefined */
  gboolean			mmap; 		/* use mmap transmit (fast) or read/write (sloooow) */
  GstAlsaTransmitFunction	transmit;
122

123
  /* latency / performance parameters */
124
125
  snd_pcm_uframes_t		period_size;
  unsigned int			period_count;
126

127
  gboolean			autorecover;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
128

Benjamin Otte's avatar
Benjamin Otte committed
129
  /* clocking */
130
131
132
  GstAlsaClock *		clock;		/* our provided clock */
  snd_pcm_uframes_t		transmitted; 	/* samples transmitted since last sync 
						   This thing actually is our master clock.
Benjamin Otte's avatar
Benjamin Otte committed
133
134
						   We will event insert silent samples or
						   drop some to sync to incoming timestamps.
135
136
						 */
  GstClockTime			max_discont;	/* max difference between current
137
138
  						   playback timestamp and buffers timestamps
						 */
Benjamin Otte's avatar
Benjamin Otte committed
139
};
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
140
struct _GstAlsaClass {
141
142
143
  GstElementClass		parent_class;

  snd_pcm_stream_t		stream;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
144

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  /* different transmit functions */
  GstAlsaTransmitFunction	transmit_mmap;
  GstAlsaTransmitFunction	transmit_rw;
};
struct _GstAlsaSink {
  GstAlsa			parent;
  /* array of the data on the channels */
  guint8 *			data[GST_ALSA_MAX_CHANNELS];		/* pointer into buffer */
  guint				size[GST_ALSA_MAX_CHANNELS];		/* sink: bytes left in buffer */
  GstBuffer *			buf[GST_ALSA_MAX_CHANNELS];		/* current buffer */
  guint				behaviour[GST_ALSA_MAX_CHANNELS]; 	/* 0 = data points into buffer (so unref when size == 0), 
									   1 = data should be freed, use buffer after that */
};
struct _GstAlsaSinkClass {
  GstAlsaClass			parent_class;
};
struct _GstAlsaSrc {
  GstAlsa			parent;
163
164
165

  GstBuffer *			buf[GST_ALSA_MAX_CHANNELS];
  GstBufferPool *		pool;
166
167
168
169
};
struct _GstAlsaSrcClass {
  GstAlsaClass			parent_class;
};
Benjamin Otte's avatar
Benjamin Otte committed
170
171
172
173
174
175
176

struct _GstAlsaClock {
  GstSystemClock		parent;

  GstAlsaClockGetTimeFunc	get_time;
  GstAlsa *			owner;

177
178
  GstClockTimeDiff		adjust; 	/* adjustment to real clock (recalculated when stopping) */
  GstClockTime			start_time;	/* time when the stream started (NONE when stopped) */
Benjamin Otte's avatar
Benjamin Otte committed
179
180
181
182
183
184
185
186
187
188
189
190
191

  GstClockTime			last_unlock;    /* time of last unlock request */
};

struct _GstAlsaClockClass {
  GstSystemClockClass 		parent_class;
};

GType 				gst_alsa_get_type		(void);
GType 				gst_alsa_sink_get_type		(void);
GType 				gst_alsa_src_get_type		(void);

GType                   	gst_alsa_clock_get_type		(void);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
192
193

#endif /* __ALSA_H__ */