2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 /// \ingroup ConfigParsers Playtree
38 #include "parser-mpcmd.h"
40 static int recursion_depth
= 0;
47 #define dvd_range(a) (a>0 && a<256)
48 #define UNSET_GLOBAL (mode = LOCAL)
49 // Use this 1 if you want to have only global option (no per file option)
50 // #define UNSET_GLOBAL (mode = GLOBAL)
53 static int is_entry_option(char *opt
, char *param
, play_tree_t
** ret
) {
54 play_tree_t
* entry
= NULL
;
58 if(strcasecmp(opt
,"playlist") == 0) { // We handle playlist here
60 return M_OPT_MISSING_PARAM
;
62 entry
= parse_playlist_file(param
);
73 static inline void add_entry(play_tree_t
**last_parentp
,
74 play_tree_t
**last_entryp
, play_tree_t
*entry
) {
75 if(*last_entryp
== NULL
)
76 play_tree_set_child(*last_parentp
,entry
);
78 play_tree_append_entry(*last_entryp
,entry
);
82 /// Setup the \ref Config from command line arguments and build a playtree.
83 /** \ingroup ConfigParsers
86 m_config_parse_mp_command_line(m_config_t
*config
, int argc
, char **argv
)
88 int i
,j
,start_title
=-1,end_title
=-1;
89 char *opt
,*splitpos
=NULL
;
92 int opt_exit
= 0; // flag indicating whether mplayer should exit without playing anything
93 play_tree_t
*last_parent
, *last_entry
= NULL
, *root
;
94 #ifdef CONFIG_MACOSX_FINDER
95 play_tree_t
*macosx_finder_args(m_config_t
*, int , char **);
99 assert(config
!= NULL
);
100 assert(argv
!= NULL
);
104 config
->mode
= M_COMMAND_LINE
;
106 #ifdef CONFIG_MACOSX_FINDER
107 root
=macosx_finder_args(config
, argc
, argv
);
112 last_parent
= root
= play_tree_new();
113 /* in order to work recursion detection properly in parse_config_file */
116 for (i
= 1; i
< argc
; i
++) {
119 /* check for -- (no more options id.) except --help! */
120 if ((*opt
== '-') && (*(opt
+1) == '-') && (*(opt
+2) == 0))
125 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, MSGTR_NoFileGivenOnCommandLine
);
130 if((opt
[0] == '{') && (opt
[1] == '\0'))
132 play_tree_t
* entry
= play_tree_new();
134 if(last_parent
->flags
& PLAY_TREE_RND
)
135 entry
->flags
|= PLAY_TREE_RND
;
136 if(last_entry
== NULL
) {
137 play_tree_set_child(last_parent
,entry
);
139 play_tree_append_entry(last_entry
,entry
);
146 if((opt
[0] == '}') && (opt
[1] == '\0'))
148 if( ! last_parent
|| ! last_parent
->parent
) {
149 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "too much }-\n");
152 last_entry
= last_parent
;
153 last_parent
= last_entry
->parent
;
157 if ((no_more_opts
== 0) && (*opt
== '-') && (*(opt
+1) != 0)) /* option */
160 /* remove trailing '-' */
163 mp_msg(MSGT_CFGPARSER
, MSGL_DBG3
, "this_opt = option: %s\n", opt
);
164 // We handle here some specific option
165 // Loop option when it apply to a group
166 if(strcasecmp(opt
,"loop") == 0 &&
167 (! last_entry
|| last_entry
->child
) ) {
170 l
= (i
+1<argc
) ? strtol(argv
[i
+1],&end
,0) : 0;
171 if(!end
|| *end
!= '\0') {
172 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, MSGTR_TheLoopOptionMustBeAnInteger
, argv
[i
+1]);
173 tmp
= ERR_OUT_OF_RANGE
;
175 play_tree_t
* pt
= last_entry
? last_entry
: last_parent
;
180 } else if(strcasecmp(opt
,"shuffle") == 0) {
181 if(last_entry
&& last_entry
->child
)
182 last_entry
->flags
|= PLAY_TREE_RND
;
184 last_parent
->flags
|= PLAY_TREE_RND
;
185 } else if(strcasecmp(opt
,"noshuffle") == 0) {
186 if(last_entry
&& last_entry
->child
)
187 last_entry
->flags
&= ~PLAY_TREE_RND
;
189 last_parent
->flags
&= ~PLAY_TREE_RND
;
191 const m_option_t
* mp_opt
= NULL
;
192 play_tree_t
* entry
= NULL
;
194 tmp
= is_entry_option(opt
,(i
+1<argc
) ? argv
[i
+ 1] : NULL
,&entry
);
195 if(tmp
> 0) { // It's an entry
197 add_entry(&last_parent
,&last_entry
,entry
);
198 if((last_parent
->flags
& PLAY_TREE_RND
) && entry
->child
)
199 entry
->flags
|= PLAY_TREE_RND
;
201 } else if(mode
== LOCAL
) // Entry is empty we have to drop his params
203 } else if(tmp
== 0) { // 'normal' options
204 mp_opt
= m_config_get_option(config
,opt
);
205 if (mp_opt
!= NULL
) { // Option exist
206 if(mode
== GLOBAL
|| (mp_opt
->flags
& M_OPT_GLOBAL
))
207 tmp
= (i
+1<argc
) ? m_config_set_option(config
, opt
, argv
[i
+ 1])
208 : m_config_set_option(config
, opt
, NULL
);
210 tmp
= m_config_check_option(config
, opt
, (i
+1<argc
) ? argv
[i
+ 1] : NULL
);
211 if(tmp
>= 0 && mode
!= DROP_LOCAL
) {
212 play_tree_t
* pt
= last_entry
? last_entry
: last_parent
;
213 play_tree_set_param(pt
,opt
, argv
[i
+ 1]);
218 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, MSGTR_UnknownOptionOnCommandLine
, opt
);
223 if (tmp
<= M_OPT_EXIT
) {
225 tmp
= M_OPT_EXIT
- tmp
;
228 mp_msg(MSGT_CFGPARSER
, MSGL_FATAL
, MSGTR_ErrorParsingOptionOnCommandLine
, opt
);
235 int is_dvdnav
= strstr(argv
[i
],"dvdnav://") != NULL
;
236 play_tree_t
* entry
= play_tree_new();
237 mp_msg(MSGT_CFGPARSER
, MSGL_DBG2
,"Adding file %s\n",argv
[i
]);
238 // if required expand DVD filename entries like dvd://1-3 into component titles
239 if ( strstr(argv
[i
],"dvd://") != NULL
|| is_dvdnav
)
241 int offset
= is_dvdnav
? 9 : 6;
242 splitpos
=strstr(argv
[i
]+offset
,"-");
245 start_title
=strtol(argv
[i
]+offset
,NULL
,10);
246 if (start_title
<0) { //entries like dvd://-2 start title implied 1
247 end_title
=abs(start_title
);
250 end_title
=strtol(splitpos
+1,NULL
,10);
253 if (dvd_range(start_title
) && dvd_range(end_title
) && (start_title
<end_title
))
255 for (j
=start_title
;j
<=end_title
;j
++)
258 entry
=play_tree_new();
259 snprintf(entbuf
,sizeof(entbuf
),is_dvdnav
? "dvdnav://%d" : "dvd://%d",j
);
260 play_tree_add_file(entry
,entbuf
);
261 add_entry(&last_parent
,&last_entry
,entry
);
265 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, MSGTR_InvalidPlayEntry
, argv
[i
]);
268 } else { // dvd:// or dvd://x entry
269 play_tree_add_file(entry
,argv
[i
]);
272 play_tree_add_file(entry
,argv
[i
]);
275 // Lock stdin if it will be used as input
276 if(strcasecmp(argv
[i
],"-") == 0)
277 m_config_set_option(config
,"noconsolecontrols",NULL
);
278 add_entry(&last_parent
,&last_entry
,entry
);
279 UNSET_GLOBAL
; // We start entry specific options
287 if(last_parent
!= root
)
288 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,"Missing }- ?\n");
293 play_tree_free(root
,1);