Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-2-2
Commits
8e18f5c6
Commit
8e18f5c6
authored
May 12, 2008
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Try to split the mind boggingly big vlm.c
parent
5ab3b814
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1931 additions
and
1873 deletions
+1931
-1873
src/Makefile.am
src/Makefile.am
+1
-0
src/input/vlm.c
src/input/vlm.c
+112
-1873
src/input/vlm_internal.h
src/input/vlm_internal.h
+5
-0
src/input/vlmshell.c
src/input/vlmshell.c
+1813
-0
No files found.
src/Makefile.am
View file @
8e18f5c6
...
@@ -371,6 +371,7 @@ SOURCES_libvlc_common = \
...
@@ -371,6 +371,7 @@ SOURCES_libvlc_common = \
SOURCES_libvlc_sout
=
\
SOURCES_libvlc_sout
=
\
input/vlm.c
\
input/vlm.c
\
input/vlmshell.c
\
stream_output/stream_output.c
\
stream_output/stream_output.c
\
stream_output/stream_output.h
\
stream_output/stream_output.h
\
stream_output/announce.c
\
stream_output/announce.c
\
...
...
src/input/vlm.c
View file @
8e18f5c6
...
@@ -63,1918 +63,154 @@
...
@@ -63,1918 +63,154 @@
* Local prototypes.
* Local prototypes.
*****************************************************************************/
*****************************************************************************/
/* ugly kludge to avoid "null format string" warnings,
static
void
vlm_Destructor
(
vlm_t
*
p_vlm
);
* even if we handle NULL format string in vlm_MessageNew() */
static
int
Manage
(
vlc_object_t
*
);
static
const
char
*
vlm_NULL
=
NULL
;
static
int
vlm_MediaVodControl
(
void
*
,
vod_media_t
*
,
const
char
*
,
int
,
va_list
);
static
void
vlm_Destructor
(
vlm_t
*
p_vlm
);
/* */
static
int
vlm_ControlInternal
(
vlm_t
*
,
int
,
...
);
/* */
static
vlm_message_t
*
vlm_Show
(
vlm_t
*
,
vlm_media_sys_t
*
,
vlm_schedule_sys_t
*
,
const
char
*
);
static
vlm_schedule_sys_t
*
vlm_ScheduleSearch
(
vlm_t
*
,
const
char
*
);
static
char
*
Save
(
vlm_t
*
);
static
int
Load
(
vlm_t
*
,
char
*
);
static
int
ExecuteCommand
(
vlm_t
*
,
const
char
*
,
vlm_message_t
**
);
static
int
Manage
(
vlc_object_t
*
);
static
vlm_schedule_sys_t
*
vlm_ScheduleNew
(
vlm_t
*
vlm
,
const
char
*
psz_name
);
static
void
vlm_ScheduleDelete
(
vlm_t
*
vlm
,
vlm_schedule_sys_t
*
sched
);
static
int
vlm_ScheduleSetup
(
vlm_schedule_sys_t
*
schedule
,
const
char
*
psz_cmd
,
const
char
*
psz_value
);
static
int
vlm_MediaVodControl
(
void
*
,
vod_media_t
*
,
const
char
*
,
int
,
va_list
);
/* */
static
vlm_media_sys_t
*
vlm_MediaSearch
(
vlm_t
*
,
const
char
*
);
/*****************************************************************************
* vlm_New:
*****************************************************************************/
vlm_t
*
__vlm_New
(
vlc_object_t
*
p_this
)
{
vlc_value_t
lockval
;
vlm_t
*
p_vlm
=
NULL
,
**
pp_vlm
=
&
(
libvlc_priv
(
p_this
->
p_libvlc
)
->
p_vlm
);
char
*
psz_vlmconf
;
static
const
char
vlm_object_name
[]
=
"vlm daemon"
;
/* Avoid multiple creation */
if
(
var_Create
(
p_this
->
p_libvlc
,
"vlm_mutex"
,
VLC_VAR_MUTEX
)
||
var_Get
(
p_this
->
p_libvlc
,
"vlm_mutex"
,
&
lockval
)
)
return
NULL
;
vlc_mutex_lock
(
lockval
.
p_address
);
p_vlm
=
*
pp_vlm
;
if
(
p_vlm
)
{
/* VLM already exists */
vlc_object_yield
(
p_vlm
);
vlc_mutex_unlock
(
lockval
.
p_address
);
return
p_vlm
;
}
msg_Dbg
(
p_this
,
"creating VLM"
);
p_vlm
=
vlc_custom_create
(
p_this
,
sizeof
(
*
p_vlm
),
VLC_OBJECT_GENERIC
,
vlm_object_name
);
if
(
!
p_vlm
)
{
vlc_mutex_unlock
(
lockval
.
p_address
);
return
NULL
;
}
vlc_mutex_init
(
&
p_vlm
->
lock
);
p_vlm
->
i_id
=
1
;
TAB_INIT
(
p_vlm
->
i_media
,
p_vlm
->
media
);
TAB_INIT
(
p_vlm
->
i_schedule
,
p_vlm
->
schedule
);
p_vlm
->
i_vod
=
0
;
p_vlm
->
p_vod
=
NULL
;
vlc_object_attach
(
p_vlm
,
p_this
->
p_libvlc
);
if
(
vlc_thread_create
(
p_vlm
,
"vlm thread"
,
Manage
,
VLC_THREAD_PRIORITY_LOW
,
false
)
)
{
vlc_mutex_destroy
(
&
p_vlm
->
lock
);
vlc_object_release
(
p_vlm
);
return
NULL
;
}
/* Load our configuration file */
psz_vlmconf
=
var_CreateGetString
(
p_vlm
,
"vlm-conf"
);
if
(
psz_vlmconf
&&
*
psz_vlmconf
)
{
vlm_message_t
*
p_message
=
NULL
;
char
*
psz_buffer
=
NULL
;
msg_Dbg
(
p_this
,
"loading VLM configuration"
);
if
(
asprintf
(
&
psz_buffer
,
"load %s"
,
psz_vlmconf
)
==
-
1
)
psz_buffer
=
NULL
;
if
(
psz_buffer
)
{
msg_Dbg
(
p_this
,
psz_buffer
);
if
(
vlm_ExecuteCommand
(
p_vlm
,
psz_buffer
,
&
p_message
)
)
msg_Warn
(
p_this
,
"error while loading the configuration file"
);
vlm_MessageDelete
(
p_message
);
free
(
psz_buffer
);
}
}
free
(
psz_vlmconf
);
vlc_object_set_destructor
(
p_vlm
,
(
vlc_destructor_t
)
vlm_Destructor
);
*
pp_vlm
=
p_vlm
;
/* for future reference */
vlc_mutex_unlock
(
lockval
.
p_address
);
return
p_vlm
;
}
/*****************************************************************************
* vlm_Delete:
*****************************************************************************/
void
vlm_Delete
(
vlm_t
*
p_vlm
)
{
vlc_value_t
lockval
;
/* vlm_Delete() is serialized against itself, and against vlm_New().
* This way, vlm_Destructor () (called from vlc_objet_release() above)
* is serialized against setting libvlc_priv->p_vlm from vlm_New(). */
var_Get
(
p_vlm
->
p_libvlc
,
"vlm_mutex"
,
&
lockval
);
vlc_mutex_lock
(
lockval
.
p_address
);
vlc_object_release
(
p_vlm
);
vlc_mutex_unlock
(
lockval
.
p_address
);
}
/*****************************************************************************
* vlm_Destructor:
*****************************************************************************/
static
void
vlm_Destructor
(
vlm_t
*
p_vlm
)
{
libvlc_priv
(
p_vlm
->
p_libvlc
)
->
p_vlm
=
NULL
;
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_MEDIAS
);
TAB_CLEAN
(
p_vlm
->
i_media
,
p_vlm
->
media
);
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_SCHEDULES
);
TAB_CLEAN
(
p_vlm
->
schedule
,
p_vlm
->
schedule
);
vlc_mutex_destroy
(
&
p_vlm
->
lock
);
}
/*****************************************************************************
* vlm_ExecuteCommand:
*****************************************************************************/
int
vlm_ExecuteCommand
(
vlm_t
*
p_vlm
,
const
char
*
psz_command
,
vlm_message_t
**
pp_message
)
{
int
i_result
;
vlc_mutex_lock
(
&
p_vlm
->
lock
);
i_result
=
ExecuteCommand
(
p_vlm
,
psz_command
,
pp_message
);
vlc_mutex_unlock
(
&
p_vlm
->
lock
);
return
i_result
;
}
static
const
char
quotes
[]
=
"
\"
'"
;
/**
* FindCommandEnd: look for the end of a possibly quoted string
* @return NULL on mal-formatted string,
* pointer past the last character otherwise.
*/
static
const
char
*
FindCommandEnd
(
const
char
*
psz_sent
)
{
char
c
,
quote
=
0
;
while
(
(
c
=
*
psz_sent
)
!=
'\0'
)
{
if
(
!
quote
)
{
if
(
strchr
(
quotes
,
c
)
)
// opening quote
quote
=
c
;
else
if
(
isspace
(
c
)
)
// non-escaped space
return
psz_sent
;
else
if
(
c
==
'\\'
)
{
psz_sent
++
;
// skip escaped character
if
(
*
psz_sent
==
'\0'
)
return
psz_sent
;
}
}
else
{
if
(
c
==
quote
)
// non-escaped matching quote
quote
=
0
;
else
if
(
(
quote
==
'"'
)
&&
(
c
==
'\\'
)
)
{
psz_sent
++
;
// skip escaped character
if
(
*
psz_sent
==
'\0'
)
return
NULL
;
// error, closing quote missing
}
}
psz_sent
++
;
}
// error (NULL) if we could not find a matching quote
return
quote
?
NULL
:
psz_sent
;
}
/**
* Unescape a nul-terminated string.
* Note that in and out can be identical.
*
* @param out output buffer (at least <strlen (in) + 1> characters long)
* @param in nul-terminated string to be unescaped
*
* @return 0 on success, -1 on error.
*/
static
int
Unescape
(
char
*
out
,
const
char
*
in
)
{
char
c
,
quote
=
0
;
while
(
(
c
=
*
in
++
)
!=
'\0'
)
{
if
(
!
quote
)
{
if
(
strchr
(
quotes
,
c
))
// opening quote
{
quote
=
c
;
continue
;
}
else
if
(
c
==
'\\'
)
{
switch
(
c
=
*
in
++
)
{
case
'"'
:
case
'\''
:
case
'\\'
:
*
out
++
=
c
;
continue
;
case
'\0'
:
*
out
=
'\0'
;
return
0
;
}
if
(
isspace
(
c
)
)
{
*
out
++
=
c
;
continue
;
}
/* None of the special cases - copy the backslash */
*
out
++
=
'\\'
;
}
}
else
{
if
(
c
==
quote
)
// non-escaped matching quote
{
quote
=
0
;
continue
;
}
if
(
(
quote
==
'"'
)
&&
(
c
==
'\\'
)
)
{
switch
(
c
=
*
in
++
)
{
case
'"'
:
case
'\\'
:
*
out
++
=
c
;
continue
;
case
'\0'
:
// should never happen
*
out
=
'\0'
;
return
-
1
;
}
/* None of the special cases - copy the backslash */
*
out
++
=
'\\'
;
}
}
*
out
++
=
c
;
}
*
out
=
'\0'
;
return
0
;
}
/*****************************************************************************
* ExecuteCommand: The main state machine
*****************************************************************************
* Execute a command which ends with '\0' (string)
*****************************************************************************/
static
int
ExecuteSyntaxError
(
const
char
*
psz_cmd
,
vlm_message_t
**
pp_status
)
{
*
pp_status
=
vlm_MessageNew
(
psz_cmd
,
"Wrong command syntax"
);
return
VLC_EGENERIC
;
}
static
bool
ExecuteIsMedia
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
)
{
int64_t
id
;
if
(
!
psz_name
||
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_ID
,
psz_name
,
&
id
)
)
return
false
;
return
true
;
}
static
bool
ExecuteIsSchedule
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
)
{
if
(
!
psz_name
||
!
vlm_ScheduleSearch
(
p_vlm
,
psz_name
)
)
return
false
;
return
true
;
}
static
int
ExecuteDel
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
,
vlm_message_t
**
pp_status
)
{
vlm_media_sys_t
*
p_media
;
vlm_schedule_sys_t
*
p_schedule
;
p_media
=
vlm_MediaSearch
(
p_vlm
,
psz_name
);
p_schedule
=
vlm_ScheduleSearch
(
p_vlm
,
psz_name
);
if
(
p_schedule
!=
NULL
)
{
vlm_ScheduleDelete
(
p_vlm
,
p_schedule
);
}
else
if
(
p_media
!=
NULL
)
{
vlm_ControlInternal
(
p_vlm
,
VLM_DEL_MEDIA
,
p_media
->
cfg
.
id
);
}
else
if
(
!
strcmp
(
psz_name
,
"media"
)
)
{
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_MEDIAS
);
}
else
if
(
!
strcmp
(
psz_name
,
"schedule"
)
)
{
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_SCHEDULES
);
}
else
if
(
!
strcmp
(
psz_name
,
"all"
)
)
{
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_MEDIAS
);
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_SCHEDULES
);
}
else
{
*
pp_status
=
vlm_MessageNew
(
"del"
,
"%s: media unknown"
,
psz_name
);
return
VLC_EGENERIC
;
}
*
pp_status
=
vlm_MessageNew
(
"del"
,
vlm_NULL
);
return
VLC_SUCCESS
;
}
static
int
ExecuteShow
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
,
vlm_message_t
**
pp_status
)
{
vlm_media_sys_t
*
p_media
;
vlm_schedule_sys_t
*
p_schedule
;
if
(
!
psz_name
)
{
*
pp_status
=
vlm_Show
(
p_vlm
,
NULL
,
NULL
,
NULL
);
return
VLC_SUCCESS
;
}
p_media
=
vlm_MediaSearch
(
p_vlm
,
psz_name
);
p_schedule
=
vlm_ScheduleSearch
(
p_vlm
,
psz_name
);
if
(
p_schedule
!=
NULL
)
*
pp_status
=
vlm_Show
(
p_vlm
,
NULL
,
p_schedule
,
NULL
);
else
if
(
p_media
!=
NULL
)
*
pp_status
=
vlm_Show
(
p_vlm
,
p_media
,
NULL
,
NULL
);
else
*
pp_status
=
vlm_Show
(
p_vlm
,
NULL
,
NULL
,
psz_name
);
return
VLC_SUCCESS
;
}
static
int
ExecuteHelp
(
vlm_message_t
**
pp_status
)
{
vlm_message_t
*
message_child
;
#define MessageAdd( a ) \
vlm_MessageAdd( *pp_status, vlm_MessageNew( a, vlm_NULL ) );
#define MessageAddChild( a ) \
vlm_MessageAdd( message_child, vlm_MessageNew( a, vlm_NULL ) );
*
pp_status
=
vlm_MessageNew
(
"help"
,
vlm_NULL
);
message_child
=
MessageAdd
(
"Commands Syntax:"
);
MessageAddChild
(
"new (name) vod|broadcast|schedule [properties]"
);
MessageAddChild
(
"setup (name) (properties)"
);
MessageAddChild
(
"show [(name)|media|schedule]"
);
MessageAddChild
(
"del (name)|all|media|schedule"
);
MessageAddChild
(
"control (name) [instance_name] (command)"
);
MessageAddChild
(
"save (config_file)"
);
MessageAddChild
(
"export"
);
MessageAddChild
(
"load (config_file)"
);
message_child
=
MessageAdd
(
"Media Proprieties Syntax:"
);
MessageAddChild
(
"input (input_name)"
);
MessageAddChild
(
"inputdel (input_name)|all"
);
MessageAddChild
(
"inputdeln input_number"
);
MessageAddChild
(
"output (output_name)"
);
MessageAddChild
(
"option (option_name)[=value]"
);
MessageAddChild
(
"enabled|disabled"
);
MessageAddChild
(
"loop|unloop (broadcast only)"
);
MessageAddChild
(
"mux (mux_name)"
);
message_child
=
MessageAdd
(
"Schedule Proprieties Syntax:"
);
MessageAddChild
(
"enabled|disabled"
);
MessageAddChild
(
"append (command_until_rest_of_the_line)"
);
MessageAddChild
(
"date (year)/(month)/(day)-(hour):(minutes):"
"(seconds)|now"
);
MessageAddChild
(
"period (years_aka_12_months)/(months_aka_30_days)/"
"(days)-(hours):(minutes):(seconds)"
);
MessageAddChild
(
"repeat (number_of_repetitions)"
);
message_child
=
MessageAdd
(
"Control Commands Syntax:"
);
MessageAddChild
(
"play [input_number]"
);
MessageAddChild
(
"pause"
);
MessageAddChild
(
"stop"
);
MessageAddChild
(
"seek [+-](percentage) | [+-](seconds)s | [+-](miliseconds)ms"
);
return
VLC_SUCCESS
;
}
static
int
ExecuteControl
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
,
const
int
i_arg
,
char
**
ppsz_arg
,
vlm_message_t
**
pp_status
)
{
vlm_media_sys_t
*
p_media
;
const
char
*
psz_control
=
NULL
;
const
char
*
psz_instance
=
NULL
;
const
char
*
psz_argument
=
NULL
;
int
i_index
;
int
i_result
;
if
(
!
ExecuteIsMedia
(
p_vlm
,
psz_name
)
)
{
*
pp_status
=
vlm_MessageNew
(
"control"
,
"%s: media unknown"
,
psz_name
);
return
VLC_EGENERIC
;
}
assert
(
i_arg
>
0
);
#define IS(txt) ( !strcmp( ppsz_arg[i_index], (txt) ) )
i_index
=
0
;
if
(
!
IS
(
"play"
)
&&
!
IS
(
"stop"
)
&&
!
IS
(
"pause"
)
&&
!
IS
(
"seek"
)
)
{
i_index
=
1
;
psz_instance
=
ppsz_arg
[
0
];
if
(
i_index
>=
i_arg
||
(
!
IS
(
"play"
)
&&
!
IS
(
"stop"
)
&&
!
IS
(
"pause"
)
&&
!
IS
(
"seek"
)
)
)
return
ExecuteSyntaxError
(
"control"
,
pp_status
);
}
#undef IS
psz_control
=
ppsz_arg
[
i_index
];
if
(
i_index
+
1
<
i_arg
)
psz_argument
=
ppsz_arg
[
i_index
+
1
];
p_media
=
vlm_MediaSearch
(
p_vlm
,
psz_name
);
assert
(
p_media
);
if
(
!
strcmp
(
psz_control
,
"play"
)
)
{
int
i_input_index
=
0
;
int
i
;
if
(
(
psz_argument
&&
sscanf
(
psz_argument
,
"%d"
,
&
i
)
==
1
)
&&
i
>
0
&&
i
-
1
<
p_media
->
cfg
.
i_input
)
{
i_input_index
=
i
-
1
;
}
else
if
(
psz_argument
)
{
int
j
;
vlm_media_t
*
p_cfg
=
&
p_media
->
cfg
;
for
(
j
=
0
;
j
<
p_cfg
->
i_input
;
j
++
)
{
if
(
!
strcmp
(
p_cfg
->
ppsz_input
[
j
],
psz_argument
)
)
{
i_input_index
=
j
;
break
;
}
}
}
if
(
p_media
->
cfg
.
b_vod
)
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_START_MEDIA_VOD_INSTANCE
,
p_media
->
cfg
.
id
,
psz_instance
,
i_input_index
,
NULL
);
// we should get here now
else
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_START_MEDIA_BROADCAST_INSTANCE
,
p_media
->
cfg
.
id
,
psz_instance
,
i_input_index
);
}
else
if
(
!
strcmp
(
psz_control
,
"seek"
)
)
{
if
(
psz_argument
)
{
bool
b_relative
;
if
(
psz_argument
[
0
]
==
'+'
||
psz_argument
[
0
]
==
'-'
)
b_relative
=
true
;
else
b_relative
=
false
;
if
(
strstr
(
psz_argument
,
"ms"
)
||
strstr
(
psz_argument
,
"s"
)
)
{
/* Time (ms or s) */
int64_t
i_new_time
;
if
(
strstr
(
psz_argument
,
"ms"
)
)
i_new_time
=
1000
*
(
int64_t
)
atoi
(
psz_argument
);
else
i_new_time
=
1000000
*
(
int64_t
)
atoi
(
psz_argument
);
if
(
b_relative
)
{
int64_t
i_time
=
0
;
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_INSTANCE_TIME
,
p_media
->
cfg
.
id
,
psz_instance
,
&
i_time
);
i_new_time
+=
i_time
;
}
if
(
i_new_time
<
0
)
i_new_time
=
0
;
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_SET_MEDIA_INSTANCE_TIME
,
p_media
->
cfg
.
id
,
psz_instance
,
i_new_time
);
}
else
{
/* Percent */
double
d_new_position
=
i18n_atof
(
psz_argument
)
/
100
.
0
;
if
(
b_relative
)
{
double
d_position
=
0
.
0
;
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
&
d_position
);
d_new_position
+=
d_position
;
}
if
(
d_new_position
<
0
.
0
)
d_new_position
=
0
.
0
;
else
if
(
d_new_position
>
1
.
0
)
d_new_position
=
1
.
0
;
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_SET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
d_new_position
);
}
}
else
{
i_result
=
VLC_EGENERIC
;
}
}
else
if
(
!
strcmp
(
psz_control
,
"rewind"
)
)
{
if
(
psz_argument
)
{
const
double
d_scale
=
i18n_atof
(
psz_argument
);
double
d_position
;
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
&
d_position
);
d_position
-=
(
d_scale
/
1000
.
0
);
if
(
d_position
<
0
.
0
)
d_position
=
0
.
0
;
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_SET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
d_position
);
}
else
{
i_result
=
VLC_EGENERIC
;
}
}
else
if
(
!
strcmp
(
psz_control
,
"forward"
)
)
{
if
(
psz_argument
)
{
const
double
d_scale
=
i18n_atof
(
psz_argument
);
double
d_position
;
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
&
d_position
);
d_position
+=
(
d_scale
/
1000
.
0
);
if
(
d_position
>
1
.
0
)
d_position
=
1
.
0
;
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_SET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
d_position
);
}
else
{
i_result
=
VLC_EGENERIC
;
}
}
else
if
(
!
strcmp
(
psz_control
,
"stop"
)
)
{
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_STOP_MEDIA_INSTANCE
,
p_media
->
cfg
.
id
,
psz_instance
);
}
else
if
(
!
strcmp
(
psz_control
,
"pause"
)
)
{
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_PAUSE_MEDIA_INSTANCE
,
p_media
->
cfg
.
id
,
psz_instance
);
}
else
{
i_result
=
VLC_EGENERIC
;
}
if
(
i_result
)
{
*
pp_status
=
vlm_MessageNew
(
"control"
,
"unknown error"
);
return
VLC_SUCCESS
;
}
*
pp_status
=
vlm_MessageNew
(
"control"
,
vlm_NULL
);
return
VLC_SUCCESS
;
}
static
int
ExecuteExport
(
vlm_t
*
p_vlm
,
vlm_message_t
**
pp_status
)
{
char
*
psz_export
=
Save
(
p_vlm
);
*
pp_status
=
vlm_MessageNew
(
"export"
,
psz_export
);
free
(
psz_export
);
return
VLC_SUCCESS
;
}
static
int
ExecuteSave
(
vlm_t
*
p_vlm
,
const
char
*
psz_file
,
vlm_message_t
**
pp_status
)
{
FILE
*
f
=
utf8_fopen
(
psz_file
,
"wt"
);
char
*
psz_save
=
NULL
;
if
(
!
f
)
goto
error
;
psz_save
=
Save
(
p_vlm
);
if
(
psz_save
==
NULL
)
goto
error
;
if
(
fputs
(
psz_save
,
f
)
==
EOF
)
goto
error
;;
if
(
fclose
(
f
)
)
{
f
=
NULL
;
goto
error
;
}
free
(
psz_save
);
*
pp_status
=
vlm_MessageNew
(
"save"
,
vlm_NULL
);
return
VLC_SUCCESS
;
error:
free
(
psz_save
);
if
(
f
)
fclose
(
f
);
*
pp_status
=
vlm_MessageNew
(
"save"
,
"Unable to save to file"
);
return
VLC_EGENERIC
;
}
static
int
ExecuteLoad
(
vlm_t
*
p_vlm
,
const
char
*
psz_url
,
vlm_message_t
**
pp_status
)
{
stream_t
*
p_stream
=
stream_UrlNew
(
p_vlm
,
psz_url
);
int64_t
i_size
;
char
*
psz_buffer
;
if
(
!
p_stream
)
{
*
pp_status
=
vlm_MessageNew
(
"load"
,
"Unable to load from file"
);
return
VLC_EGENERIC
;
}
/* FIXME needed ? */
if
(
stream_Seek
(
p_stream
,
0
)
!=
0
)
{
stream_Delete
(
p_stream
);
*
pp_status
=
vlm_MessageNew
(
"load"
,
"Read file error"
);
return
VLC_EGENERIC
;
}
i_size
=
stream_Size
(
p_stream
);
psz_buffer
=
malloc
(
i_size
+
1
);
if
(
!
psz_buffer
)
{
stream_Delete
(
p_stream
);
*
pp_status
=
vlm_MessageNew
(
"load"
,
"Read file error"
);
return
VLC_EGENERIC
;
}
stream_Read
(
p_stream
,
psz_buffer
,
i_size
);
psz_buffer
[
i_size
]
=
'\0'
;
stream_Delete
(
p_stream
);
if
(
Load
(
p_vlm
,
psz_buffer
)
)
{
free
(
psz_buffer
);
*
pp_status
=
vlm_MessageNew
(
"load"
,
"Error while loading file"
);
return
VLC_EGENERIC
;
}
free
(
psz_buffer
);
*
pp_status
=
vlm_MessageNew
(
"load"
,
vlm_NULL
);
return
VLC_SUCCESS
;
}
static
int
ExecuteScheduleProperty
(
vlm_t
*
p_vlm
,
vlm_schedule_sys_t
*
p_schedule
,
bool
b_new
,
const
int
i_property
,
char
*
ppsz_property
[],
vlm_message_t
**
pp_status
)
{
const
char
*
psz_cmd
=
b_new
?
"new"
:
"setup"
;
int
i
;
for
(
i
=
0
;
i
<
i_property
;
i
++
)
{
if
(
!
strcmp
(
ppsz_property
[
i
],
"enabled"
)
||
!
strcmp
(
ppsz_property
[
i
],
"disabled"
)
)
{
vlm_ScheduleSetup
(
p_schedule
,
ppsz_property
[
i
],
NULL
);
}
else
if
(
!
strcmp
(
ppsz_property
[
i
],
"append"
)
)
{
char
*
psz_line
;
int
j
;
/* Beware: everything behind append is considered as
* command line */
if
(
++
i
>=
i_property
)
break
;
psz_line
=
strdup
(
ppsz_property
[
i
]
);
for
(
j
=
i
+
1
;
j
<
i_property
;
j
++
)
{
psz_line
=
realloc
(
psz_line
,
strlen
(
psz_line
)
+
strlen
(
ppsz_property
[
j
])
+
1
+
1
);
strcat
(
psz_line
,
" "
);
strcat
(
psz_line
,
ppsz_property
[
j
]
);
}
vlm_ScheduleSetup
(
p_schedule
,
"append"
,
psz_line
);
break
;
}
else
{
if
(
i
+
1
>=
i_property
)
{
if
(
b_new
)
vlm_ScheduleDelete
(
p_vlm
,
p_schedule
);
return
ExecuteSyntaxError
(
psz_cmd
,
pp_status
);
}
vlm_ScheduleSetup
(
p_schedule
,
ppsz_property
[
i
],
ppsz_property
[
i
+
1
]
);
i
++
;
}
}
*
pp_status
=
vlm_MessageNew
(
psz_cmd
,
vlm_NULL
);
return
VLC_SUCCESS
;
}
static
int
ExecuteMediaProperty
(
vlm_t
*
p_vlm
,
int64_t
id
,
bool
b_new
,
const
int
i_property
,
char
*
ppsz_property
[],
vlm_message_t
**
pp_status
)
{
const
char
*
psz_cmd
=
b_new
?
"new"
:
"setup"
;
vlm_media_t
*
p_cfg
=
NULL
;
int
i_result
;
int
i
;
#undef ERROR
#undef MISSING
#define ERROR( txt ) do { *pp_status = vlm_MessageNew( psz_cmd, txt); goto error; } while(0)
if
(
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA
,
id
,
&
p_cfg
)
)
ERROR
(
"unknown media"
);
#define MISSING(cmd) do { if( !psz_value ) ERROR( "missing argument for " cmd ); } while(0)
for
(
i
=
0
;
i
<
i_property
;
i
++
)
{
const
char
*
psz_option
=
ppsz_property
[
i
];
const
char
*
psz_value
=
i
+
1
<
i_property
?
ppsz_property
[
i
+
1
]
:
NULL
;
if
(
!
strcmp
(
psz_option
,
"enabled"
)
)
{
p_cfg
->
b_enabled
=
true
;
}
else
if
(
!
strcmp
(
psz_option
,
"disabled"
)
)
{
p_cfg
->
b_enabled
=
false
;
}
else
if
(
!
strcmp
(
psz_option
,
"input"
)
)
{
MISSING
(
"input"
);
TAB_APPEND
(
p_cfg
->
i_input
,
p_cfg
->
ppsz_input
,
strdup
(
psz_value
)
);
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"inputdel"
)
&&
psz_value
&&
!
strcmp
(
psz_value
,
"all"
)
)
{
while
(
p_cfg
->
i_input
>
0
)
TAB_REMOVE
(
p_cfg
->
i_input
,
p_cfg
->
ppsz_input
,
p_cfg
->
ppsz_input
[
0
]
);
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"inputdel"
)
)
{
int
j
;
MISSING
(
"inputdel"
);
for
(
j
=
0
;
j
<
p_cfg
->
i_input
;
j
++
)
{
if
(
!
strcmp
(
p_cfg
->
ppsz_input
[
j
],
psz_value
)
)
{
TAB_REMOVE
(
p_cfg
->
i_input
,
p_cfg
->
ppsz_input
,
p_cfg
->
ppsz_input
[
j
]
);
break
;
}
}
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"inputdeln"
)
)
{
int
i_index
;
MISSING
(
"inputdeln"
);
i_index
=
atoi
(
psz_value
);
if
(
i_index
>
0
&&
i_index
<=
p_cfg
->
i_input
)
TAB_REMOVE
(
p_cfg
->
i_input
,
p_cfg
->
ppsz_input
,
p_cfg
->
ppsz_input
[
i_index
-
1
]
);
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"output"
)
)
{
MISSING
(
"output"
);
free
(
p_cfg
->
psz_output
);
p_cfg
->
psz_output
=
*
psz_value
?
strdup
(
psz_value
)
:
NULL
;
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"option"
)
)
{
MISSING
(
"option"
);
TAB_APPEND
(
p_cfg
->
i_option
,
p_cfg
->
ppsz_option
,
strdup
(
psz_value
)
);
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"loop"
)
)
{
if
(
p_cfg
->
b_vod
)
ERROR
(
"invalid loop option for vod"
);
p_cfg
->
broadcast
.
b_loop
=
true
;
}
else
if
(
!
strcmp
(
psz_option
,
"unloop"
)
)
{
if
(
p_cfg
->
b_vod
)
ERROR
(
"invalid unloop option for vod"
);
p_cfg
->
broadcast
.
b_loop
=
false
;
}
else
if
(
!
strcmp
(
psz_option
,
"mux"
)
)
{
MISSING
(
"mux"
);
if
(
!
p_cfg
->
b_vod
)
ERROR
(
"invalid mux option for broadcast"
);
free
(
p_cfg
->
vod
.
psz_mux
);
p_cfg
->
vod
.
psz_mux
=
*
psz_value
?
strdup
(
psz_value
)
:
NULL
;
i
++
;
}
else
{
fprintf
(
stderr
,
"PROP: name=%s unknown
\n
"
,
psz_option
);
ERROR
(
"Wrong command syntax"
);
}
}
#undef MISSING
#undef ERROR
/* */
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_CHANGE_MEDIA
,
p_cfg
);
vlm_media_Delete
(
p_cfg
);
*
pp_status
=
vlm_MessageNew
(
psz_cmd
,
vlm_NULL
);
return
i_result
;
error:
if
(
p_cfg
)
{
if
(
b_new
)
vlm_ControlInternal
(
p_vlm
,
VLM_DEL_MEDIA
,
p_cfg
->
id
);
vlm_media_Delete
(
p_cfg
);
}
return
VLC_EGENERIC
;
}
static
int
ExecuteNew
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
,
const
char
*
psz_type
,
const
int
i_property
,
char
*
ppsz_property
[],
vlm_message_t
**
pp_status
)
{
/* Check name */
if
(
!
strcmp
(
psz_name
,
"all"
)
||
!
strcmp
(
psz_name
,
"media"
)
||
!
strcmp
(
psz_name
,
"schedule"
)
)
{
*
pp_status
=
vlm_MessageNew
(
"new"
,
"
\"
all
\"
,
\"
media
\"
and
\"
schedule
\"
are reserved names"
);
return
VLC_EGENERIC
;
}
if
(
ExecuteIsMedia
(
p_vlm
,
psz_name
)
||
ExecuteIsSchedule
(
p_vlm
,
psz_name
)
)
{
*
pp_status
=
vlm_MessageNew
(
"new"
,
"%s: Name already in use"
,
psz_name
);
return
VLC_EGENERIC
;
}
/* */
if
(
!
strcmp
(
psz_type
,
"schedule"
)
)
{
vlm_schedule_sys_t
*
p_schedule
=
vlm_ScheduleNew
(
p_vlm
,
psz_name
);
if
(
!
p_schedule
)
{
*
pp_status
=
vlm_MessageNew
(
"new"
,
"could not create schedule"
);
return
VLC_EGENERIC
;
}
return
ExecuteScheduleProperty
(
p_vlm
,
p_schedule
,
true
,
i_property
,
ppsz_property
,
pp_status
);
}
else
if
(
!
strcmp
(
psz_type
,
"vod"
)
||
!
strcmp
(
psz_type
,
"broadcast"
)
)
{
vlm_media_t
cfg
;
int64_t
id
;
vlm_media_Init
(
&
cfg
);
cfg
.
psz_name
=
strdup
(
psz_name
);
cfg
.
b_vod
=
!
strcmp
(
psz_type
,
"vod"
);
if
(
vlm_ControlInternal
(
p_vlm
,
VLM_ADD_MEDIA
,
&
cfg
,
&
id
)
)
{
vlm_media_Clean
(
&
cfg
);
*
pp_status
=
vlm_MessageNew
(
"new"
,
"could not create media"
);
return
VLC_EGENERIC
;
}
vlm_media_Clean
(
&
cfg
);
return
ExecuteMediaProperty
(
p_vlm
,
id
,
true
,
i_property
,
ppsz_property
,
pp_status
);
}
else
{
*
pp_status
=
vlm_MessageNew
(
"new"
,
"%s: Choose between vod, broadcast or schedule"
,
psz_type
);
return
VLC_EGENERIC
;
}
}
static
int
ExecuteSetup
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
,
const
int
i_property
,
char
*
ppsz_property
[],
vlm_message_t
**
pp_status
)
{
if
(
ExecuteIsSchedule
(
p_vlm
,
psz_name
)
)
{
vlm_schedule_sys_t
*
p_schedule
=
vlm_ScheduleSearch
(
p_vlm
,
psz_name
);
return
ExecuteScheduleProperty
(
p_vlm
,
p_schedule
,
false
,
i_property
,
ppsz_property
,
pp_status
);
}
else
if
(
ExecuteIsMedia
(
p_vlm
,
psz_name
)
)
{
int64_t
id
;
if
(
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_ID
,
psz_name
,
&
id
)
)
goto
error
;
return
ExecuteMediaProperty
(
p_vlm
,
id
,
false
,
i_property
,
ppsz_property
,
pp_status
);
}
error:
*
pp_status
=
vlm_MessageNew
(
"setup"
,
"%s unknown"
,
psz_name
);
return
VLC_EGENERIC
;
}
static
int
ExecuteCommand
(
vlm_t
*
p_vlm
,
const
char
*
psz_command
,
vlm_message_t
**
pp_message
)
{
size_t
i_command
=
0
;
char
buf
[
strlen
(
psz_command
)
+
1
],
*
psz_buf
=
buf
;
char
*
ppsz_command
[
3
+
sizeof
(
buf
)
/
2
];
vlm_message_t
*
p_message
=
NULL
;
/* First, parse the line and cut it */
while
(
*
psz_command
!=
'\0'
)
{
const
char
*
psz_temp
;
if
(
isspace
(
*
psz_command
))
{
psz_command
++
;
continue
;
}
/* support for comments */
if
(
i_command
==
0
&&
*
psz_command
==
'#'
)
{
p_message
=
vlm_MessageNew
(
""
,
vlm_NULL
);
goto
success
;
}
psz_temp
=
FindCommandEnd
(
psz_command
);
if
(
psz_temp
==
NULL
)
{
p_message
=
vlm_MessageNew
(
"Incomplete command"
,
psz_command
);
goto
error
;
}
assert
(
i_command
<
(
sizeof
(
ppsz_command
)
/
sizeof
(
ppsz_command
[
0
])));
ppsz_command
[
i_command
]
=
psz_buf
;
memcpy
(
psz_buf
,
psz_command
,
psz_temp
-
psz_command
);
psz_buf
[
psz_temp
-
psz_command
]
=
'\0'
;
Unescape
(
psz_buf
,
psz_buf
);
i_command
++
;
psz_buf
+=
psz_temp
-
psz_command
+
1
;
psz_command
=
psz_temp
;
assert
(
buf
+
sizeof
(
buf
)
>=
psz_buf
);
}
/*
* And then Interpret it
*/
#define IF_EXECUTE( name, check, cmd ) if( !strcmp(ppsz_command[0], name ) ) { if( (check) ) goto syntax_error; if( (cmd) ) goto error; goto success; }
if
(
i_command
==
0
)
{
p_message
=
vlm_MessageNew
(
""
,
vlm_NULL
);
goto
success
;
}
else
IF_EXECUTE
(
"del"
,
(
i_command
!=
2
),
ExecuteDel
(
p_vlm
,
ppsz_command
[
1
],
&
p_message
)
)
else
IF_EXECUTE
(
"show"
,
(
i_command
>
2
),
ExecuteShow
(
p_vlm
,
i_command
>
1
?
ppsz_command
[
1
]
:
NULL
,
&
p_message
)
)
else
IF_EXECUTE
(
"help"
,
(
i_command
!=
1
),
ExecuteHelp
(
&
p_message
)
)
else
IF_EXECUTE
(
"control"
,
(
i_command
<
3
),
ExecuteControl
(
p_vlm
,
ppsz_command
[
1
],
i_command
-
2
,
&
ppsz_command
[
2
],
&
p_message
)
)
else
IF_EXECUTE
(
"save"
,
(
i_command
!=
2
),
ExecuteSave
(
p_vlm
,
ppsz_command
[
1
],
&
p_message
)
)
else
IF_EXECUTE
(
"export"
,
(
i_command
!=
1
),
ExecuteExport
(
p_vlm
,
&
p_message
)
)
else
IF_EXECUTE
(
"load"
,
(
i_command
!=
2
),
ExecuteLoad
(
p_vlm
,
ppsz_command
[
1
],
&
p_message
)
)
else
IF_EXECUTE
(
"new"
,
(
i_command
<
3
),
ExecuteNew
(
p_vlm
,
ppsz_command
[
1
],
ppsz_command
[
2
],
i_command
-
3
,
&
ppsz_command
[
3
],
&
p_message
)
)
else
IF_EXECUTE
(
"setup"
,
(
i_command
<
2
),
ExecuteSetup
(
p_vlm
,
ppsz_command
[
1
],
i_command
-
2
,
&
ppsz_command
[
2
],
&
p_message
)
)
else
{
p_message
=
vlm_MessageNew
(
ppsz_command
[
0
],
"Unknown command"
);
goto
error
;
}
#undef IF_EXECUTE
success:
*
pp_message
=
p_message
;
return
VLC_SUCCESS
;
syntax_error:
return
ExecuteSyntaxError
(
ppsz_command
[
0
],
pp_message
);
error:
*
pp_message
=
p_message
;
return
VLC_EGENERIC
;
}
/*****************************************************************************
* Media handling
*****************************************************************************/
vlm_media_sys_t
*
vlm_MediaSearch
(
vlm_t
*
vlm
,
const
char
*
psz_name
)
{
int
i
;
for
(
i
=
0
;
i
<
vlm
->
i_media
;
i
++
)
{
if
(
strcmp
(
psz_name
,
vlm
->
media
[
i
]
->
cfg
.
psz_name
)
==
0
)
return
vlm
->
media
[
i
];
}
return
NULL
;
}
/*****************************************************************************
* Schedule handling
*****************************************************************************/
static
int64_t
vlm_Date
(
void
)
{
#ifdef WIN32
struct
timeb
tm
;
ftime
(
&
tm
);
return
((
int64_t
)
tm
.
time
)
*
1000000
+
((
int64_t
)
tm
.
millitm
)
*
1000
;
#else
struct
timeval
tv_date
;
/* gettimeofday() cannot fail given &tv_date is a valid address */
(
void
)
gettimeofday
(
&
tv_date
,
NULL
);
return
(
mtime_t
)
tv_date
.
tv_sec
*
1000000
+
(
mtime_t
)
tv_date
.
tv_usec
;
#endif
}
static
vlm_schedule_sys_t
*
vlm_ScheduleNew
(
vlm_t
*
vlm
,
const
char
*
psz_name
)
{
vlm_schedule_sys_t
*
p_sched
=
malloc
(
sizeof
(
vlm_schedule_sys_t
)
);
if
(
!
p_sched
)
{
return
NULL
;
}
if
(
!
psz_name
)
{
return
NULL
;
}
p_sched
->
psz_name
=
strdup
(
psz_name
);
p_sched
->
b_enabled
=
false
;
p_sched
->
i_command
=
0
;
p_sched
->
command
=
NULL
;
p_sched
->
i_date
=
0
;
p_sched
->
i_period
=
0
;
p_sched
->
i_repeat
=
-
1
;
TAB_APPEND
(
vlm
->
i_schedule
,
vlm
->
schedule
,
p_sched
);
return
p_sched
;
}
/* for now, simple delete. After, del with options (last arg) */
static
void
vlm_ScheduleDelete
(
vlm_t
*
vlm
,
vlm_schedule_sys_t
*
sched
)
{
if
(
sched
==
NULL
)
return
;
TAB_REMOVE
(
vlm
->
i_schedule
,
vlm
->
schedule
,
sched
);
if
(
vlm
->
i_schedule
==
0
)
free
(
vlm
->
schedule
);
free
(
sched
->
psz_name
);
while
(
sched
->
i_command
)
{
char
*
psz_cmd
=
sched
->
command
[
0
];
TAB_REMOVE
(
sched
->
i_command
,
sched
->
command
,
psz_cmd
);
free
(
psz_cmd
);
}
free
(
sched
);
}
static
vlm_schedule_sys_t
*
vlm_ScheduleSearch
(
vlm_t
*
vlm
,
const
char
*
psz_name
)
{
int
i
;
for
(
i
=
0
;
i
<
vlm
->
i_schedule
;
i
++
)
{
if
(
strcmp
(
psz_name
,
vlm
->
schedule
[
i
]
->
psz_name
)
==
0
)
{
return
vlm
->
schedule
[
i
];
}
}
return
NULL
;
}
/* Ok, setup schedule command will be able to support only one (argument value) at a time */
static
int
vlm_ScheduleSetup
(
vlm_schedule_sys_t
*
schedule
,
const
char
*
psz_cmd
,
const
char
*
psz_value
)
{
if
(
!
strcmp
(
psz_cmd
,
"enabled"
)
)
{
schedule
->
b_enabled
=
true
;
}
else
if
(
!
strcmp
(
psz_cmd
,
"disabled"
)
)
{
schedule
->
b_enabled
=
false
;
}
#if !defined( UNDER_CE )
else
if
(
!
strcmp
(
psz_cmd
,
"date"
)
)
{
struct
tm
time
;
const
char
*
p
;
time_t
date
;
time
.
tm_sec
=
0
;
/* seconds */
time
.
tm_min
=
0
;
/* minutes */
time
.
tm_hour
=
0
;
/* hours */
time
.
tm_mday
=
0
;
/* day of the month */
time
.
tm_mon
=
0
;
/* month */
time
.
tm_year
=
0
;
/* year */
time
.
tm_wday
=
0
;
/* day of the week */
time
.
tm_yday
=
0
;
/* day in the year */
time
.
tm_isdst
=
-
1
;
/* daylight saving time */
/* date should be year/month/day-hour:minutes:seconds */
p
=
strchr
(
psz_value
,
'-'
);
if
(
!
strcmp
(
psz_value
,
"now"
)
)
{
schedule
->
i_date
=
0
;
}
else
if
(
(
p
==
NULL
)
&&
sscanf
(
psz_value
,
"%d:%d:%d"
,
&
time
.
tm_hour
,
&
time
.
tm_min
,
&
time
.
tm_sec
)
!=
3
)
/* it must be a hour:minutes:seconds */
{
return
1
;
}
else
{
unsigned
i
,
j
,
k
;
switch
(
sscanf
(
p
+
1
,
"%u:%u:%u"
,
&
i
,
&
j
,
&
k
)
)
{
case
1
:
time
.
tm_sec
=
i
;
break
;
case
2
:
time
.
tm_min
=
i
;
time
.
tm_sec
=
j
;
break
;
case
3
:
time
.
tm_hour
=
i
;
time
.
tm_min
=
j
;
time
.
tm_sec
=
k
;
break
;
default:
return
1
;
}
switch
(
sscanf
(
psz_value
,
"%d/%d/%d"
,
&
i
,
&
j
,
&
k
)
)
{
case
1
:
time
.
tm_mday
=
i
;
break
;
case
2
:
time
.
tm_mon
=
i
-
1
;
time
.
tm_mday
=
j
;
break
;
case
3
:
time
.
tm_year
=
i
-
1900
;
time
.
tm_mon
=
j
-
1
;
time
.
tm_mday
=
k
;
break
;
default:
return
1
;
}
date
=
mktime
(
&
time
);
schedule
->
i_date
=
((
mtime_t
)
date
)
*
1000000
;
}
}
else
if
(
!
strcmp
(
psz_cmd
,
"period"
)
)
{
struct
tm
time
;
const
char
*
p
;
const
char
*
psz_time
=
NULL
,
*
psz_date
=
NULL
;
time_t
date
;
unsigned
i
,
j
,
k
;
/* First, if date or period are modified, repeat should be equal to -1 */
schedule
->
i_repeat
=
-
1
;
time
.
tm_sec
=
0
;
/* seconds */
time
.
tm_min
=
0
;
/* minutes */
time
.
tm_hour
=
0
;
/* hours */
time
.
tm_mday
=
0
;
/* day of the month */
time
.
tm_mon
=
0
;
/* month */
time
.
tm_year
=
0
;
/* year */
time
.
tm_wday
=
0
;
/* day of the week */
time
.
tm_yday
=
0
;
/* day in the year */
time
.
tm_isdst
=
-
1
;
/* daylight saving time */
/* date should be year/month/day-hour:minutes:seconds */
p
=
strchr
(
psz_value
,
'-'
);
if
(
p
)
{
psz_date
=
psz_value
;
psz_time
=
p
+
1
;
}
else
{
psz_time
=
psz_value
;
}
switch
(
sscanf
(
psz_time
,
"%u:%u:%u"
,
&
i
,
&
j
,
&
k
)
)
{
case
1
:
time
.
tm_sec
=
i
;
break
;
case
2
:
time
.
tm_min
=
i
;
time
.
tm_sec
=
j
;
break
;
case
3
:
time
.
tm_hour
=
i
;
time
.
tm_min
=
j
;
time
.
tm_sec
=
k
;
break
;
default:
return
1
;
}
if
(
psz_date
)
{
switch
(
sscanf
(
psz_date
,
"%u/%u/%u"
,
&
i
,
&
j
,
&
k
)
)
{
case
1
:
time
.
tm_mday
=
i
;
break
;
case
2
:
time
.
tm_mon
=
i
;
time
.
tm_mday
=
j
;
break
;
case
3
:
time
.
tm_year
=
i
;
time
.
tm_mon
=
j
;
time
.
tm_mday
=
k
;
break
;
default:
return
1
;
}
}
/* ok, that's stupid... who is going to schedule streams every 42 years ? */
date
=
((((
time
.
tm_year
*
12
+
time
.
tm_mon
)
*
30
+
time
.
tm_mday
)
*
24
+
time
.
tm_hour
)
*
60
+
time
.
tm_min
)
*
60
+
time
.
tm_sec
;
schedule
->
i_period
=
((
mtime_t
)
date
)
*
1000000
;
}
#endif
/* UNDER_CE */
else
if
(
!
strcmp
(
psz_cmd
,
"repeat"
)
)
{
int
i
;
if
(
sscanf
(
psz_value
,
"%d"
,
&
i
)
==
1
)
{
schedule
->
i_repeat
=
i
;
}
else
{
return
1
;
}
}
else
if
(
!
strcmp
(
psz_cmd
,
"append"
)
)
{
char
*
command
=
strdup
(
psz_value
);
TAB_APPEND
(
schedule
->
i_command
,
schedule
->
command
,
command
);
}
else
{
return
1
;
}
return
0
;
}
/*****************************************************************************
* Message handling functions
*****************************************************************************/
vlm_message_t
*
vlm_MessageNew
(
const
char
*
psz_name
,
const
char
*
psz_format
,
...
)
{
vlm_message_t
*
p_message
;
va_list
args
;
if
(
!
psz_name
)
return
NULL
;
p_message
=
malloc
(
sizeof
(
vlm_message_t
)
);
if
(
!
p_message
)
{
return
NULL
;
}
p_message
->
psz_value
=
0
;
if
(
psz_format
)
{
va_start
(
args
,
psz_format
);
if
(
vasprintf
(
&
p_message
->
psz_value
,
psz_format
,
args
)
==
-
1
)
{
va_end
(
args
);
free
(
p_message
);
return
NULL
;
}
va_end
(
args
);
}
p_message
->
psz_name
=
strdup
(
psz_name
);
p_message
->
i_child
=
0
;
p_message
->
child
=
NULL
;
return
p_message
;
}
void
vlm_MessageDelete
(
vlm_message_t
*
p_message
)
{
free
(
p_message
->
psz_name
);
free
(
p_message
->
psz_value
);
while
(
p_message
->
i_child
--
)
vlm_MessageDelete
(
p_message
->
child
[
p_message
->
i_child
]
);
free
(
p_message
->
child
);
free
(
p_message
);
}
/* Add a child */
vlm_message_t
*
vlm_MessageAdd
(
vlm_message_t
*
p_message
,
vlm_message_t
*
p_child
)
{
if
(
p_message
==
NULL
)
return
NULL
;
if
(
p_child
)
{
TAB_APPEND
(
p_message
->
i_child
,
p_message
->
child
,
p_child
);
}
return
p_child
;
}
/*****************************************************************************
* Misc utility functions
*****************************************************************************/
static
vlm_message_t
*
vlm_ShowMedia
(
vlm_media_sys_t
*
p_media
)
{
vlm_media_t
*
p_cfg
=
&
p_media
->
cfg
;
vlm_message_t
*
p_msg
;
vlm_message_t
*
p_msg_sub
;
int
i
;
p_msg
=
vlm_MessageNew
(
p_cfg
->
psz_name
,
vlm_NULL
);
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"type"
,
p_cfg
->
b_vod
?
"vod"
:
"broadcast"
)
);
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"enabled"
,
p_cfg
->
b_enabled
?
"yes"
:
"no"
)
);
if
(
p_cfg
->
b_vod
)
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"mux"
,
p_cfg
->
vod
.
psz_mux
)
);
else
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"loop"
,
p_cfg
->
broadcast
.
b_loop
?
"yes"
:
"no"
)
);
p_msg_sub
=
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"inputs"
,
vlm_NULL
)
);
for
(
i
=
0
;
i
<
p_cfg
->
i_input
;
i
++
)
{
char
*
psz_tmp
;
if
(
asprintf
(
&
psz_tmp
,
"%d"
,
i
+
1
)
!=
-
1
)
{
vlm_MessageAdd
(
p_msg_sub
,
vlm_MessageNew
(
psz_tmp
,
p_cfg
->
ppsz_input
[
i
]
)
);
free
(
psz_tmp
);
}
}
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"output"
,
p_cfg
->
psz_output
?
p_cfg
->
psz_output
:
""
)
);
p_msg_sub
=
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"options"
,
vlm_NULL
)
);
for
(
i
=
0
;
i
<
p_cfg
->
i_option
;
i
++
)
vlm_MessageAdd
(
p_msg_sub
,
vlm_MessageNew
(
p_cfg
->
ppsz_option
[
i
],
vlm_NULL
)
);
p_msg_sub
=
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"instances"
,
vlm_NULL
)
);
for
(
i
=
0
;
i
<
p_media
->
i_instance
;
i
++
)
{
vlm_media_instance_sys_t
*
p_instance
=
p_media
->
instance
[
i
];
vlc_value_t
val
;
vlm_message_t
*
p_msg_instance
;
char
*
psz_tmp
;
val
.
i_int
=
END_S
;
if
(
p_instance
->
p_input
)
var_Get
(
p_instance
->
p_input
,
"state"
,
&
val
);
p_msg_instance
=
vlm_MessageAdd
(
p_msg_sub
,
vlm_MessageNew
(
"instance"
,
vlm_NULL
)
);
vlm_MessageAdd
(
p_msg_instance
,
vlm_MessageNew
(
"name"
,
p_instance
->
psz_name
?
p_instance
->
psz_name
:
"default"
)
);
vlm_MessageAdd
(
p_msg_instance
,
vlm_MessageNew
(
"state"
,
val
.
i_int
==
PLAYING_S
?
"playing"
:
val
.
i_int
==
PAUSE_S
?
"paused"
:
"stopped"
)
);
/* FIXME should not do that this way */
if
(
p_instance
->
p_input
)
{
#define APPEND_INPUT_INFO( a, format, type ) \
if( asprintf( &psz_tmp, format, \
var_Get ## type( p_instance->p_input, a ) ) != -1 ) \
{ \
vlm_MessageAdd( p_msg_instance, vlm_MessageNew( a, \
psz_tmp ) ); \
free( psz_tmp ); \
}
APPEND_INPUT_INFO
(
"position"
,
"%f"
,
Float
);
APPEND_INPUT_INFO
(
"time"
,
"%"
PRIi64
,
Time
);
APPEND_INPUT_INFO
(
"length"
,
"%"
PRIi64
,
Time
);
APPEND_INPUT_INFO
(
"rate"
,
"%d"
,
Integer
);
APPEND_INPUT_INFO
(
"title"
,
"%d"
,
Integer
);
APPEND_INPUT_INFO
(
"chapter"
,
"%d"
,
Integer
);
APPEND_INPUT_INFO
(
"seekable"
,
"%d"
,
Bool
);
}
#undef APPEND_INPUT_INFO
if
(
asprintf
(
&
psz_tmp
,
"%d"
,
p_instance
->
i_index
+
1
)
!=
-
1
)
{
vlm_MessageAdd
(
p_msg_instance
,
vlm_MessageNew
(
"playlistindex"
,
psz_tmp
)
);
free
(
psz_tmp
);
}
}
return
p_msg
;
}
static
vlm_message_t
*
vlm_Show
(
vlm_t
*
vlm
,
vlm_media_sys_t
*
media
,
/*****************************************************************************
vlm_schedule_sys_t
*
schedule
,
* vlm_New:
const
char
*
psz_filter
)
*****************************************************************************/
vlm_t
*
__vlm_New
(
vlc_object_t
*
p_this
)
{
{
if
(
media
!=
NULL
)
vlc_value_t
lockval
;
{
vlm_t
*
p_vlm
=
NULL
,
**
pp_vlm
=
&
(
libvlc_priv
(
p_this
->
p_libvlc
)
->
p_vlm
);
vlm_message_t
*
p_msg
=
vlm_MessageNew
(
"show"
,
vlm_NULL
);
char
*
psz_vlmconf
;
if
(
p_msg
)
static
const
char
vlm_object_name
[]
=
"vlm daemon"
;
vlm_MessageAdd
(
p_msg
,
vlm_ShowMedia
(
media
)
);
return
p_msg
;
}
else
if
(
schedule
!=
NULL
)
{
int
i
;
vlm_message_t
*
msg
;
vlm_message_t
*
msg_schedule
;
vlm_message_t
*
msg_child
;
char
buffer
[
100
];
msg
=
vlm_MessageNew
(
"show"
,
vlm_NULL
);
msg_schedule
=
vlm_MessageAdd
(
msg
,
vlm_MessageNew
(
schedule
->
psz_name
,
vlm_NULL
)
);
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"type"
,
"schedule"
)
);
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"enabled"
,
schedule
->
b_enabled
?
"yes"
:
"no"
)
);
#if !defined( UNDER_CE )
if
(
schedule
->
i_date
!=
0
)
{
struct
tm
date
;
time_t
i_time
=
(
time_t
)(
schedule
->
i_date
/
1000000
);
char
*
psz_date
;
localtime_r
(
&
i_time
,
&
date
);
if
(
asprintf
(
&
psz_date
,
"%d/%d/%d-%d:%d:%d"
,
date
.
tm_year
+
1900
,
date
.
tm_mon
+
1
,
date
.
tm_mday
,
date
.
tm_hour
,
date
.
tm_min
,
date
.
tm_sec
)
!=
-
1
)
{
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"date"
,
psz_date
)
);
free
(
psz_date
);
}
}
else
{
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"date"
,
"now"
)
);
}
if
(
schedule
->
i_period
!=
0
)
{
time_t
i_time
=
(
time_t
)
(
schedule
->
i_period
/
1000000
);
struct
tm
date
;
date
.
tm_sec
=
(
int
)(
i_time
%
60
);
i_time
=
i_time
/
60
;
date
.
tm_min
=
(
int
)(
i_time
%
60
);
i_time
=
i_time
/
60
;
date
.
tm_hour
=
(
int
)(
i_time
%
24
);
i_time
=
i_time
/
24
;
date
.
tm_mday
=
(
int
)(
i_time
%
30
);
i_time
=
i_time
/
30
;
/* okay, okay, months are not always 30 days long */
date
.
tm_mon
=
(
int
)(
i_time
%
12
);
i_time
=
i_time
/
12
;
date
.
tm_year
=
(
int
)
i_time
;
sprintf
(
buffer
,
"%d/%d/%d-%d:%d:%d"
,
date
.
tm_year
,
date
.
tm_mon
,
date
.
tm_mday
,
date
.
tm_hour
,
date
.
tm_min
,
date
.
tm_sec
);
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"period"
,
buffer
)
);
}
else
{
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"period"
,
"0"
)
);
}
#endif
/* UNDER_CE */
sprintf
(
buffer
,
"%d"
,
schedule
->
i_repeat
);
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"repeat"
,
buffer
)
);
msg_child
=
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"commands"
,
vlm_NULL
)
);
for
(
i
=
0
;
i
<
schedule
->
i_command
;
i
++
)
/* Avoid multiple creation */
{
if
(
var_Create
(
p_this
->
p_libvlc
,
"vlm_mutex"
,
VLC_VAR_MUTEX
)
||
vlm_MessageAdd
(
msg_child
,
var_Get
(
p_this
->
p_libvlc
,
"vlm_mutex"
,
&
lockval
)
)
vlm_MessageNew
(
schedule
->
command
[
i
],
vlm_NULL
)
);
return
NULL
;
}
return
msg
;
vlc_mutex_lock
(
lockval
.
p_address
)
;
p_vlm
=
*
pp_vlm
;
if
(
p_vlm
)
{
/* VLM already exists */
vlc_object_yield
(
p_vlm
);
vlc_mutex_unlock
(
lockval
.
p_address
);
return
p_vlm
;
}
}
else
if
(
psz_filter
&&
!
strcmp
(
psz_filter
,
"media"
)
)
msg_Dbg
(
p_this
,
"creating VLM"
);
{
vlm_message_t
*
p_msg
;
vlm_message_t
*
p_msg_child
;
int
i_vod
=
0
,
i_broadcast
=
0
;
int
i
;
char
*
psz_count
;
for
(
i
=
0
;
i
<
vlm
->
i_media
;
i
++
)
{
if
(
vlm
->
media
[
i
]
->
cfg
.
b_vod
)
i_vod
++
;
else
i_broadcast
++
;
}
if
(
asprintf
(
&
psz_count
,
"( %d broadcast - %d vod )"
,
i_broadcast
,
p_vlm
=
vlc_custom_create
(
p_this
,
sizeof
(
*
p_vlm
),
VLC_OBJECT_GENERIC
,
i_vod
)
==
-
1
)
vlm_object_name
);
return
NULL
;
if
(
!
p_vlm
)
p_msg
=
vlm_MessageNew
(
"show"
,
vlm_NULL
);
{
p_msg_child
=
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"media"
,
psz_count
)
);
vlc_mutex_unlock
(
lockval
.
p_address
);
free
(
psz_count
);
return
NULL
;
}
for
(
i
=
0
;
i
<
vlm
->
i_media
;
i
++
)
vlc_mutex_init
(
&
p_vlm
->
lock
);
vlm_MessageAdd
(
p_msg_child
,
vlm_ShowMedia
(
vlm
->
media
[
i
]
)
);
p_vlm
->
i_id
=
1
;
TAB_INIT
(
p_vlm
->
i_media
,
p_vlm
->
media
);
TAB_INIT
(
p_vlm
->
i_schedule
,
p_vlm
->
schedule
);
p_vlm
->
i_vod
=
0
;
p_vlm
->
p_vod
=
NULL
;
vlc_object_attach
(
p_vlm
,
p_this
->
p_libvlc
);
return
p_msg
;
if
(
vlc_thread_create
(
p_vlm
,
"vlm thread"
,
Manage
,
VLC_THREAD_PRIORITY_LOW
,
false
)
)
{
vlc_mutex_destroy
(
&
p_vlm
->
lock
);
vlc_object_release
(
p_vlm
);
return
NULL
;
}
}
else
if
(
psz_filter
&&
!
strcmp
(
psz_filter
,
"schedule"
)
)
/* Load our configuration file */
psz_vlmconf
=
var_CreateGetString
(
p_vlm
,
"vlm-conf"
);
if
(
psz_vlmconf
&&
*
psz_vlmconf
)
{
{
int
i
;
vlm_message_t
*
p_message
=
NULL
;
vlm_message_t
*
msg
;
char
*
psz_buffer
=
NULL
;
vlm_message_t
*
msg_child
;
msg
=
vlm_MessageNew
(
"show"
,
vlm_NULL
);
msg_child
=
vlm_MessageAdd
(
msg
,
vlm_MessageNew
(
"schedule"
,
vlm_NULL
)
);
for
(
i
=
0
;
i
<
vlm
->
i_schedule
;
i
++
)
msg_Dbg
(
p_this
,
"loading VLM configuration"
);
if
(
asprintf
(
&
psz_buffer
,
"load %s"
,
psz_vlmconf
)
==
-
1
)
psz_buffer
=
NULL
;
if
(
psz_buffer
)
{
{
vlm_schedule_sys_t
*
s
=
vlm
->
schedule
[
i
];
msg_Dbg
(
p_this
,
psz_buffer
);
vlm_message_t
*
msg_schedule
;
if
(
vlm_ExecuteCommand
(
p_vlm
,
psz_buffer
,
&
p_message
)
)
mtime_t
i_time
,
i_next_date
;
msg_Warn
(
p_this
,
"error while loading the configuration file"
);
msg_schedule
=
vlm_MessageAdd
(
msg_child
,
vlm_MessageNew
(
s
->
psz_name
,
vlm_NULL
)
);
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"enabled"
,
s
->
b_enabled
?
"yes"
:
"no"
)
);
/* calculate next date */
i_time
=
vlm_Date
();
i_next_date
=
s
->
i_date
;
if
(
s
->
i_period
!=
0
)
{
int
j
=
0
;
while
(
s
->
i_date
+
j
*
s
->
i_period
<=
i_time
&&
s
->
i_repeat
>
j
)
{
j
++
;
}
i_next_date
=
s
->
i_date
+
j
*
s
->
i_period
;
}
if
(
i_next_date
>
i_time
)
{
time_t
i_date
=
(
time_t
)
(
i_next_date
/
1000000
)
;
#if !defined( UNDER_CE )
#ifdef HAVE_CTIME_R
char
psz_date
[
500
];
ctime_r
(
&
i_date
,
psz_date
);
#else
char
*
psz_date
=
ctime
(
&
i_date
);
#endif
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageDelete
(
p_message
);
vlm_MessageNew
(
"next launch"
,
psz_date
)
);
free
(
psz_buffer
);
#endif
}
}
}
return
msg
;
}
}
free
(
psz_vlmconf
);
else
if
(
(
psz_filter
==
NULL
)
&&
(
media
==
NULL
)
&&
(
schedule
==
NULL
)
)
vlc_object_set_destructor
(
p_vlm
,
(
vlc_destructor_t
)
vlm_Destructor
);
{
*
pp_vlm
=
p_vlm
;
/* for future reference */
vlm_message_t
*
show1
=
vlm_Show
(
vlm
,
NULL
,
NULL
,
"media"
);
vlc_mutex_unlock
(
lockval
.
p_address
);
vlm_message_t
*
show2
=
vlm_Show
(
vlm
,
NULL
,
NULL
,
"schedule"
);
vlm_MessageAdd
(
show1
,
show2
->
child
[
0
]
);
/* We must destroy the parent node "show" of show2
* and not the children */
free
(
show2
->
psz_name
);
free
(
show2
);
return
show1
;
}
else
return
p_vlm
;
{
return
vlm_MessageNew
(
"show"
,
vlm_NULL
);
}
}
}
/*****************************************************************************
/*****************************************************************************
*
Config handling functions
*
vlm_Delete:
*****************************************************************************/
*****************************************************************************/
static
int
Load
(
vlm_t
*
vlm
,
char
*
file
)
void
vlm_Delete
(
vlm_t
*
p_vlm
)
{
{
char
*
pf
=
file
;
vlc_value_t
lockval
;
int
i_line
=
1
;
while
(
*
pf
!=
'\0'
)
{
vlm_message_t
*
message
=
NULL
;
int
i_end
=
0
;
while
(
pf
[
i_end
]
!=
'\n'
&&
pf
[
i_end
]
!=
'\0'
&&
pf
[
i_end
]
!=
'\r'
)
{
i_end
++
;
}
if
(
pf
[
i_end
]
==
'\r'
||
pf
[
i_end
]
==
'\n'
)
{
pf
[
i_end
]
=
'\0'
;
i_end
++
;
if
(
pf
[
i_end
]
==
'\n'
)
i_end
++
;
}
if
(
*
pf
&&
ExecuteCommand
(
vlm
,
pf
,
&
message
)
)
{
if
(
message
)
{
if
(
message
->
psz_value
)
msg_Err
(
vlm
,
"Load error on line %d: %s: %s"
,
i_line
,
message
->
psz_name
,
message
->
psz_value
);
vlm_MessageDelete
(
message
);
}
return
1
;
}
if
(
message
)
vlm_MessageDelete
(
message
);
pf
+=
i_end
;
i_line
++
;
}
return
0
;
/* vlm_Delete() is serialized against itself, and against vlm_New().
* This way, vlm_Destructor () (called from vlc_objet_release() above)
* is serialized against setting libvlc_priv->p_vlm from vlm_New(). */
var_Get
(
p_vlm
->
p_libvlc
,
"vlm_mutex"
,
&
lockval
);
vlc_mutex_lock
(
lockval
.
p_address
);
vlc_object_release
(
p_vlm
);
vlc_mutex_unlock
(
lockval
.
p_address
);
}
}
static
char
*
Save
(
vlm_t
*
vlm
)
/*****************************************************************************
* vlm_Destructor:
*****************************************************************************/
static
void
vlm_Destructor
(
vlm_t
*
p_vlm
)
{
{
char
*
save
=
NULL
;
libvlc_priv
(
p_vlm
->
p_libvlc
)
->
p_vlm
=
NULL
;
char
psz_header
[]
=
"
\n
"
"# VLC media player VLM command batch
\n
"
"# http://www.videolan.org/vlc/
\n\n
"
;
char
*
p
;
int
i
,
j
;
int
i_length
=
strlen
(
psz_header
);
for
(
i
=
0
;
i
<
vlm
->
i_media
;
i
++
)
{
vlm_media_sys_t
*
media
=
vlm
->
media
[
i
];
vlm_media_t
*
p_cfg
=
&
media
->
cfg
;
if
(
p_cfg
->
b_vod
)
i_length
+=
strlen
(
"new * vod "
)
+
strlen
(
p_cfg
->
psz_name
);
else
i_length
+=
strlen
(
"new * broadcast "
)
+
strlen
(
p_cfg
->
psz_name
);
if
(
p_cfg
->
b_enabled
==
true
)
i_length
+=
strlen
(
"enabled"
);
else
i_length
+=
strlen
(
"disabled"
);
if
(
!
p_cfg
->
b_vod
&&
p_cfg
->
broadcast
.
b_loop
==
true
)
i_length
+=
strlen
(
" loop
\n
"
);
else
i_length
+=
strlen
(
"
\n
"
);
for
(
j
=
0
;
j
<
p_cfg
->
i_input
;
j
++
)
i_length
+=
strlen
(
"setup * input
\"\"\n
"
)
+
strlen
(
p_cfg
->
psz_name
)
+
strlen
(
p_cfg
->
ppsz_input
[
j
]
);
if
(
p_cfg
->
psz_output
!=
NULL
)
i_length
+=
strlen
(
"setup * output
\n
"
)
+
strlen
(
p_cfg
->
psz_name
)
+
strlen
(
p_cfg
->
psz_output
);
for
(
j
=
0
;
j
<
p_cfg
->
i_option
;
j
++
)
i_length
+=
strlen
(
"setup * option
\n
"
)
+
strlen
(
p_cfg
->
psz_name
)
+
strlen
(
p_cfg
->
ppsz_option
[
j
]);
if
(
p_cfg
->
b_vod
&&
p_cfg
->
vod
.
psz_mux
)
i_length
+=
strlen
(
"setup * mux
\n
"
)
+
strlen
(
p_cfg
->
psz_name
)
+
strlen
(
p_cfg
->
vod
.
psz_mux
);
}
for
(
i
=
0
;
i
<
vlm
->
i_schedule
;
i
++
)
{
vlm_schedule_sys_t
*
schedule
=
vlm
->
schedule
[
i
];
i_length
+=
strlen
(
"new schedule "
)
+
strlen
(
schedule
->
psz_name
);
if
(
schedule
->
b_enabled
==
true
)
{
i_length
+=
strlen
(
"date //-:: enabled
\n
"
)
+
14
;
}
else
{
i_length
+=
strlen
(
"date //-:: disabled
\n
"
)
+
14
;
}
if
(
schedule
->
i_period
!=
0
)
{
i_length
+=
strlen
(
"setup "
)
+
strlen
(
schedule
->
psz_name
)
+
strlen
(
"period //-::
\n
"
)
+
14
;
}
if
(
schedule
->
i_repeat
>=
0
)
{
char
buffer
[
12
];
sprintf
(
buffer
,
"%d"
,
schedule
->
i_repeat
);
i_length
+=
strlen
(
"setup repeat
\n
"
)
+
strlen
(
schedule
->
psz_name
)
+
strlen
(
buffer
);
}
else
{
i_length
++
;
}
for
(
j
=
0
;
j
<
schedule
->
i_command
;
j
++
)
{
i_length
+=
strlen
(
"setup append
\n
"
)
+
strlen
(
schedule
->
psz_name
)
+
strlen
(
schedule
->
command
[
j
]
);
}
}
/* Don't forget the '\0' */
i_length
++
;
/* now we have the length of save */
p
=
save
=
malloc
(
i_length
);
if
(
!
save
)
return
NULL
;
*
save
=
'\0'
;
p
+=
sprintf
(
p
,
"%s"
,
psz_header
);
/* finally we can write in it */
for
(
i
=
0
;
i
<
vlm
->
i_media
;
i
++
)
{
vlm_media_sys_t
*
media
=
vlm
->
media
[
i
];
vlm_media_t
*
p_cfg
=
&
media
->
cfg
;
if
(
p_cfg
->
b_vod
)
p
+=
sprintf
(
p
,
"new %s vod "
,
p_cfg
->
psz_name
);
else
p
+=
sprintf
(
p
,
"new %s broadcast "
,
p_cfg
->
psz_name
);
if
(
p_cfg
->
b_enabled
)
p
+=
sprintf
(
p
,
"enabled"
);
else
p
+=
sprintf
(
p
,
"disabled"
);
if
(
!
p_cfg
->
b_vod
&&
p_cfg
->
broadcast
.
b_loop
)
p
+=
sprintf
(
p
,
" loop
\n
"
);
else
p
+=
sprintf
(
p
,
"
\n
"
);
for
(
j
=
0
;
j
<
p_cfg
->
i_input
;
j
++
)
p
+=
sprintf
(
p
,
"setup %s input
\"
%s
\"\n
"
,
p_cfg
->
psz_name
,
p_cfg
->
ppsz_input
[
j
]
);
if
(
p_cfg
->
psz_output
)
p
+=
sprintf
(
p
,
"setup %s output %s
\n
"
,
p_cfg
->
psz_name
,
p_cfg
->
psz_output
);
for
(
j
=
0
;
j
<
p_cfg
->
i_option
;
j
++
)
p
+=
sprintf
(
p
,
"setup %s option %s
\n
"
,
p_cfg
->
psz_name
,
p_cfg
->
ppsz_option
[
j
]
);
if
(
p_cfg
->
b_vod
&&
p_cfg
->
vod
.
psz_mux
)
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_MEDIAS
);
p
+=
sprintf
(
p
,
"setup %s mux %s
\n
"
,
p_cfg
->
psz_name
,
p_cfg
->
vod
.
psz_mux
);
TAB_CLEAN
(
p_vlm
->
i_media
,
p_vlm
->
media
);
}
/* and now, the schedule scripts */
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_SCHEDULES
);
#if !defined( UNDER_CE )
TAB_CLEAN
(
p_vlm
->
schedule
,
p_vlm
->
schedule
);
for
(
i
=
0
;
i
<
vlm
->
i_schedule
;
i
++
)
{
vlm_schedule_sys_t
*
schedule
=
vlm
->
schedule
[
i
];
struct
tm
date
;
time_t
i_time
=
(
time_t
)
(
schedule
->
i_date
/
1000000
);
localtime_r
(
&
i_time
,
&
date
);
vlc_mutex_destroy
(
&
p_vlm
->
lock
);
p
+=
sprintf
(
p
,
"new %s schedule "
,
schedule
->
psz_name
);
}
if
(
schedule
->
b_enabled
==
true
)
/*****************************************************************************
{
* vlm_ExecuteCommand:
p
+=
sprintf
(
p
,
"date %d/%d/%d-%d:%d:%d enabled
\n
"
,
*****************************************************************************/
date
.
tm_year
+
1900
,
date
.
tm_mon
+
1
,
date
.
tm_mday
,
int
vlm_ExecuteCommand
(
vlm_t
*
p_vlm
,
const
char
*
psz_command
,
date
.
tm_hour
,
date
.
tm_min
,
date
.
tm_sec
);
vlm_message_t
**
pp_message
)
}
{
else
int
i_result
;
{
p
+=
sprintf
(
p
,
"date %d/%d/%d-%d:%d:%d disabled
\n
"
,
date
.
tm_year
+
1900
,
date
.
tm_mon
+
1
,
date
.
tm_mday
,
date
.
tm_hour
,
date
.
tm_min
,
date
.
tm_sec
);
}
if
(
schedule
->
i_period
!=
0
)
vlc_mutex_lock
(
&
p_vlm
->
lock
);
{
i_result
=
ExecuteCommand
(
p_vlm
,
psz_command
,
pp_message
);
p
+=
sprintf
(
p
,
"setup %s "
,
schedule
->
psz_name
);
vlc_mutex_unlock
(
&
p_vlm
->
lock
);
i_time
=
(
time_t
)
(
schedule
->
i_period
/
1000000
);
date
.
tm_sec
=
(
int
)(
i_time
%
60
);
i_time
=
i_time
/
60
;
date
.
tm_min
=
(
int
)(
i_time
%
60
);
i_time
=
i_time
/
60
;
date
.
tm_hour
=
(
int
)(
i_time
%
24
);
i_time
=
i_time
/
24
;
date
.
tm_mday
=
(
int
)(
i_time
%
30
);
i_time
=
i_time
/
30
;
/* okay, okay, months are not always 30 days long */
date
.
tm_mon
=
(
int
)(
i_time
%
12
);
i_time
=
i_time
/
12
;
date
.
tm_year
=
(
int
)
i_time
;
p
+=
sprintf
(
p
,
"period %d/%d/%d-%d:%d:%d
\n
"
,
date
.
tm_year
,
date
.
tm_mon
,
date
.
tm_mday
,
date
.
tm_hour
,
date
.
tm_min
,
date
.
tm_sec
);
}
if
(
schedule
->
i_repeat
>=
0
)
return
i_result
;
{
}
p
+=
sprintf
(
p
,
"setup %s repeat %d
\n
"
,
schedule
->
psz_name
,
schedule
->
i_repeat
);
}
else
{
p
+=
sprintf
(
p
,
"
\n
"
);
}
for
(
j
=
0
;
j
<
schedule
->
i_command
;
j
++
)
{
p
+=
sprintf
(
p
,
"setup %s append %s
\n
"
,
schedule
->
psz_name
,
schedule
->
command
[
j
]
);
}
}
int64_t
vlm_Date
(
void
)
#endif
/* UNDER_CE */
{
#ifdef WIN32
struct
timeb
tm
;
ftime
(
&
tm
);
return
((
int64_t
)
tm
.
time
)
*
1000000
+
((
int64_t
)
tm
.
millitm
)
*
1000
;
#else
struct
timeval
tv_date
;
return
save
;
/* gettimeofday() cannot fail given &tv_date is a valid address */
(
void
)
gettimeofday
(
&
tv_date
,
NULL
);
return
(
mtime_t
)
tv_date
.
tv_sec
*
1000000
+
(
mtime_t
)
tv_date
.
tv_usec
;
#endif
}
}
/*****************************************************************************
/*****************************************************************************
*
*
*****************************************************************************/
*****************************************************************************/
...
@@ -2746,6 +982,7 @@ static int vlm_ControlMediaInstanceGets( vlm_t *p_vlm, int64_t id, vlm_media_ins
...
@@ -2746,6 +982,7 @@ static int vlm_ControlMediaInstanceGets( vlm_t *p_vlm, int64_t id, vlm_media_ins
*
pi_instance
=
i_idsc
;
*
pi_instance
=
i_idsc
;
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
static
int
vlm_ControlMediaInstanceClear
(
vlm_t
*
p_vlm
,
int64_t
id
)
static
int
vlm_ControlMediaInstanceClear
(
vlm_t
*
p_vlm
,
int64_t
id
)
{
{
vlm_media_sys_t
*
p_media
=
vlm_ControlMediaGetById
(
p_vlm
,
id
);
vlm_media_sys_t
*
p_media
=
vlm_ControlMediaGetById
(
p_vlm
,
id
);
...
@@ -2766,6 +1003,7 @@ static int vlm_ControlScheduleClear( vlm_t *p_vlm )
...
@@ -2766,6 +1003,7 @@ static int vlm_ControlScheduleClear( vlm_t *p_vlm )
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
}
}
static
int
vlm_vaControlInternal
(
vlm_t
*
p_vlm
,
int
i_query
,
va_list
args
)
static
int
vlm_vaControlInternal
(
vlm_t
*
p_vlm
,
int
i_query
,
va_list
args
)
{
{
vlm_media_t
*
p_dsc
;
vlm_media_t
*
p_dsc
;
...
@@ -2886,7 +1124,8 @@ static int vlm_vaControlInternal( vlm_t *p_vlm, int i_query, va_list args )
...
@@ -2886,7 +1124,8 @@ static int vlm_vaControlInternal( vlm_t *p_vlm, int i_query, va_list args )
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
}
}
static
int
vlm_ControlInternal
(
vlm_t
*
p_vlm
,
int
i_query
,
...
)
int
vlm_ControlInternal
(
vlm_t
*
p_vlm
,
int
i_query
,
...
)
{
{
va_list
args
;
va_list
args
;
int
i_result
;
int
i_result
;
...
...
src/input/vlm_internal.h
View file @
8e18f5c6
...
@@ -105,4 +105,9 @@ struct vlm_t
...
@@ -105,4 +105,9 @@ struct vlm_t
vlm_schedule_sys_t
**
schedule
;
vlm_schedule_sys_t
**
schedule
;
};
};
int64_t
vlm_Date
(
void
);
int
vlm_ControlInternal
(
vlm_t
*
p_vlm
,
int
i_query
,
...
);
int
ExecuteCommand
(
vlm_t
*
,
const
char
*
,
vlm_message_t
**
);
void
vlm_ScheduleDelete
(
vlm_t
*
vlm
,
vlm_schedule_sys_t
*
sched
);
#endif
#endif
src/input/vlmshell.c
0 → 100644
View file @
8e18f5c6
/*****************************************************************************
* vlm.c: VLM interface plugin
*****************************************************************************
* Copyright (C) 2000-2005 the VideoLAN team
* $Id$
*
* Authors: Simon Latapie <garf@videolan.org>
* Laurent Aimar <fenrir@videolan.org>
* Gildas Bazin <gbazin@videolan.org>
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc/vlc.h>
#include <stdio.h>
#include <ctype.h>
/* tolower() */
#include <assert.h>
#include <vlc_vlm.h>
#ifdef ENABLE_VLM
#ifndef WIN32
# include <sys/time.h>
/* gettimeofday() */
#endif
#ifdef HAVE_TIME_H
# include <time.h>
/* ctime() */
# include <sys/timeb.h>
/* ftime() */
#endif
#include <vlc_input.h>
#include "input_internal.h"
#include <vlc_stream.h>
#include "vlm_internal.h"
#include <vlc_vod.h>
#include <vlc_charset.h>
#include <vlc_sout.h>
#include "../stream_output/stream_output.h"
#include "../libvlc.h"
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
/* ugly kludge to avoid "null format string" warnings,
* even if we handle NULL format string in vlm_MessageNew() */
static
const
char
*
vlm_NULL
=
NULL
;
/* */
static
vlm_message_t
*
vlm_Show
(
vlm_t
*
,
vlm_media_sys_t
*
,
vlm_schedule_sys_t
*
,
const
char
*
);
static
vlm_schedule_sys_t
*
vlm_ScheduleSearch
(
vlm_t
*
,
const
char
*
);
static
char
*
Save
(
vlm_t
*
);
static
int
Load
(
vlm_t
*
,
char
*
);
static
vlm_schedule_sys_t
*
vlm_ScheduleNew
(
vlm_t
*
vlm
,
const
char
*
psz_name
);
static
int
vlm_ScheduleSetup
(
vlm_schedule_sys_t
*
schedule
,
const
char
*
psz_cmd
,
const
char
*
psz_value
);
/* */
static
vlm_media_sys_t
*
vlm_MediaSearch
(
vlm_t
*
,
const
char
*
);
static
const
char
quotes
[]
=
"
\"
'"
;
/**
* FindCommandEnd: look for the end of a possibly quoted string
* @return NULL on mal-formatted string,
* pointer past the last character otherwise.
*/
static
const
char
*
FindCommandEnd
(
const
char
*
psz_sent
)
{
char
c
,
quote
=
0
;
while
(
(
c
=
*
psz_sent
)
!=
'\0'
)
{
if
(
!
quote
)
{
if
(
strchr
(
quotes
,
c
)
)
// opening quote
quote
=
c
;
else
if
(
isspace
(
c
)
)
// non-escaped space
return
psz_sent
;
else
if
(
c
==
'\\'
)
{
psz_sent
++
;
// skip escaped character
if
(
*
psz_sent
==
'\0'
)
return
psz_sent
;
}
}
else
{
if
(
c
==
quote
)
// non-escaped matching quote
quote
=
0
;
else
if
(
(
quote
==
'"'
)
&&
(
c
==
'\\'
)
)
{
psz_sent
++
;
// skip escaped character
if
(
*
psz_sent
==
'\0'
)
return
NULL
;
// error, closing quote missing
}
}
psz_sent
++
;
}
// error (NULL) if we could not find a matching quote
return
quote
?
NULL
:
psz_sent
;
}
/**
* Unescape a nul-terminated string.
* Note that in and out can be identical.
*
* @param out output buffer (at least <strlen (in) + 1> characters long)
* @param in nul-terminated string to be unescaped
*
* @return 0 on success, -1 on error.
*/
static
int
Unescape
(
char
*
out
,
const
char
*
in
)
{
char
c
,
quote
=
0
;
while
(
(
c
=
*
in
++
)
!=
'\0'
)
{
if
(
!
quote
)
{
if
(
strchr
(
quotes
,
c
))
// opening quote
{
quote
=
c
;
continue
;
}
else
if
(
c
==
'\\'
)
{
switch
(
c
=
*
in
++
)
{
case
'"'
:
case
'\''
:
case
'\\'
:
*
out
++
=
c
;
continue
;
case
'\0'
:
*
out
=
'\0'
;
return
0
;
}
if
(
isspace
(
c
)
)
{
*
out
++
=
c
;
continue
;
}
/* None of the special cases - copy the backslash */
*
out
++
=
'\\'
;
}
}
else
{
if
(
c
==
quote
)
// non-escaped matching quote
{
quote
=
0
;
continue
;
}
if
(
(
quote
==
'"'
)
&&
(
c
==
'\\'
)
)
{
switch
(
c
=
*
in
++
)
{
case
'"'
:
case
'\\'
:
*
out
++
=
c
;
continue
;
case
'\0'
:
// should never happen
*
out
=
'\0'
;
return
-
1
;
}
/* None of the special cases - copy the backslash */
*
out
++
=
'\\'
;
}
}
*
out
++
=
c
;
}
*
out
=
'\0'
;
return
0
;
}
/*****************************************************************************
* ExecuteCommand: The main state machine
*****************************************************************************
* Execute a command which ends with '\0' (string)
*****************************************************************************/
static
int
ExecuteSyntaxError
(
const
char
*
psz_cmd
,
vlm_message_t
**
pp_status
)
{
*
pp_status
=
vlm_MessageNew
(
psz_cmd
,
"Wrong command syntax"
);
return
VLC_EGENERIC
;
}
static
bool
ExecuteIsMedia
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
)
{
int64_t
id
;
if
(
!
psz_name
||
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_ID
,
psz_name
,
&
id
)
)
return
false
;
return
true
;
}
static
bool
ExecuteIsSchedule
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
)
{
if
(
!
psz_name
||
!
vlm_ScheduleSearch
(
p_vlm
,
psz_name
)
)
return
false
;
return
true
;
}
static
int
ExecuteDel
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
,
vlm_message_t
**
pp_status
)
{
vlm_media_sys_t
*
p_media
;
vlm_schedule_sys_t
*
p_schedule
;
p_media
=
vlm_MediaSearch
(
p_vlm
,
psz_name
);
p_schedule
=
vlm_ScheduleSearch
(
p_vlm
,
psz_name
);
if
(
p_schedule
!=
NULL
)
{
vlm_ScheduleDelete
(
p_vlm
,
p_schedule
);
}
else
if
(
p_media
!=
NULL
)
{
vlm_ControlInternal
(
p_vlm
,
VLM_DEL_MEDIA
,
p_media
->
cfg
.
id
);
}
else
if
(
!
strcmp
(
psz_name
,
"media"
)
)
{
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_MEDIAS
);
}
else
if
(
!
strcmp
(
psz_name
,
"schedule"
)
)
{
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_SCHEDULES
);
}
else
if
(
!
strcmp
(
psz_name
,
"all"
)
)
{
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_MEDIAS
);
vlm_ControlInternal
(
p_vlm
,
VLM_CLEAR_SCHEDULES
);
}
else
{
*
pp_status
=
vlm_MessageNew
(
"del"
,
"%s: media unknown"
,
psz_name
);
return
VLC_EGENERIC
;
}
*
pp_status
=
vlm_MessageNew
(
"del"
,
vlm_NULL
);
return
VLC_SUCCESS
;
}
static
int
ExecuteShow
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
,
vlm_message_t
**
pp_status
)
{
vlm_media_sys_t
*
p_media
;
vlm_schedule_sys_t
*
p_schedule
;
if
(
!
psz_name
)
{
*
pp_status
=
vlm_Show
(
p_vlm
,
NULL
,
NULL
,
NULL
);
return
VLC_SUCCESS
;
}
p_media
=
vlm_MediaSearch
(
p_vlm
,
psz_name
);
p_schedule
=
vlm_ScheduleSearch
(
p_vlm
,
psz_name
);
if
(
p_schedule
!=
NULL
)
*
pp_status
=
vlm_Show
(
p_vlm
,
NULL
,
p_schedule
,
NULL
);
else
if
(
p_media
!=
NULL
)
*
pp_status
=
vlm_Show
(
p_vlm
,
p_media
,
NULL
,
NULL
);
else
*
pp_status
=
vlm_Show
(
p_vlm
,
NULL
,
NULL
,
psz_name
);
return
VLC_SUCCESS
;
}
static
int
ExecuteHelp
(
vlm_message_t
**
pp_status
)
{
vlm_message_t
*
message_child
;
#define MessageAdd( a ) \
vlm_MessageAdd( *pp_status, vlm_MessageNew( a, vlm_NULL ) );
#define MessageAddChild( a ) \
vlm_MessageAdd( message_child, vlm_MessageNew( a, vlm_NULL ) );
*
pp_status
=
vlm_MessageNew
(
"help"
,
vlm_NULL
);
message_child
=
MessageAdd
(
"Commands Syntax:"
);
MessageAddChild
(
"new (name) vod|broadcast|schedule [properties]"
);
MessageAddChild
(
"setup (name) (properties)"
);
MessageAddChild
(
"show [(name)|media|schedule]"
);
MessageAddChild
(
"del (name)|all|media|schedule"
);
MessageAddChild
(
"control (name) [instance_name] (command)"
);
MessageAddChild
(
"save (config_file)"
);
MessageAddChild
(
"export"
);
MessageAddChild
(
"load (config_file)"
);
message_child
=
MessageAdd
(
"Media Proprieties Syntax:"
);
MessageAddChild
(
"input (input_name)"
);
MessageAddChild
(
"inputdel (input_name)|all"
);
MessageAddChild
(
"inputdeln input_number"
);
MessageAddChild
(
"output (output_name)"
);
MessageAddChild
(
"option (option_name)[=value]"
);
MessageAddChild
(
"enabled|disabled"
);
MessageAddChild
(
"loop|unloop (broadcast only)"
);
MessageAddChild
(
"mux (mux_name)"
);
message_child
=
MessageAdd
(
"Schedule Proprieties Syntax:"
);
MessageAddChild
(
"enabled|disabled"
);
MessageAddChild
(
"append (command_until_rest_of_the_line)"
);
MessageAddChild
(
"date (year)/(month)/(day)-(hour):(minutes):"
"(seconds)|now"
);
MessageAddChild
(
"period (years_aka_12_months)/(months_aka_30_days)/"
"(days)-(hours):(minutes):(seconds)"
);
MessageAddChild
(
"repeat (number_of_repetitions)"
);
message_child
=
MessageAdd
(
"Control Commands Syntax:"
);
MessageAddChild
(
"play [input_number]"
);
MessageAddChild
(
"pause"
);
MessageAddChild
(
"stop"
);
MessageAddChild
(
"seek [+-](percentage) | [+-](seconds)s | [+-](miliseconds)ms"
);
return
VLC_SUCCESS
;
}
static
int
ExecuteControl
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
,
const
int
i_arg
,
char
**
ppsz_arg
,
vlm_message_t
**
pp_status
)
{
vlm_media_sys_t
*
p_media
;
const
char
*
psz_control
=
NULL
;
const
char
*
psz_instance
=
NULL
;
const
char
*
psz_argument
=
NULL
;
int
i_index
;
int
i_result
;
if
(
!
ExecuteIsMedia
(
p_vlm
,
psz_name
)
)
{
*
pp_status
=
vlm_MessageNew
(
"control"
,
"%s: media unknown"
,
psz_name
);
return
VLC_EGENERIC
;
}
assert
(
i_arg
>
0
);
#define IS(txt) ( !strcmp( ppsz_arg[i_index], (txt) ) )
i_index
=
0
;
if
(
!
IS
(
"play"
)
&&
!
IS
(
"stop"
)
&&
!
IS
(
"pause"
)
&&
!
IS
(
"seek"
)
)
{
i_index
=
1
;
psz_instance
=
ppsz_arg
[
0
];
if
(
i_index
>=
i_arg
||
(
!
IS
(
"play"
)
&&
!
IS
(
"stop"
)
&&
!
IS
(
"pause"
)
&&
!
IS
(
"seek"
)
)
)
return
ExecuteSyntaxError
(
"control"
,
pp_status
);
}
#undef IS
psz_control
=
ppsz_arg
[
i_index
];
if
(
i_index
+
1
<
i_arg
)
psz_argument
=
ppsz_arg
[
i_index
+
1
];
p_media
=
vlm_MediaSearch
(
p_vlm
,
psz_name
);
assert
(
p_media
);
if
(
!
strcmp
(
psz_control
,
"play"
)
)
{
int
i_input_index
=
0
;
int
i
;
if
(
(
psz_argument
&&
sscanf
(
psz_argument
,
"%d"
,
&
i
)
==
1
)
&&
i
>
0
&&
i
-
1
<
p_media
->
cfg
.
i_input
)
{
i_input_index
=
i
-
1
;
}
else
if
(
psz_argument
)
{
int
j
;
vlm_media_t
*
p_cfg
=
&
p_media
->
cfg
;
for
(
j
=
0
;
j
<
p_cfg
->
i_input
;
j
++
)
{
if
(
!
strcmp
(
p_cfg
->
ppsz_input
[
j
],
psz_argument
)
)
{
i_input_index
=
j
;
break
;
}
}
}
if
(
p_media
->
cfg
.
b_vod
)
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_START_MEDIA_VOD_INSTANCE
,
p_media
->
cfg
.
id
,
psz_instance
,
i_input_index
,
NULL
);
// we should get here now
else
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_START_MEDIA_BROADCAST_INSTANCE
,
p_media
->
cfg
.
id
,
psz_instance
,
i_input_index
);
}
else
if
(
!
strcmp
(
psz_control
,
"seek"
)
)
{
if
(
psz_argument
)
{
bool
b_relative
;
if
(
psz_argument
[
0
]
==
'+'
||
psz_argument
[
0
]
==
'-'
)
b_relative
=
true
;
else
b_relative
=
false
;
if
(
strstr
(
psz_argument
,
"ms"
)
||
strstr
(
psz_argument
,
"s"
)
)
{
/* Time (ms or s) */
int64_t
i_new_time
;
if
(
strstr
(
psz_argument
,
"ms"
)
)
i_new_time
=
1000
*
(
int64_t
)
atoi
(
psz_argument
);
else
i_new_time
=
1000000
*
(
int64_t
)
atoi
(
psz_argument
);
if
(
b_relative
)
{
int64_t
i_time
=
0
;
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_INSTANCE_TIME
,
p_media
->
cfg
.
id
,
psz_instance
,
&
i_time
);
i_new_time
+=
i_time
;
}
if
(
i_new_time
<
0
)
i_new_time
=
0
;
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_SET_MEDIA_INSTANCE_TIME
,
p_media
->
cfg
.
id
,
psz_instance
,
i_new_time
);
}
else
{
/* Percent */
double
d_new_position
=
i18n_atof
(
psz_argument
)
/
100
.
0
;
if
(
b_relative
)
{
double
d_position
=
0
.
0
;
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
&
d_position
);
d_new_position
+=
d_position
;
}
if
(
d_new_position
<
0
.
0
)
d_new_position
=
0
.
0
;
else
if
(
d_new_position
>
1
.
0
)
d_new_position
=
1
.
0
;
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_SET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
d_new_position
);
}
}
else
{
i_result
=
VLC_EGENERIC
;
}
}
else
if
(
!
strcmp
(
psz_control
,
"rewind"
)
)
{
if
(
psz_argument
)
{
const
double
d_scale
=
i18n_atof
(
psz_argument
);
double
d_position
;
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
&
d_position
);
d_position
-=
(
d_scale
/
1000
.
0
);
if
(
d_position
<
0
.
0
)
d_position
=
0
.
0
;
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_SET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
d_position
);
}
else
{
i_result
=
VLC_EGENERIC
;
}
}
else
if
(
!
strcmp
(
psz_control
,
"forward"
)
)
{
if
(
psz_argument
)
{
const
double
d_scale
=
i18n_atof
(
psz_argument
);
double
d_position
;
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
&
d_position
);
d_position
+=
(
d_scale
/
1000
.
0
);
if
(
d_position
>
1
.
0
)
d_position
=
1
.
0
;
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_SET_MEDIA_INSTANCE_POSITION
,
p_media
->
cfg
.
id
,
psz_instance
,
d_position
);
}
else
{
i_result
=
VLC_EGENERIC
;
}
}
else
if
(
!
strcmp
(
psz_control
,
"stop"
)
)
{
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_STOP_MEDIA_INSTANCE
,
p_media
->
cfg
.
id
,
psz_instance
);
}
else
if
(
!
strcmp
(
psz_control
,
"pause"
)
)
{
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_PAUSE_MEDIA_INSTANCE
,
p_media
->
cfg
.
id
,
psz_instance
);
}
else
{
i_result
=
VLC_EGENERIC
;
}
if
(
i_result
)
{
*
pp_status
=
vlm_MessageNew
(
"control"
,
"unknown error"
);
return
VLC_SUCCESS
;
}
*
pp_status
=
vlm_MessageNew
(
"control"
,
vlm_NULL
);
return
VLC_SUCCESS
;
}
static
int
ExecuteExport
(
vlm_t
*
p_vlm
,
vlm_message_t
**
pp_status
)
{
char
*
psz_export
=
Save
(
p_vlm
);
*
pp_status
=
vlm_MessageNew
(
"export"
,
psz_export
);
free
(
psz_export
);
return
VLC_SUCCESS
;
}
static
int
ExecuteSave
(
vlm_t
*
p_vlm
,
const
char
*
psz_file
,
vlm_message_t
**
pp_status
)
{
FILE
*
f
=
utf8_fopen
(
psz_file
,
"wt"
);
char
*
psz_save
=
NULL
;
if
(
!
f
)
goto
error
;
psz_save
=
Save
(
p_vlm
);
if
(
psz_save
==
NULL
)
goto
error
;
if
(
fputs
(
psz_save
,
f
)
==
EOF
)
goto
error
;;
if
(
fclose
(
f
)
)
{
f
=
NULL
;
goto
error
;
}
free
(
psz_save
);
*
pp_status
=
vlm_MessageNew
(
"save"
,
vlm_NULL
);
return
VLC_SUCCESS
;
error:
free
(
psz_save
);
if
(
f
)
fclose
(
f
);
*
pp_status
=
vlm_MessageNew
(
"save"
,
"Unable to save to file"
);
return
VLC_EGENERIC
;
}
static
int
ExecuteLoad
(
vlm_t
*
p_vlm
,
const
char
*
psz_url
,
vlm_message_t
**
pp_status
)
{
stream_t
*
p_stream
=
stream_UrlNew
(
p_vlm
,
psz_url
);
int64_t
i_size
;
char
*
psz_buffer
;
if
(
!
p_stream
)
{
*
pp_status
=
vlm_MessageNew
(
"load"
,
"Unable to load from file"
);
return
VLC_EGENERIC
;
}
/* FIXME needed ? */
if
(
stream_Seek
(
p_stream
,
0
)
!=
0
)
{
stream_Delete
(
p_stream
);
*
pp_status
=
vlm_MessageNew
(
"load"
,
"Read file error"
);
return
VLC_EGENERIC
;
}
i_size
=
stream_Size
(
p_stream
);
psz_buffer
=
malloc
(
i_size
+
1
);
if
(
!
psz_buffer
)
{
stream_Delete
(
p_stream
);
*
pp_status
=
vlm_MessageNew
(
"load"
,
"Read file error"
);
return
VLC_EGENERIC
;
}
stream_Read
(
p_stream
,
psz_buffer
,
i_size
);
psz_buffer
[
i_size
]
=
'\0'
;
stream_Delete
(
p_stream
);
if
(
Load
(
p_vlm
,
psz_buffer
)
)
{
free
(
psz_buffer
);
*
pp_status
=
vlm_MessageNew
(
"load"
,
"Error while loading file"
);
return
VLC_EGENERIC
;
}
free
(
psz_buffer
);
*
pp_status
=
vlm_MessageNew
(
"load"
,
vlm_NULL
);
return
VLC_SUCCESS
;
}
static
int
ExecuteScheduleProperty
(
vlm_t
*
p_vlm
,
vlm_schedule_sys_t
*
p_schedule
,
bool
b_new
,
const
int
i_property
,
char
*
ppsz_property
[],
vlm_message_t
**
pp_status
)
{
const
char
*
psz_cmd
=
b_new
?
"new"
:
"setup"
;
int
i
;
for
(
i
=
0
;
i
<
i_property
;
i
++
)
{
if
(
!
strcmp
(
ppsz_property
[
i
],
"enabled"
)
||
!
strcmp
(
ppsz_property
[
i
],
"disabled"
)
)
{
vlm_ScheduleSetup
(
p_schedule
,
ppsz_property
[
i
],
NULL
);
}
else
if
(
!
strcmp
(
ppsz_property
[
i
],
"append"
)
)
{
char
*
psz_line
;
int
j
;
/* Beware: everything behind append is considered as
* command line */
if
(
++
i
>=
i_property
)
break
;
psz_line
=
strdup
(
ppsz_property
[
i
]
);
for
(
j
=
i
+
1
;
j
<
i_property
;
j
++
)
{
psz_line
=
realloc
(
psz_line
,
strlen
(
psz_line
)
+
strlen
(
ppsz_property
[
j
])
+
1
+
1
);
strcat
(
psz_line
,
" "
);
strcat
(
psz_line
,
ppsz_property
[
j
]
);
}
vlm_ScheduleSetup
(
p_schedule
,
"append"
,
psz_line
);
break
;
}
else
{
if
(
i
+
1
>=
i_property
)
{
if
(
b_new
)
vlm_ScheduleDelete
(
p_vlm
,
p_schedule
);
return
ExecuteSyntaxError
(
psz_cmd
,
pp_status
);
}
vlm_ScheduleSetup
(
p_schedule
,
ppsz_property
[
i
],
ppsz_property
[
i
+
1
]
);
i
++
;
}
}
*
pp_status
=
vlm_MessageNew
(
psz_cmd
,
vlm_NULL
);
return
VLC_SUCCESS
;
}
static
int
ExecuteMediaProperty
(
vlm_t
*
p_vlm
,
int64_t
id
,
bool
b_new
,
const
int
i_property
,
char
*
ppsz_property
[],
vlm_message_t
**
pp_status
)
{
const
char
*
psz_cmd
=
b_new
?
"new"
:
"setup"
;
vlm_media_t
*
p_cfg
=
NULL
;
int
i_result
;
int
i
;
#undef ERROR
#undef MISSING
#define ERROR( txt ) do { *pp_status = vlm_MessageNew( psz_cmd, txt); goto error; } while(0)
if
(
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA
,
id
,
&
p_cfg
)
)
ERROR
(
"unknown media"
);
#define MISSING(cmd) do { if( !psz_value ) ERROR( "missing argument for " cmd ); } while(0)
for
(
i
=
0
;
i
<
i_property
;
i
++
)
{
const
char
*
psz_option
=
ppsz_property
[
i
];
const
char
*
psz_value
=
i
+
1
<
i_property
?
ppsz_property
[
i
+
1
]
:
NULL
;
if
(
!
strcmp
(
psz_option
,
"enabled"
)
)
{
p_cfg
->
b_enabled
=
true
;
}
else
if
(
!
strcmp
(
psz_option
,
"disabled"
)
)
{
p_cfg
->
b_enabled
=
false
;
}
else
if
(
!
strcmp
(
psz_option
,
"input"
)
)
{
MISSING
(
"input"
);
TAB_APPEND
(
p_cfg
->
i_input
,
p_cfg
->
ppsz_input
,
strdup
(
psz_value
)
);
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"inputdel"
)
&&
psz_value
&&
!
strcmp
(
psz_value
,
"all"
)
)
{
while
(
p_cfg
->
i_input
>
0
)
TAB_REMOVE
(
p_cfg
->
i_input
,
p_cfg
->
ppsz_input
,
p_cfg
->
ppsz_input
[
0
]
);
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"inputdel"
)
)
{
int
j
;
MISSING
(
"inputdel"
);
for
(
j
=
0
;
j
<
p_cfg
->
i_input
;
j
++
)
{
if
(
!
strcmp
(
p_cfg
->
ppsz_input
[
j
],
psz_value
)
)
{
TAB_REMOVE
(
p_cfg
->
i_input
,
p_cfg
->
ppsz_input
,
p_cfg
->
ppsz_input
[
j
]
);
break
;
}
}
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"inputdeln"
)
)
{
int
i_index
;
MISSING
(
"inputdeln"
);
i_index
=
atoi
(
psz_value
);
if
(
i_index
>
0
&&
i_index
<=
p_cfg
->
i_input
)
TAB_REMOVE
(
p_cfg
->
i_input
,
p_cfg
->
ppsz_input
,
p_cfg
->
ppsz_input
[
i_index
-
1
]
);
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"output"
)
)
{
MISSING
(
"output"
);
free
(
p_cfg
->
psz_output
);
p_cfg
->
psz_output
=
*
psz_value
?
strdup
(
psz_value
)
:
NULL
;
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"option"
)
)
{
MISSING
(
"option"
);
TAB_APPEND
(
p_cfg
->
i_option
,
p_cfg
->
ppsz_option
,
strdup
(
psz_value
)
);
i
++
;
}
else
if
(
!
strcmp
(
psz_option
,
"loop"
)
)
{
if
(
p_cfg
->
b_vod
)
ERROR
(
"invalid loop option for vod"
);
p_cfg
->
broadcast
.
b_loop
=
true
;
}
else
if
(
!
strcmp
(
psz_option
,
"unloop"
)
)
{
if
(
p_cfg
->
b_vod
)
ERROR
(
"invalid unloop option for vod"
);
p_cfg
->
broadcast
.
b_loop
=
false
;
}
else
if
(
!
strcmp
(
psz_option
,
"mux"
)
)
{
MISSING
(
"mux"
);
if
(
!
p_cfg
->
b_vod
)
ERROR
(
"invalid mux option for broadcast"
);
free
(
p_cfg
->
vod
.
psz_mux
);
p_cfg
->
vod
.
psz_mux
=
*
psz_value
?
strdup
(
psz_value
)
:
NULL
;
i
++
;
}
else
{
fprintf
(
stderr
,
"PROP: name=%s unknown
\n
"
,
psz_option
);
ERROR
(
"Wrong command syntax"
);
}
}
#undef MISSING
#undef ERROR
/* */
i_result
=
vlm_ControlInternal
(
p_vlm
,
VLM_CHANGE_MEDIA
,
p_cfg
);
vlm_media_Delete
(
p_cfg
);
*
pp_status
=
vlm_MessageNew
(
psz_cmd
,
vlm_NULL
);
return
i_result
;
error:
if
(
p_cfg
)
{
if
(
b_new
)
vlm_ControlInternal
(
p_vlm
,
VLM_DEL_MEDIA
,
p_cfg
->
id
);
vlm_media_Delete
(
p_cfg
);
}
return
VLC_EGENERIC
;
}
static
int
ExecuteNew
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
,
const
char
*
psz_type
,
const
int
i_property
,
char
*
ppsz_property
[],
vlm_message_t
**
pp_status
)
{
/* Check name */
if
(
!
strcmp
(
psz_name
,
"all"
)
||
!
strcmp
(
psz_name
,
"media"
)
||
!
strcmp
(
psz_name
,
"schedule"
)
)
{
*
pp_status
=
vlm_MessageNew
(
"new"
,
"
\"
all
\"
,
\"
media
\"
and
\"
schedule
\"
are reserved names"
);
return
VLC_EGENERIC
;
}
if
(
ExecuteIsMedia
(
p_vlm
,
psz_name
)
||
ExecuteIsSchedule
(
p_vlm
,
psz_name
)
)
{
*
pp_status
=
vlm_MessageNew
(
"new"
,
"%s: Name already in use"
,
psz_name
);
return
VLC_EGENERIC
;
}
/* */
if
(
!
strcmp
(
psz_type
,
"schedule"
)
)
{
vlm_schedule_sys_t
*
p_schedule
=
vlm_ScheduleNew
(
p_vlm
,
psz_name
);
if
(
!
p_schedule
)
{
*
pp_status
=
vlm_MessageNew
(
"new"
,
"could not create schedule"
);
return
VLC_EGENERIC
;
}
return
ExecuteScheduleProperty
(
p_vlm
,
p_schedule
,
true
,
i_property
,
ppsz_property
,
pp_status
);
}
else
if
(
!
strcmp
(
psz_type
,
"vod"
)
||
!
strcmp
(
psz_type
,
"broadcast"
)
)
{
vlm_media_t
cfg
;
int64_t
id
;
vlm_media_Init
(
&
cfg
);
cfg
.
psz_name
=
strdup
(
psz_name
);
cfg
.
b_vod
=
!
strcmp
(
psz_type
,
"vod"
);
if
(
vlm_ControlInternal
(
p_vlm
,
VLM_ADD_MEDIA
,
&
cfg
,
&
id
)
)
{
vlm_media_Clean
(
&
cfg
);
*
pp_status
=
vlm_MessageNew
(
"new"
,
"could not create media"
);
return
VLC_EGENERIC
;
}
vlm_media_Clean
(
&
cfg
);
return
ExecuteMediaProperty
(
p_vlm
,
id
,
true
,
i_property
,
ppsz_property
,
pp_status
);
}
else
{
*
pp_status
=
vlm_MessageNew
(
"new"
,
"%s: Choose between vod, broadcast or schedule"
,
psz_type
);
return
VLC_EGENERIC
;
}
}
static
int
ExecuteSetup
(
vlm_t
*
p_vlm
,
const
char
*
psz_name
,
const
int
i_property
,
char
*
ppsz_property
[],
vlm_message_t
**
pp_status
)
{
if
(
ExecuteIsSchedule
(
p_vlm
,
psz_name
)
)
{
vlm_schedule_sys_t
*
p_schedule
=
vlm_ScheduleSearch
(
p_vlm
,
psz_name
);
return
ExecuteScheduleProperty
(
p_vlm
,
p_schedule
,
false
,
i_property
,
ppsz_property
,
pp_status
);
}
else
if
(
ExecuteIsMedia
(
p_vlm
,
psz_name
)
)
{
int64_t
id
;
if
(
vlm_ControlInternal
(
p_vlm
,
VLM_GET_MEDIA_ID
,
psz_name
,
&
id
)
)
goto
error
;
return
ExecuteMediaProperty
(
p_vlm
,
id
,
false
,
i_property
,
ppsz_property
,
pp_status
);
}
error:
*
pp_status
=
vlm_MessageNew
(
"setup"
,
"%s unknown"
,
psz_name
);
return
VLC_EGENERIC
;
}
int
ExecuteCommand
(
vlm_t
*
p_vlm
,
const
char
*
psz_command
,
vlm_message_t
**
pp_message
)
{
size_t
i_command
=
0
;
char
buf
[
strlen
(
psz_command
)
+
1
],
*
psz_buf
=
buf
;
char
*
ppsz_command
[
3
+
sizeof
(
buf
)
/
2
];
vlm_message_t
*
p_message
=
NULL
;
/* First, parse the line and cut it */
while
(
*
psz_command
!=
'\0'
)
{
const
char
*
psz_temp
;
if
(
isspace
(
*
psz_command
))
{
psz_command
++
;
continue
;
}
/* support for comments */
if
(
i_command
==
0
&&
*
psz_command
==
'#'
)
{
p_message
=
vlm_MessageNew
(
""
,
vlm_NULL
);
goto
success
;
}
psz_temp
=
FindCommandEnd
(
psz_command
);
if
(
psz_temp
==
NULL
)
{
p_message
=
vlm_MessageNew
(
"Incomplete command"
,
psz_command
);
goto
error
;
}
assert
(
i_command
<
(
sizeof
(
ppsz_command
)
/
sizeof
(
ppsz_command
[
0
])));
ppsz_command
[
i_command
]
=
psz_buf
;
memcpy
(
psz_buf
,
psz_command
,
psz_temp
-
psz_command
);
psz_buf
[
psz_temp
-
psz_command
]
=
'\0'
;
Unescape
(
psz_buf
,
psz_buf
);
i_command
++
;
psz_buf
+=
psz_temp
-
psz_command
+
1
;
psz_command
=
psz_temp
;
assert
(
buf
+
sizeof
(
buf
)
>=
psz_buf
);
}
/*
* And then Interpret it
*/
#define IF_EXECUTE( name, check, cmd ) if( !strcmp(ppsz_command[0], name ) ) { if( (check) ) goto syntax_error; if( (cmd) ) goto error; goto success; }
if
(
i_command
==
0
)
{
p_message
=
vlm_MessageNew
(
""
,
vlm_NULL
);
goto
success
;
}
else
IF_EXECUTE
(
"del"
,
(
i_command
!=
2
),
ExecuteDel
(
p_vlm
,
ppsz_command
[
1
],
&
p_message
)
)
else
IF_EXECUTE
(
"show"
,
(
i_command
>
2
),
ExecuteShow
(
p_vlm
,
i_command
>
1
?
ppsz_command
[
1
]
:
NULL
,
&
p_message
)
)
else
IF_EXECUTE
(
"help"
,
(
i_command
!=
1
),
ExecuteHelp
(
&
p_message
)
)
else
IF_EXECUTE
(
"control"
,
(
i_command
<
3
),
ExecuteControl
(
p_vlm
,
ppsz_command
[
1
],
i_command
-
2
,
&
ppsz_command
[
2
],
&
p_message
)
)
else
IF_EXECUTE
(
"save"
,
(
i_command
!=
2
),
ExecuteSave
(
p_vlm
,
ppsz_command
[
1
],
&
p_message
)
)
else
IF_EXECUTE
(
"export"
,
(
i_command
!=
1
),
ExecuteExport
(
p_vlm
,
&
p_message
)
)
else
IF_EXECUTE
(
"load"
,
(
i_command
!=
2
),
ExecuteLoad
(
p_vlm
,
ppsz_command
[
1
],
&
p_message
)
)
else
IF_EXECUTE
(
"new"
,
(
i_command
<
3
),
ExecuteNew
(
p_vlm
,
ppsz_command
[
1
],
ppsz_command
[
2
],
i_command
-
3
,
&
ppsz_command
[
3
],
&
p_message
)
)
else
IF_EXECUTE
(
"setup"
,
(
i_command
<
2
),
ExecuteSetup
(
p_vlm
,
ppsz_command
[
1
],
i_command
-
2
,
&
ppsz_command
[
2
],
&
p_message
)
)
else
{
p_message
=
vlm_MessageNew
(
ppsz_command
[
0
],
"Unknown command"
);
goto
error
;
}
#undef IF_EXECUTE
success:
*
pp_message
=
p_message
;
return
VLC_SUCCESS
;
syntax_error:
return
ExecuteSyntaxError
(
ppsz_command
[
0
],
pp_message
);
error:
*
pp_message
=
p_message
;
return
VLC_EGENERIC
;
}
/*****************************************************************************
* Media handling
*****************************************************************************/
vlm_media_sys_t
*
vlm_MediaSearch
(
vlm_t
*
vlm
,
const
char
*
psz_name
)
{
int
i
;
for
(
i
=
0
;
i
<
vlm
->
i_media
;
i
++
)
{
if
(
strcmp
(
psz_name
,
vlm
->
media
[
i
]
->
cfg
.
psz_name
)
==
0
)
return
vlm
->
media
[
i
];
}
return
NULL
;
}
/*****************************************************************************
* Schedule handling
*****************************************************************************/
static
vlm_schedule_sys_t
*
vlm_ScheduleNew
(
vlm_t
*
vlm
,
const
char
*
psz_name
)
{
vlm_schedule_sys_t
*
p_sched
=
malloc
(
sizeof
(
vlm_schedule_sys_t
)
);
if
(
!
p_sched
)
{
return
NULL
;
}
if
(
!
psz_name
)
{
return
NULL
;
}
p_sched
->
psz_name
=
strdup
(
psz_name
);
p_sched
->
b_enabled
=
false
;
p_sched
->
i_command
=
0
;
p_sched
->
command
=
NULL
;
p_sched
->
i_date
=
0
;
p_sched
->
i_period
=
0
;
p_sched
->
i_repeat
=
-
1
;
TAB_APPEND
(
vlm
->
i_schedule
,
vlm
->
schedule
,
p_sched
);
return
p_sched
;
}
/* for now, simple delete. After, del with options (last arg) */
void
vlm_ScheduleDelete
(
vlm_t
*
vlm
,
vlm_schedule_sys_t
*
sched
)
{
if
(
sched
==
NULL
)
return
;
TAB_REMOVE
(
vlm
->
i_schedule
,
vlm
->
schedule
,
sched
);
if
(
vlm
->
i_schedule
==
0
)
free
(
vlm
->
schedule
);
free
(
sched
->
psz_name
);
while
(
sched
->
i_command
)
{
char
*
psz_cmd
=
sched
->
command
[
0
];
TAB_REMOVE
(
sched
->
i_command
,
sched
->
command
,
psz_cmd
);
free
(
psz_cmd
);
}
free
(
sched
);
}
static
vlm_schedule_sys_t
*
vlm_ScheduleSearch
(
vlm_t
*
vlm
,
const
char
*
psz_name
)
{
int
i
;
for
(
i
=
0
;
i
<
vlm
->
i_schedule
;
i
++
)
{
if
(
strcmp
(
psz_name
,
vlm
->
schedule
[
i
]
->
psz_name
)
==
0
)
{
return
vlm
->
schedule
[
i
];
}
}
return
NULL
;
}
/* Ok, setup schedule command will be able to support only one (argument value) at a time */
static
int
vlm_ScheduleSetup
(
vlm_schedule_sys_t
*
schedule
,
const
char
*
psz_cmd
,
const
char
*
psz_value
)
{
if
(
!
strcmp
(
psz_cmd
,
"enabled"
)
)
{
schedule
->
b_enabled
=
true
;
}
else
if
(
!
strcmp
(
psz_cmd
,
"disabled"
)
)
{
schedule
->
b_enabled
=
false
;
}
else
if
(
!
strcmp
(
psz_cmd
,
"date"
)
)
{
struct
tm
time
;
const
char
*
p
;
time_t
date
;
time
.
tm_sec
=
0
;
/* seconds */
time
.
tm_min
=
0
;
/* minutes */
time
.
tm_hour
=
0
;
/* hours */
time
.
tm_mday
=
0
;
/* day of the month */
time
.
tm_mon
=
0
;
/* month */
time
.
tm_year
=
0
;
/* year */
time
.
tm_wday
=
0
;
/* day of the week */
time
.
tm_yday
=
0
;
/* day in the year */
time
.
tm_isdst
=
-
1
;
/* daylight saving time */
/* date should be year/month/day-hour:minutes:seconds */
p
=
strchr
(
psz_value
,
'-'
);
if
(
!
strcmp
(
psz_value
,
"now"
)
)
{
schedule
->
i_date
=
0
;
}
else
if
(
(
p
==
NULL
)
&&
sscanf
(
psz_value
,
"%d:%d:%d"
,
&
time
.
tm_hour
,
&
time
.
tm_min
,
&
time
.
tm_sec
)
!=
3
)
/* it must be a hour:minutes:seconds */
{
return
1
;
}
else
{
unsigned
i
,
j
,
k
;
switch
(
sscanf
(
p
+
1
,
"%u:%u:%u"
,
&
i
,
&
j
,
&
k
)
)
{
case
1
:
time
.
tm_sec
=
i
;
break
;
case
2
:
time
.
tm_min
=
i
;
time
.
tm_sec
=
j
;
break
;
case
3
:
time
.
tm_hour
=
i
;
time
.
tm_min
=
j
;
time
.
tm_sec
=
k
;
break
;
default:
return
1
;
}
switch
(
sscanf
(
psz_value
,
"%d/%d/%d"
,
&
i
,
&
j
,
&
k
)
)
{
case
1
:
time
.
tm_mday
=
i
;
break
;
case
2
:
time
.
tm_mon
=
i
-
1
;
time
.
tm_mday
=
j
;
break
;
case
3
:
time
.
tm_year
=
i
-
1900
;
time
.
tm_mon
=
j
-
1
;
time
.
tm_mday
=
k
;
break
;
default:
return
1
;
}
date
=
mktime
(
&
time
);
schedule
->
i_date
=
((
mtime_t
)
date
)
*
1000000
;
}
}
else
if
(
!
strcmp
(
psz_cmd
,
"period"
)
)
{
struct
tm
time
;
const
char
*
p
;
const
char
*
psz_time
=
NULL
,
*
psz_date
=
NULL
;
time_t
date
;
unsigned
i
,
j
,
k
;
/* First, if date or period are modified, repeat should be equal to -1 */
schedule
->
i_repeat
=
-
1
;
time
.
tm_sec
=
0
;
/* seconds */
time
.
tm_min
=
0
;
/* minutes */
time
.
tm_hour
=
0
;
/* hours */
time
.
tm_mday
=
0
;
/* day of the month */
time
.
tm_mon
=
0
;
/* month */
time
.
tm_year
=
0
;
/* year */
time
.
tm_wday
=
0
;
/* day of the week */
time
.
tm_yday
=
0
;
/* day in the year */
time
.
tm_isdst
=
-
1
;
/* daylight saving time */
/* date should be year/month/day-hour:minutes:seconds */
p
=
strchr
(
psz_value
,
'-'
);
if
(
p
)
{
psz_date
=
psz_value
;
psz_time
=
p
+
1
;
}
else
{
psz_time
=
psz_value
;
}
switch
(
sscanf
(
psz_time
,
"%u:%u:%u"
,
&
i
,
&
j
,
&
k
)
)
{
case
1
:
time
.
tm_sec
=
i
;
break
;
case
2
:
time
.
tm_min
=
i
;
time
.
tm_sec
=
j
;
break
;
case
3
:
time
.
tm_hour
=
i
;
time
.
tm_min
=
j
;
time
.
tm_sec
=
k
;
break
;
default:
return
1
;
}
if
(
psz_date
)
{
switch
(
sscanf
(
psz_date
,
"%u/%u/%u"
,
&
i
,
&
j
,
&
k
)
)
{
case
1
:
time
.
tm_mday
=
i
;
break
;
case
2
:
time
.
tm_mon
=
i
;
time
.
tm_mday
=
j
;
break
;
case
3
:
time
.
tm_year
=
i
;
time
.
tm_mon
=
j
;
time
.
tm_mday
=
k
;
break
;
default:
return
1
;
}
}
/* ok, that's stupid... who is going to schedule streams every 42 years ? */
date
=
((((
time
.
tm_year
*
12
+
time
.
tm_mon
)
*
30
+
time
.
tm_mday
)
*
24
+
time
.
tm_hour
)
*
60
+
time
.
tm_min
)
*
60
+
time
.
tm_sec
;
schedule
->
i_period
=
((
mtime_t
)
date
)
*
1000000
;
}
else
if
(
!
strcmp
(
psz_cmd
,
"repeat"
)
)
{
int
i
;
if
(
sscanf
(
psz_value
,
"%d"
,
&
i
)
==
1
)
{
schedule
->
i_repeat
=
i
;
}
else
{
return
1
;
}
}
else
if
(
!
strcmp
(
psz_cmd
,
"append"
)
)
{
char
*
command
=
strdup
(
psz_value
);
TAB_APPEND
(
schedule
->
i_command
,
schedule
->
command
,
command
);
}
else
{
return
1
;
}
return
0
;
}
/*****************************************************************************
* Message handling functions
*****************************************************************************/
vlm_message_t
*
vlm_MessageNew
(
const
char
*
psz_name
,
const
char
*
psz_format
,
...
)
{
vlm_message_t
*
p_message
;
va_list
args
;
if
(
!
psz_name
)
return
NULL
;
p_message
=
malloc
(
sizeof
(
vlm_message_t
)
);
if
(
!
p_message
)
{
return
NULL
;
}
p_message
->
psz_value
=
0
;
if
(
psz_format
)
{
va_start
(
args
,
psz_format
);
if
(
vasprintf
(
&
p_message
->
psz_value
,
psz_format
,
args
)
==
-
1
)
{
va_end
(
args
);
free
(
p_message
);
return
NULL
;
}
va_end
(
args
);
}
p_message
->
psz_name
=
strdup
(
psz_name
);
p_message
->
i_child
=
0
;
p_message
->
child
=
NULL
;
return
p_message
;
}
void
vlm_MessageDelete
(
vlm_message_t
*
p_message
)
{
free
(
p_message
->
psz_name
);
free
(
p_message
->
psz_value
);
while
(
p_message
->
i_child
--
)
vlm_MessageDelete
(
p_message
->
child
[
p_message
->
i_child
]
);
free
(
p_message
->
child
);
free
(
p_message
);
}
/* Add a child */
vlm_message_t
*
vlm_MessageAdd
(
vlm_message_t
*
p_message
,
vlm_message_t
*
p_child
)
{
if
(
p_message
==
NULL
)
return
NULL
;
if
(
p_child
)
{
TAB_APPEND
(
p_message
->
i_child
,
p_message
->
child
,
p_child
);
}
return
p_child
;
}
/*****************************************************************************
* Misc utility functions
*****************************************************************************/
static
vlm_message_t
*
vlm_ShowMedia
(
vlm_media_sys_t
*
p_media
)
{
vlm_media_t
*
p_cfg
=
&
p_media
->
cfg
;
vlm_message_t
*
p_msg
;
vlm_message_t
*
p_msg_sub
;
int
i
;
p_msg
=
vlm_MessageNew
(
p_cfg
->
psz_name
,
vlm_NULL
);
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"type"
,
p_cfg
->
b_vod
?
"vod"
:
"broadcast"
)
);
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"enabled"
,
p_cfg
->
b_enabled
?
"yes"
:
"no"
)
);
if
(
p_cfg
->
b_vod
)
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"mux"
,
p_cfg
->
vod
.
psz_mux
)
);
else
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"loop"
,
p_cfg
->
broadcast
.
b_loop
?
"yes"
:
"no"
)
);
p_msg_sub
=
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"inputs"
,
vlm_NULL
)
);
for
(
i
=
0
;
i
<
p_cfg
->
i_input
;
i
++
)
{
char
*
psz_tmp
;
if
(
asprintf
(
&
psz_tmp
,
"%d"
,
i
+
1
)
!=
-
1
)
{
vlm_MessageAdd
(
p_msg_sub
,
vlm_MessageNew
(
psz_tmp
,
p_cfg
->
ppsz_input
[
i
]
)
);
free
(
psz_tmp
);
}
}
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"output"
,
p_cfg
->
psz_output
?
p_cfg
->
psz_output
:
""
)
);
p_msg_sub
=
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"options"
,
vlm_NULL
)
);
for
(
i
=
0
;
i
<
p_cfg
->
i_option
;
i
++
)
vlm_MessageAdd
(
p_msg_sub
,
vlm_MessageNew
(
p_cfg
->
ppsz_option
[
i
],
vlm_NULL
)
);
p_msg_sub
=
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"instances"
,
vlm_NULL
)
);
for
(
i
=
0
;
i
<
p_media
->
i_instance
;
i
++
)
{
vlm_media_instance_sys_t
*
p_instance
=
p_media
->
instance
[
i
];
vlc_value_t
val
;
vlm_message_t
*
p_msg_instance
;
char
*
psz_tmp
;
val
.
i_int
=
END_S
;
if
(
p_instance
->
p_input
)
var_Get
(
p_instance
->
p_input
,
"state"
,
&
val
);
p_msg_instance
=
vlm_MessageAdd
(
p_msg_sub
,
vlm_MessageNew
(
"instance"
,
vlm_NULL
)
);
vlm_MessageAdd
(
p_msg_instance
,
vlm_MessageNew
(
"name"
,
p_instance
->
psz_name
?
p_instance
->
psz_name
:
"default"
)
);
vlm_MessageAdd
(
p_msg_instance
,
vlm_MessageNew
(
"state"
,
val
.
i_int
==
PLAYING_S
?
"playing"
:
val
.
i_int
==
PAUSE_S
?
"paused"
:
"stopped"
)
);
/* FIXME should not do that this way */
if
(
p_instance
->
p_input
)
{
#define APPEND_INPUT_INFO( a, format, type ) \
if( asprintf( &psz_tmp, format, \
var_Get ## type( p_instance->p_input, a ) ) != -1 ) \
{ \
vlm_MessageAdd( p_msg_instance, vlm_MessageNew( a, \
psz_tmp ) ); \
free( psz_tmp ); \
}
APPEND_INPUT_INFO
(
"position"
,
"%f"
,
Float
);
APPEND_INPUT_INFO
(
"time"
,
"%"
PRIi64
,
Time
);
APPEND_INPUT_INFO
(
"length"
,
"%"
PRIi64
,
Time
);
APPEND_INPUT_INFO
(
"rate"
,
"%d"
,
Integer
);
APPEND_INPUT_INFO
(
"title"
,
"%d"
,
Integer
);
APPEND_INPUT_INFO
(
"chapter"
,
"%d"
,
Integer
);
APPEND_INPUT_INFO
(
"seekable"
,
"%d"
,
Bool
);
}
#undef APPEND_INPUT_INFO
if
(
asprintf
(
&
psz_tmp
,
"%d"
,
p_instance
->
i_index
+
1
)
!=
-
1
)
{
vlm_MessageAdd
(
p_msg_instance
,
vlm_MessageNew
(
"playlistindex"
,
psz_tmp
)
);
free
(
psz_tmp
);
}
}
return
p_msg
;
}
static
vlm_message_t
*
vlm_Show
(
vlm_t
*
vlm
,
vlm_media_sys_t
*
media
,
vlm_schedule_sys_t
*
schedule
,
const
char
*
psz_filter
)
{
if
(
media
!=
NULL
)
{
vlm_message_t
*
p_msg
=
vlm_MessageNew
(
"show"
,
vlm_NULL
);
if
(
p_msg
)
vlm_MessageAdd
(
p_msg
,
vlm_ShowMedia
(
media
)
);
return
p_msg
;
}
else
if
(
schedule
!=
NULL
)
{
int
i
;
vlm_message_t
*
msg
;
vlm_message_t
*
msg_schedule
;
vlm_message_t
*
msg_child
;
char
buffer
[
100
];
msg
=
vlm_MessageNew
(
"show"
,
vlm_NULL
);
msg_schedule
=
vlm_MessageAdd
(
msg
,
vlm_MessageNew
(
schedule
->
psz_name
,
vlm_NULL
)
);
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"type"
,
"schedule"
)
);
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"enabled"
,
schedule
->
b_enabled
?
"yes"
:
"no"
)
);
if
(
schedule
->
i_date
!=
0
)
{
struct
tm
date
;
time_t
i_time
=
(
time_t
)(
schedule
->
i_date
/
1000000
);
char
*
psz_date
;
localtime_r
(
&
i_time
,
&
date
);
if
(
asprintf
(
&
psz_date
,
"%d/%d/%d-%d:%d:%d"
,
date
.
tm_year
+
1900
,
date
.
tm_mon
+
1
,
date
.
tm_mday
,
date
.
tm_hour
,
date
.
tm_min
,
date
.
tm_sec
)
!=
-
1
)
{
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"date"
,
psz_date
)
);
free
(
psz_date
);
}
}
else
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"date"
,
"now"
)
);
if
(
schedule
->
i_period
!=
0
)
{
time_t
i_time
=
(
time_t
)
(
schedule
->
i_period
/
1000000
);
struct
tm
date
;
date
.
tm_sec
=
(
int
)(
i_time
%
60
);
i_time
=
i_time
/
60
;
date
.
tm_min
=
(
int
)(
i_time
%
60
);
i_time
=
i_time
/
60
;
date
.
tm_hour
=
(
int
)(
i_time
%
24
);
i_time
=
i_time
/
24
;
date
.
tm_mday
=
(
int
)(
i_time
%
30
);
i_time
=
i_time
/
30
;
/* okay, okay, months are not always 30 days long */
date
.
tm_mon
=
(
int
)(
i_time
%
12
);
i_time
=
i_time
/
12
;
date
.
tm_year
=
(
int
)
i_time
;
sprintf
(
buffer
,
"%d/%d/%d-%d:%d:%d"
,
date
.
tm_year
,
date
.
tm_mon
,
date
.
tm_mday
,
date
.
tm_hour
,
date
.
tm_min
,
date
.
tm_sec
);
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"period"
,
buffer
)
);
}
else
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"period"
,
"0"
)
);
sprintf
(
buffer
,
"%d"
,
schedule
->
i_repeat
);
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"repeat"
,
buffer
)
);
msg_child
=
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"commands"
,
vlm_NULL
)
);
for
(
i
=
0
;
i
<
schedule
->
i_command
;
i
++
)
{
vlm_MessageAdd
(
msg_child
,
vlm_MessageNew
(
schedule
->
command
[
i
],
vlm_NULL
)
);
}
return
msg
;
}
else
if
(
psz_filter
&&
!
strcmp
(
psz_filter
,
"media"
)
)
{
vlm_message_t
*
p_msg
;
vlm_message_t
*
p_msg_child
;
int
i_vod
=
0
,
i_broadcast
=
0
;
int
i
;
char
*
psz_count
;
for
(
i
=
0
;
i
<
vlm
->
i_media
;
i
++
)
{
if
(
vlm
->
media
[
i
]
->
cfg
.
b_vod
)
i_vod
++
;
else
i_broadcast
++
;
}
if
(
asprintf
(
&
psz_count
,
"( %d broadcast - %d vod )"
,
i_broadcast
,
i_vod
)
==
-
1
)
return
NULL
;
p_msg
=
vlm_MessageNew
(
"show"
,
vlm_NULL
);
p_msg_child
=
vlm_MessageAdd
(
p_msg
,
vlm_MessageNew
(
"media"
,
psz_count
)
);
free
(
psz_count
);
for
(
i
=
0
;
i
<
vlm
->
i_media
;
i
++
)
vlm_MessageAdd
(
p_msg_child
,
vlm_ShowMedia
(
vlm
->
media
[
i
]
)
);
return
p_msg
;
}
else
if
(
psz_filter
&&
!
strcmp
(
psz_filter
,
"schedule"
)
)
{
int
i
;
vlm_message_t
*
msg
;
vlm_message_t
*
msg_child
;
msg
=
vlm_MessageNew
(
"show"
,
vlm_NULL
);
msg_child
=
vlm_MessageAdd
(
msg
,
vlm_MessageNew
(
"schedule"
,
vlm_NULL
)
);
for
(
i
=
0
;
i
<
vlm
->
i_schedule
;
i
++
)
{
vlm_schedule_sys_t
*
s
=
vlm
->
schedule
[
i
];
vlm_message_t
*
msg_schedule
;
mtime_t
i_time
,
i_next_date
;
msg_schedule
=
vlm_MessageAdd
(
msg_child
,
vlm_MessageNew
(
s
->
psz_name
,
vlm_NULL
)
);
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"enabled"
,
s
->
b_enabled
?
"yes"
:
"no"
)
);
/* calculate next date */
i_time
=
vlm_Date
();
i_next_date
=
s
->
i_date
;
if
(
s
->
i_period
!=
0
)
{
int
j
=
0
;
while
(
s
->
i_date
+
j
*
s
->
i_period
<=
i_time
&&
s
->
i_repeat
>
j
)
{
j
++
;
}
i_next_date
=
s
->
i_date
+
j
*
s
->
i_period
;
}
if
(
i_next_date
>
i_time
)
{
time_t
i_date
=
(
time_t
)
(
i_next_date
/
1000000
)
;
#if !defined( UNDER_CE )
#ifdef HAVE_CTIME_R
char
psz_date
[
500
];
ctime_r
(
&
i_date
,
psz_date
);
#else
char
*
psz_date
=
ctime
(
&
i_date
);
#endif
vlm_MessageAdd
(
msg_schedule
,
vlm_MessageNew
(
"next launch"
,
psz_date
)
);
#endif
}
}
return
msg
;
}
else
if
(
(
psz_filter
==
NULL
)
&&
(
media
==
NULL
)
&&
(
schedule
==
NULL
)
)
{
vlm_message_t
*
show1
=
vlm_Show
(
vlm
,
NULL
,
NULL
,
"media"
);
vlm_message_t
*
show2
=
vlm_Show
(
vlm
,
NULL
,
NULL
,
"schedule"
);
vlm_MessageAdd
(
show1
,
show2
->
child
[
0
]
);
/* We must destroy the parent node "show" of show2
* and not the children */
free
(
show2
->
psz_name
);
free
(
show2
);
return
show1
;
}
else
{
return
vlm_MessageNew
(
"show"
,
vlm_NULL
);
}
}
/*****************************************************************************
* Config handling functions
*****************************************************************************/
static
int
Load
(
vlm_t
*
vlm
,
char
*
file
)
{
char
*
pf
=
file
;
int
i_line
=
1
;
while
(
*
pf
!=
'\0'
)
{
vlm_message_t
*
message
=
NULL
;
int
i_end
=
0
;
while
(
pf
[
i_end
]
!=
'\n'
&&
pf
[
i_end
]
!=
'\0'
&&
pf
[
i_end
]
!=
'\r'
)
{
i_end
++
;
}
if
(
pf
[
i_end
]
==
'\r'
||
pf
[
i_end
]
==
'\n'
)
{
pf
[
i_end
]
=
'\0'
;
i_end
++
;
if
(
pf
[
i_end
]
==
'\n'
)
i_end
++
;
}
if
(
*
pf
&&
ExecuteCommand
(
vlm
,
pf
,
&
message
)
)
{
if
(
message
)
{
if
(
message
->
psz_value
)
msg_Err
(
vlm
,
"Load error on line %d: %s: %s"
,
i_line
,
message
->
psz_name
,
message
->
psz_value
);
vlm_MessageDelete
(
message
);
}
return
1
;
}
if
(
message
)
vlm_MessageDelete
(
message
);
pf
+=
i_end
;
i_line
++
;
}
return
0
;
}
static
char
*
Save
(
vlm_t
*
vlm
)
{
char
*
save
=
NULL
;
char
psz_header
[]
=
"
\n
"
"# VLC media player VLM command batch
\n
"
"# http://www.videolan.org/vlc/
\n\n
"
;
char
*
p
;
int
i
,
j
;
int
i_length
=
strlen
(
psz_header
);
for
(
i
=
0
;
i
<
vlm
->
i_media
;
i
++
)
{
vlm_media_sys_t
*
media
=
vlm
->
media
[
i
];
vlm_media_t
*
p_cfg
=
&
media
->
cfg
;
if
(
p_cfg
->
b_vod
)
i_length
+=
strlen
(
"new * vod "
)
+
strlen
(
p_cfg
->
psz_name
);
else
i_length
+=
strlen
(
"new * broadcast "
)
+
strlen
(
p_cfg
->
psz_name
);
if
(
p_cfg
->
b_enabled
==
true
)
i_length
+=
strlen
(
"enabled"
);
else
i_length
+=
strlen
(
"disabled"
);
if
(
!
p_cfg
->
b_vod
&&
p_cfg
->
broadcast
.
b_loop
==
true
)
i_length
+=
strlen
(
" loop
\n
"
);
else
i_length
+=
strlen
(
"
\n
"
);
for
(
j
=
0
;
j
<
p_cfg
->
i_input
;
j
++
)
i_length
+=
strlen
(
"setup * input
\"\"\n
"
)
+
strlen
(
p_cfg
->
psz_name
)
+
strlen
(
p_cfg
->
ppsz_input
[
j
]
);
if
(
p_cfg
->
psz_output
!=
NULL
)
i_length
+=
strlen
(
"setup * output
\n
"
)
+
strlen
(
p_cfg
->
psz_name
)
+
strlen
(
p_cfg
->
psz_output
);
for
(
j
=
0
;
j
<
p_cfg
->
i_option
;
j
++
)
i_length
+=
strlen
(
"setup * option
\n
"
)
+
strlen
(
p_cfg
->
psz_name
)
+
strlen
(
p_cfg
->
ppsz_option
[
j
]);
if
(
p_cfg
->
b_vod
&&
p_cfg
->
vod
.
psz_mux
)
i_length
+=
strlen
(
"setup * mux
\n
"
)
+
strlen
(
p_cfg
->
psz_name
)
+
strlen
(
p_cfg
->
vod
.
psz_mux
);
}
for
(
i
=
0
;
i
<
vlm
->
i_schedule
;
i
++
)
{
vlm_schedule_sys_t
*
schedule
=
vlm
->
schedule
[
i
];
i_length
+=
strlen
(
"new schedule "
)
+
strlen
(
schedule
->
psz_name
);
if
(
schedule
->
b_enabled
==
true
)
{
i_length
+=
strlen
(
"date //-:: enabled
\n
"
)
+
14
;
}
else
{
i_length
+=
strlen
(
"date //-:: disabled
\n
"
)
+
14
;
}
if
(
schedule
->
i_period
!=
0
)
{
i_length
+=
strlen
(
"setup "
)
+
strlen
(
schedule
->
psz_name
)
+
strlen
(
"period //-::
\n
"
)
+
14
;
}
if
(
schedule
->
i_repeat
>=
0
)
{
char
buffer
[
12
];
sprintf
(
buffer
,
"%d"
,
schedule
->
i_repeat
);
i_length
+=
strlen
(
"setup repeat
\n
"
)
+
strlen
(
schedule
->
psz_name
)
+
strlen
(
buffer
);
}
else
{
i_length
++
;
}
for
(
j
=
0
;
j
<
schedule
->
i_command
;
j
++
)
{
i_length
+=
strlen
(
"setup append
\n
"
)
+
strlen
(
schedule
->
psz_name
)
+
strlen
(
schedule
->
command
[
j
]
);
}
}
/* Don't forget the '\0' */
i_length
++
;
/* now we have the length of save */
p
=
save
=
malloc
(
i_length
);
if
(
!
save
)
return
NULL
;
*
save
=
'\0'
;
p
+=
sprintf
(
p
,
"%s"
,
psz_header
);
/* finally we can write in it */
for
(
i
=
0
;
i
<
vlm
->
i_media
;
i
++
)
{
vlm_media_sys_t
*
media
=
vlm
->
media
[
i
];
vlm_media_t
*
p_cfg
=
&
media
->
cfg
;
if
(
p_cfg
->
b_vod
)
p
+=
sprintf
(
p
,
"new %s vod "
,
p_cfg
->
psz_name
);
else
p
+=
sprintf
(
p
,
"new %s broadcast "
,
p_cfg
->
psz_name
);
if
(
p_cfg
->
b_enabled
)
p
+=
sprintf
(
p
,
"enabled"
);
else
p
+=
sprintf
(
p
,
"disabled"
);
if
(
!
p_cfg
->
b_vod
&&
p_cfg
->
broadcast
.
b_loop
)
p
+=
sprintf
(
p
,
" loop
\n
"
);
else
p
+=
sprintf
(
p
,
"
\n
"
);
for
(
j
=
0
;
j
<
p_cfg
->
i_input
;
j
++
)
p
+=
sprintf
(
p
,
"setup %s input
\"
%s
\"\n
"
,
p_cfg
->
psz_name
,
p_cfg
->
ppsz_input
[
j
]
);
if
(
p_cfg
->
psz_output
)
p
+=
sprintf
(
p
,
"setup %s output %s
\n
"
,
p_cfg
->
psz_name
,
p_cfg
->
psz_output
);
for
(
j
=
0
;
j
<
p_cfg
->
i_option
;
j
++
)
p
+=
sprintf
(
p
,
"setup %s option %s
\n
"
,
p_cfg
->
psz_name
,
p_cfg
->
ppsz_option
[
j
]
);
if
(
p_cfg
->
b_vod
&&
p_cfg
->
vod
.
psz_mux
)
p
+=
sprintf
(
p
,
"setup %s mux %s
\n
"
,
p_cfg
->
psz_name
,
p_cfg
->
vod
.
psz_mux
);
}
/* and now, the schedule scripts */
for
(
i
=
0
;
i
<
vlm
->
i_schedule
;
i
++
)
{
vlm_schedule_sys_t
*
schedule
=
vlm
->
schedule
[
i
];
struct
tm
date
;
time_t
i_time
=
(
time_t
)
(
schedule
->
i_date
/
1000000
);
localtime_r
(
&
i_time
,
&
date
);
p
+=
sprintf
(
p
,
"new %s schedule "
,
schedule
->
psz_name
);
if
(
schedule
->
b_enabled
==
true
)
{
p
+=
sprintf
(
p
,
"date %d/%d/%d-%d:%d:%d enabled
\n
"
,
date
.
tm_year
+
1900
,
date
.
tm_mon
+
1
,
date
.
tm_mday
,
date
.
tm_hour
,
date
.
tm_min
,
date
.
tm_sec
);
}
else
{
p
+=
sprintf
(
p
,
"date %d/%d/%d-%d:%d:%d disabled
\n
"
,
date
.
tm_year
+
1900
,
date
.
tm_mon
+
1
,
date
.
tm_mday
,
date
.
tm_hour
,
date
.
tm_min
,
date
.
tm_sec
);
}
if
(
schedule
->
i_period
!=
0
)
{
p
+=
sprintf
(
p
,
"setup %s "
,
schedule
->
psz_name
);
i_time
=
(
time_t
)
(
schedule
->
i_period
/
1000000
);
date
.
tm_sec
=
(
int
)(
i_time
%
60
);
i_time
=
i_time
/
60
;
date
.
tm_min
=
(
int
)(
i_time
%
60
);
i_time
=
i_time
/
60
;
date
.
tm_hour
=
(
int
)(
i_time
%
24
);
i_time
=
i_time
/
24
;
date
.
tm_mday
=
(
int
)(
i_time
%
30
);
i_time
=
i_time
/
30
;
/* okay, okay, months are not always 30 days long */
date
.
tm_mon
=
(
int
)(
i_time
%
12
);
i_time
=
i_time
/
12
;
date
.
tm_year
=
(
int
)
i_time
;
p
+=
sprintf
(
p
,
"period %d/%d/%d-%d:%d:%d
\n
"
,
date
.
tm_year
,
date
.
tm_mon
,
date
.
tm_mday
,
date
.
tm_hour
,
date
.
tm_min
,
date
.
tm_sec
);
}
if
(
schedule
->
i_repeat
>=
0
)
{
p
+=
sprintf
(
p
,
"setup %s repeat %d
\n
"
,
schedule
->
psz_name
,
schedule
->
i_repeat
);
}
else
{
p
+=
sprintf
(
p
,
"
\n
"
);
}
for
(
j
=
0
;
j
<
schedule
->
i_command
;
j
++
)
{
p
+=
sprintf
(
p
,
"setup %s append %s
\n
"
,
schedule
->
psz_name
,
schedule
->
command
[
j
]
);
}
}
return
save
;
}
#endif
/* ENABLE_VLM */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment