1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright © 2017-2017 VLC authors and VideoLAN
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20 *****************************************************************************/
26 #include <vlc_common.h>
28 #include "misc/background_worker.h"
29 #include "input/input_interface.h"
30 #include "input/input_internal.h"
31 #include "preparser.h"
34 struct playlist_preparser_t
37 playlist_fetcher_t
* fetcher
;
38 struct background_worker
* worker
;
39 atomic_bool deactivated
;
42 static int InputEvent( vlc_object_t
* obj
, const char* varname
,
43 vlc_value_t old
, vlc_value_t cur
, void* worker
)
45 VLC_UNUSED( obj
); VLC_UNUSED( varname
); VLC_UNUSED( old
);
47 if( cur
.i_int
== INPUT_EVENT_DEAD
)
48 background_worker_RequestProbe( worker
);
53 static int PreparserOpenInput( void* preparser_
, void* item_
, void** out
)
55 playlist_preparser_t
* preparser
= preparser_
;
57 input_thread_t
* input
= input_CreatePreparser( preparser
->owner
, item_
);
60 input_item_SignalPreparseEnded( item_
, ITEM_PREPARSE_FAILED
);
64 var_AddCallback( input
, "intf-event", InputEvent
, preparser
->worker
);
65 if( input_Start( input
) )
68 var_DelCallback( input
, "intf-event", InputEvent
, preparser
->worker
);
69 input_item_SignalPreparseEnded( item_
, ITEM_PREPARSE_FAILED
);
77 static int PreparserProbeInput( void* preparser_
, void* input_
)
79 int state
= input_GetState( input_
);
80 return state
== END_S
|| state
== ERROR_S
;
81 VLC_UNUSED( preparser_
);
84 static void PreparserCloseInput( void* preparser_
, void* input_
)
86 playlist_preparser_t
* preparser
= preparser_
;
87 input_thread_t
* input
= input_
;
88 input_item_t
* item
= input_priv(input
)->p_item
;
90 var_DelCallback( input
, "intf-event", InputEvent
, preparser
->worker
);
93 switch( input_GetState( input
) )
96 status
= ITEM_PREPARSE_DONE
;
99 status
= ITEM_PREPARSE_FAILED
;
102 status
= ITEM_PREPARSE_TIMEOUT
;
106 input_Close( input
);
108 if( preparser
->fetcher
)
110 if( !playlist_fetcher_Push( preparser
->fetcher
, item
, 0, status
) )
114 input_item_SetPreparsed( item
, true );
115 input_item_SignalPreparseEnded( item
, status
);
118 static void InputItemRelease( void* item
) { input_item_Release( item
); }
119 static void InputItemHold( void* item
) { input_item_Hold( item
); }
121 playlist_preparser_t
* playlist_preparser_New( vlc_object_t
*parent
)
123 playlist_preparser_t
* preparser
= malloc( sizeof *preparser
);
125 struct background_worker_config conf
= {
126 .default_timeout
= var_InheritInteger( parent
, "preparse-timeout" ),
127 .pf_start
= PreparserOpenInput
,
128 .pf_probe
= PreparserProbeInput
,
129 .pf_stop
= PreparserCloseInput
,
130 .pf_release
= InputItemRelease
,
131 .pf_hold
= InputItemHold
};
134 if( likely( preparser
) )
135 preparser
->worker
= background_worker_New( preparser
, &conf
);
137 if( unlikely( !preparser
|| !preparser
->worker
) )
143 preparser
->owner
= parent
;
144 preparser
->fetcher
= playlist_fetcher_New( parent
);
145 atomic_init( &preparser
->deactivated
, false );
147 if( unlikely( !preparser
->fetcher
) )
148 msg_Warn( parent
, "unable to create art fetcher" );
153 void playlist_preparser_Push( playlist_preparser_t
*preparser
,
154 input_item_t
*item
, input_item_meta_request_option_t i_options
,
155 int timeout
, void *id
)
157 if( atomic_load( &preparser
->deactivated
) )
160 vlc_mutex_lock( &item
->lock
);
161 int i_type
= item
->i_type
;
162 int b_net
= item
->b_net
;
163 vlc_mutex_unlock( &item
->lock
);
169 case ITEM_TYPE_DIRECTORY
:
170 case ITEM_TYPE_PLAYLIST
:
171 if( !b_net
|| i_options
& META_REQUEST_OPTION_SCOPE_NETWORK
)
174 input_item_SignalPreparseEnded( item
, ITEM_PREPARSE_SKIPPED
);
178 if( background_worker_Push( preparser
->worker
, item
, id
, timeout
) )
179 input_item_SignalPreparseEnded( item
, ITEM_PREPARSE_FAILED
);
182 void playlist_preparser_fetcher_Push( playlist_preparser_t
*preparser
,
183 input_item_t
*item
, input_item_meta_request_option_t options
)
185 if( preparser
->fetcher
)
186 playlist_fetcher_Push( preparser
->fetcher
, item
, options
, -1 );
189 void playlist_preparser_Cancel( playlist_preparser_t
*preparser
, void *id
)
191 background_worker_Cancel( preparser
->worker
, id
);
194 void playlist_preparser_Deactivate( playlist_preparser_t
* preparser
)
196 atomic_store( &preparser
->deactivated
, true );
197 background_worker_Cancel( preparser
->worker
, NULL
);
200 void playlist_preparser_Delete( playlist_preparser_t
*preparser
)
202 background_worker_Delete( preparser
->worker
);
204 if( preparser
->fetcher
)
205 playlist_fetcher_Delete( preparser
->fetcher
);