2 * Copyright (C) Joey Parrish
4 * This file is part of MPlayer.
6 * MPlayer is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * MPlayer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 * If you have a tivo with the vstream server installed, (and most tivo
23 * hackers do,) then you can connect to it and stream ty files using
24 * this module. The url syntax is tivo://host/fsid or tivo://host/list
25 * to list the available recordings and their fsid's.
26 * This module depends on libvstream-client, which is available from
27 * http://armory.nicewarrior.org/projects/vstream-client .
34 #include <sys/types.h>
51 #include <vstream-client.h>
53 void vstream_error(const char *format
, ...) {
57 vsnprintf(buf
, 1024, format
, va
);
59 mp_msg(MSGT_STREAM
, MSGL_ERR
, "%s", buf
);
62 static struct stream_priv_s
{
65 } stream_priv_dflts
= {
70 #define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
72 static const m_option_t stream_opts_fields
[] = {
73 {"hostname", ST_OFF(host
), CONF_TYPE_STRING
, 0, 0 ,0, NULL
},
74 {"filename", ST_OFF(fsid
), CONF_TYPE_STRING
, 0, 0 ,0, NULL
},
75 { NULL
, NULL
, 0, 0, 0, 0, NULL
}
78 static const struct m_struct_st stream_opts
= {
80 sizeof(struct stream_priv_s
),
85 static int fill_buffer(stream_t
*s
, char* buffer
, int max_len
){
86 struct stream_priv_s
* p
= (struct stream_priv_s
*)s
->priv
;
87 int len
= vstream_load_chunk(p
->fsid
, buffer
, max_len
, s
->pos
);
88 if (len
<= 0) return 0;
92 static int seek(stream_t
*s
,off_t newpos
) {
97 static int control(struct stream
*s
, int cmd
, void *arg
) {
98 return STREAM_UNSUPPORTED
;
101 static void close_s(struct stream
*s
) {
104 static int open_s(stream_t
*stream
, int mode
, void* opts
, int* file_format
) {
106 struct stream_priv_s
* p
= (struct stream_priv_s
*)opts
;
108 if(mode
!= STREAM_READ
)
109 return STREAM_UNSUPPORTED
;
112 mp_msg(MSGT_OPEN
, MSGL_ERR
, "We need a host name (ex: tivo://hostname/fsid)\n");
113 m_struct_free(&stream_opts
, opts
);
117 if(!p
->fsid
|| strlen(p
->fsid
) == 0) {
118 mp_msg(MSGT_OPEN
, MSGL_ERR
, "We need an fsid (ex: tivo://hostname/fsid)\n");
119 m_struct_free(&stream_opts
, opts
);
123 f
= connect2Server(p
->host
, VSERVER_PORT
, 1);
126 mp_msg(MSGT_OPEN
, MSGL_ERR
, "Connection to %s failed\n", p
->host
);
127 m_struct_free(&stream_opts
, opts
);
132 vstream_set_socket_fd(f
);
134 if (!strcmp(p
->fsid
, "list")) {
135 vstream_list_streams(0);
137 } else if (!strcmp(p
->fsid
, "llist")) {
138 vstream_list_streams(1);
142 if (vstream_start()) {
143 mp_msg(MSGT_OPEN
, MSGL_ERR
, "Cryptic internal error #1\n");
144 m_struct_free(&stream_opts
, opts
);
147 if (vstream_startstream(p
->fsid
)) {
148 mp_msg(MSGT_OPEN
, MSGL_ERR
, "Cryptic internal error #2\n");
149 m_struct_free(&stream_opts
, opts
);
153 stream
->start_pos
= 0;
154 stream
->end_pos
= vstream_streamsize();
155 mp_msg(MSGT_OPEN
, MSGL_DBG2
, "Tivo stream size is %lld\n",
156 (long long)stream
->end_pos
);
159 stream
->fill_buffer
= fill_buffer
;
160 stream
->control
= control
;
162 stream
->close
= close_s
;
163 stream
->type
= STREAMTYPE_VSTREAM
;
168 const stream_info_t stream_info_vstream
= {
176 1 // Url is an option string