LGPL
[vlc.git] / src / video_output / postprocessing.c
1 /*****************************************************************************
2  * postprocessing.c
3  *****************************************************************************
4  * Copyright (C) 2010 Laurent Aimar
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27 #include <assert.h>
28
29 #include <vlc_common.h>
30 #include <vlc_vout.h>
31
32 #include "postprocessing.h"
33
34 static bool PostProcessIsPresent(const char *filter)
35 {
36     const char  *pp        = "postproc";
37     const size_t pp_length = strlen(pp);
38     return filter &&
39            !strncmp(filter, pp, pp_length) &&
40            (filter[pp_length] == '\0' || filter[pp_length] == ':');
41 }
42
43 static int PostProcessCallback(vlc_object_t *object, char const *cmd,
44                                vlc_value_t oldval, vlc_value_t newval, void *data)
45 {
46     vout_thread_t *vout = (vout_thread_t *)object;
47     VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
48
49     static const char *pp = "postproc";
50
51     char *filters = var_GetString(vout, "video-filter");
52
53     if (newval.i_int <= 0) {
54         if (PostProcessIsPresent(filters)) {
55             strcpy(filters, &filters[strlen(pp)]);
56             if (*filters == ':')
57                 strcpy(filters, &filters[1]);
58         }
59     } else {
60         if (!PostProcessIsPresent(filters)) {
61             if (filters) {
62                 char *tmp = filters;
63                 if (asprintf(&filters, "%s:%s", pp, tmp) < 0)
64                     filters = tmp;
65                 else
66                     free(tmp);
67             } else {
68                 filters = strdup(pp);
69             }
70         }
71     }
72     if (newval.i_int > 0)
73         var_SetInteger(vout, "postproc-q", newval.i_int);
74     if (filters) {
75         var_SetString(vout, "video-filter", filters);
76         free(filters);
77     } else if (newval.i_int > 0) {
78         var_TriggerCallback(vout, "video-filter");
79     }
80     return VLC_SUCCESS;
81 }
82 static void PostProcessEnable(vout_thread_t *vout)
83 {
84     vlc_value_t text;
85     msg_Dbg(vout, "Post-processing available");
86     var_Create(vout, "postprocess", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE);
87     text.psz_string = _("Post processing");
88     var_Change(vout, "postprocess", VLC_VAR_SETTEXT, &text, NULL);
89
90     for (int i = 0; i <= 6; i++) {
91         vlc_value_t val;
92         vlc_value_t text;
93         char tmp[1+1];
94
95         val.i_int = i;
96         snprintf(tmp, sizeof(tmp), "%d", i);
97         if (i == 0)
98             text.psz_string = _("Disable");
99         else
100             text.psz_string = tmp;
101         var_Change(vout, "postprocess", VLC_VAR_ADDCHOICE, &val, &text);
102     }
103     var_AddCallback(vout, "postprocess", PostProcessCallback, NULL);
104
105     /* */
106     char *filters = var_GetNonEmptyString(vout, "video-filter");
107     int postproc_q = 0;
108     if (PostProcessIsPresent(filters))
109         postproc_q = var_CreateGetInteger(vout, "postproc-q");
110
111     var_SetInteger(vout, "postprocess", postproc_q);
112
113     free(filters);
114 }
115 static void PostProcessDisable(vout_thread_t *vout)
116 {
117     msg_Dbg(vout, "Post-processing no more available");
118     var_Destroy(vout, "postprocess");
119 }
120
121 void vout_SetPostProcessingState(vout_thread_t *vout, vout_postprocessing_support_t *state, int qtype)
122 {
123     const int postproc_change = (qtype != QTYPE_NONE) - (state->qtype != QTYPE_NONE);
124     if (postproc_change == 1)
125         PostProcessEnable(vout);
126     else if (postproc_change == -1)
127         PostProcessDisable(vout);
128     if (postproc_change)
129         state->qtype = qtype;
130 }
131