File: spdif.h

package info (click to toggle)
vdr-plugin-bitstreamout 0.81-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 724 kB
  • ctags: 974
  • sloc: ansic: 8,974; makefile: 158; sh: 152
file content (146 lines) | stat: -rw-r--r-- 4,503 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 * spdif.h:	Access the S/P-DIF interface of sound cards supported by ALSA.
 *		for redirecting none audio streams (NO decoding!).
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
 *
 * Copyright (C) 2002-2005 Werner Fink, <werner@suse.de>
 */

#ifndef __SPDIF_H
#define __SPDIF_H

#include <sys/time.h>
#include <signal.h>
#include <alsa/asoundlib.h>
#include <vdr/thread.h>
#include "iec60958.h"
#include "bounce.h"
#include "bitstreamout.h"

#define EINTR_RETRY(exp)				\
    (__extension__ ({					\
	int __result;					\
	do { __result = (int) (exp);			\
	     if (__result < 0) pthread_yield();		\
	} while (__result < 0 && errno == EINTR);	\
	__result; }))

class cPsleep {
private:
    pthread_mutex_t mutex;
    pthread_cond_t  cond;
    struct timeval  now;
    struct timespec res;
public:
    cPsleep();
    ~cPsleep();
    void msec(int ms);
    void usec(int us);
};

class spdif {
private:
    // Thread locking
    cThread *thread;
    #define HOLD(thread) cThreadLock ThreadLock(thread)
    iec60958 *stream;
    virtual bool Stream(iec60958 *in);
    snd_pcm_t *out;
    snd_pcm_uframes_t burst_size;
    snd_pcm_uframes_t periods;
    snd_pcm_sframes_t delay;
    snd_pcm_sframes_t pause;
    snd_pcm_uframes_t buffer_size;
    snd_pcm_format_t  format;
    int count;
    size_t paysize;
#   define PCM_SILENT_10MS48KHZ	((10*48000)/1000)
    static uint_32 silent_buf[];
    frame_t silent;
    int fragsize;
    int period;
    typedef snd_pcm_sframes_t (*snd_pcm_writei_t)(snd_pcm_t *, const void *, snd_pcm_uframes_t);
    snd_pcm_writei_t writei;
    snd_pcm_status_t *status;
    snd_output_t *log;
    snd_aes_iec958_t ch;
    enum {
	FL_FIRST    = 0x00000001,	// Start and after Pause
	FL_IO       = 0x00000002,	// More frames in Forward() handled
	FL_CANPAUSE = 0x00000004,	// Hardware can do pause
	FL_UNDERRUN = 0x00000008,	// Underrun detected
	FL_VRPERIOD = 0x00000010,	// double frames in case of underrun
	FL_NOEXSYNC = 0x00000020,	// Synchronize() was not called before
	FL_BURSTRUN = 0x00000040,	// burst() active
	FL_PAUSE    = 0x00000080,	// Pause() called
	FL_OVERRUN  = 0x00000100,	// Overrun detected
	FL_REPEAT   = 0x00000200	// Repeat last frame upto 1 second
    };
    uint_32 ctrlbits;
    virtual void burst(const frame_t &pcm);
    struct timeval xrstart;
    inline bool xrepeat(void);
    inline void xunderrun(void);
    inline void xsuspend (void);
    // Block signals during handlers
    sigset_t oldset;
    virtual inline void block_signals(void);
    virtual inline void leave_signals(void);
    // buffer checking
    enum {SPDIF_LOW = -1, SPDIF_OK = 0, SPDIF_HIGH = 1};
    virtual int check(snd_pcm_status_t * status = NULL);
    struct {
	snd_pcm_uframes_t upper;
	snd_pcm_uframes_t lower;
	snd_pcm_uframes_t high;
	snd_pcm_uframes_t alarm;
    } buf;
    // Wait on close
    cMutex   _close;
    inline void Lock  (void) { _close.Lock();   };
    inline void Unlock(void) { _close.Unlock(); };
    // Option handling
    enum {SPDIF_CON, SPDIF_PRO};
    struct {
	unsigned int card;
	unsigned int device;
	unsigned int type;
	int first;
	int mdelay;
	int adelay;
	unsigned int iec958_aes3_con_fs_rate;
	unsigned int iec958_aes0_pro_fs_rate;
	bool mmap;
	bool audio;
    } opt;
    ctrl_t &setup;
    cPsleep wait;
protected:
public:
    spdif(ctrl_t &up);
    virtual ~spdif();
    virtual inline operator void* () { return (void*)out; };
    virtual void Forward(const uint_8 *data, const size_t dlen, class cBounce *bounce);
    virtual bool Open(iec60958 *in);
    virtual void Close(void);
    virtual void Clear(bool exit = false);
    virtual bool Synchronize(class cBounce *bounce);
    virtual size_t Available(const size_t max);
    virtual void Pause(const bool onoff);
};

#endif // __SPDIF_H