1 /*****************************************************************************
2 * bluray.c: Blu-ray disc support plugin
3 *****************************************************************************
4 * Copyright (C) 2010 VideoLAN, VLC authors and libbluray AUTHORS
6 * This program 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 * This program 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
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
25 #ifdef HAVE_SYS_STAT_H
26 # include <sys/stat.h>
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_access.h>
35 #include <vlc_messages.h>
37 #include <libbluray/bluray.h>
39 /*****************************************************************************
41 *****************************************************************************/
42 #define CACHING_TEXT N_("Caching value in ms")
43 #define CACHING_LONGTEXT N_( "Caching value for BDs. This "\
44 "value should be set in milliseconds." )
47 static int blurayOpen ( vlc_object_t
* );
48 static void blurayClose( vlc_object_t
* );
51 set_shortname( N_("BluRay") )
52 set_description( N_("Blu-Ray Disc support (libbluray)") )
54 set_category( CAT_INPUT
)
55 set_subcategory( SUBCAT_INPUT_ACCESS
)
56 set_capability( "access", 60 )
58 add_integer( "bluray-caching", 1000, NULL
,
59 CACHING_TEXT
, CACHING_LONGTEXT
, true )
61 add_shortcut( "bluray" )
62 add_shortcut( "file" )
64 set_callbacks( blurayOpen
, blurayClose
)
67 /*****************************************************************************
69 *****************************************************************************/
77 static ssize_t
blurayRead (access_t
*, uint8_t *, size_t);
78 static int bluraySeek (access_t
*, uint64_t);
79 static int blurayControl(access_t
*, int, va_list);
80 static int bluraySetTitle(access_t
*p_access
, int i_tile
);
82 /*****************************************************************************
83 * blurayOpen: module init function
84 *****************************************************************************/
85 static int blurayOpen( vlc_object_t
*object
)
87 access_t
*p_access
= (access_t
*)object
;
92 char bd_path
[PATH_MAX
];
94 if( strcmp( p_access
->psz_access
, "bluray" ) ) {
95 // TODO BDMV support, once we figure out what to do in libbluray
99 /* init access fields */
100 access_InitFields(p_access
);
102 /* register callback function for communication */
103 ACCESS_SET_CALLBACKS(blurayRead
, NULL
, blurayControl
, bluraySeek
);
105 p_access
->p_sys
= p_sys
= malloc(sizeof(access_sys_t
));
106 if (unlikely(!p_sys
)) {
110 /* store current bd_path */
111 strncpy(bd_path
, p_access
->psz_location
, sizeof(bd_path
));
112 bd_path
[PATH_MAX
- 1] = '\0';
114 if ( (pos_title
= strrchr(bd_path
, ':')) ) {
115 /* found character ':' for title information */
116 *(pos_title
++) = '\0';
117 i_title
= atoi(pos_title
);
120 p_sys
->bluray
= bd_open(bd_path
, NULL
);
121 if ( !p_sys
->bluray
) {
126 /* set start title number */
127 if ( bluraySetTitle(p_access
, i_title
) != VLC_SUCCESS
) {
132 p_sys
->i_bd_delay
= var_InheritInteger(p_access
, "bluray-caching");
138 /*****************************************************************************
139 * blurayClose: module destroy function
140 *****************************************************************************/
141 static void blurayClose( vlc_object_t
*object
)
143 access_t
*p_access
= (access_t
*)object
;
144 access_sys_t
*p_sys
= p_access
->p_sys
;
146 /* bd_close( NULL ) can crash */
147 assert(p_sys
->bluray
);
148 bd_close(p_sys
->bluray
);
153 /*****************************************************************************
154 * bluraySetTitle: select new BD title
155 *****************************************************************************/
156 static int bluraySetTitle(access_t
*p_access
, int i_title
)
158 access_sys_t
*p_sys
= p_access
->p_sys
;
160 unsigned int i_nb_titles
= bd_get_titles(p_sys
->bluray
, TITLES_RELEVANT
);
162 /* Looking for the main title, ie the longest duration */
165 for (unsigned int i
= 0; i
< i_nb_titles
; i
++) {
166 BLURAY_TITLE_INFO
*info
= bd_get_title_info(p_sys
->bluray
, i
);
167 if (info
->duration
> duration
) {
169 duration
= info
->duration
;
174 /* Select Blu-Ray title */
175 if ( bd_select_title(p_access
->p_sys
->bluray
, i_title
) == 0 ) {
176 msg_Err( p_access
, "cannot select bd title '%d'", p_access
->info
.i_title
);
180 /* read title length and init some values */
181 p_access
->info
.i_title
= i_title
;
182 p_access
->info
.i_size
= bd_get_title_size(p_sys
->bluray
);
183 p_access
->info
.i_pos
= 0;
184 p_access
->info
.b_eof
= false;
185 p_access
->info
.i_seekpoint
= 0;
191 /*****************************************************************************
192 * blurayControl: handle the controls
193 *****************************************************************************/
194 static int blurayControl(access_t
*p_access
, int query
, va_list args
)
196 access_sys_t
*p_sys
= p_access
->p_sys
;
201 case ACCESS_CAN_SEEK
:
202 case ACCESS_CAN_FASTSEEK
:
203 case ACCESS_CAN_PAUSE
:
204 case ACCESS_CAN_CONTROL_PACE
:
205 pb_bool
= (bool*)va_arg( args
, bool * );
209 case ACCESS_GET_PTS_DELAY
:
210 pi_64
= (int64_t*)va_arg( args
, int64_t * );
211 *pi_64
= p_sys
->i_bd_delay
;
214 case ACCESS_SET_PAUSE_STATE
:
218 case ACCESS_SET_TITLE
:
220 int i_title
= (int)va_arg( args
, int );
221 if( bluraySetTitle( p_access
, i_title
) != VLC_SUCCESS
)
225 case ACCESS_SET_SEEKPOINT
:
227 int i_chapter
= (int)va_arg( args
, int );
228 bd_seek_chapter( p_sys
->bluray
, i_chapter
);
231 case ACCESS_GET_META
:
232 case ACCESS_GET_TITLE_INFO
:
233 case ACCESS_SET_PRIVATE_ID_STATE
:
234 case ACCESS_GET_CONTENT_TYPE
:
238 msg_Warn( p_access
, "unimplemented query (%d) in control", query
);
246 /*****************************************************************************
247 * bluraySeek: seek to the given position
248 *****************************************************************************/
249 static int bluraySeek(access_t
*p_access
, uint64_t position
)
251 access_sys_t
*p_sys
= p_access
->p_sys
;
253 p_access
->info
.i_pos
= bd_seek(p_sys
->bluray
, position
);
254 p_access
->info
.b_eof
= false;
260 /*****************************************************************************
261 * blurayRead: read BD data into buffer
262 *****************************************************************************/
263 static ssize_t
blurayRead(access_t
*p_access
, uint8_t *data
, size_t size
)
265 access_sys_t
*p_sys
= p_access
->p_sys
;
268 if (p_access
->info
.b_eof
) {
272 /* read data into buffer with given length */
273 nread
= bd_read(p_sys
->bluray
, data
, size
);
276 p_access
->info
.b_eof
= true;
278 else if( nread
> 0 ) {
279 p_access
->info
.i_pos
+= nread
;