Beispiel #1
0
unsigned char
__mb_cur_max(void)
{
	return (__mb_cur_max_l(uselocale(NULL)));
}
Beispiel #2
0
/**
 * Emit a log message. This function is the variable argument list equivalent
 * to vlc_Log().
 */
void vlc_vaLog (vlc_object_t *obj, int type, const char *module,
                const char *format, va_list args)
{
    if (obj != NULL && obj->i_flags & OBJECT_FLAGS_QUIET)
        return;

    /* Get basename from the module filename */
    char *p = strrchr(module, '/');
    if (p != NULL)
        module = p;
    p = strchr(module, '.');

    size_t modlen = (p != NULL) ? (p - module) : 1;
    char modulebuf[modlen];
    if (p != NULL)
    {
        memcpy(modulebuf, module, modlen);
        modulebuf[modlen] = '\0';
        module = modulebuf;
    }

    /* C locale to get error messages in English in the logs */
    locale_t c = newlocale (LC_MESSAGES_MASK, "C", (locale_t)0);
    locale_t locale = uselocale (c);

#ifndef __GLIBC__
    /* Expand %m to strerror(errno) - only once */
    char buf[strlen(format) + 2001], *ptr;
    strcpy (buf, format);
    ptr = (char*)buf;
    format = (const char*) buf;

    for( ;; )
    {
        ptr = strchr( ptr, '%' );
        if( ptr == NULL )
            break;

        if( ptr[1] == 'm' )
        {
            char errbuf[2001];
            size_t errlen;

#ifndef _WIN32
            strerror_r( errno, errbuf, 1001 );
#else
            int sockerr = WSAGetLastError( );
            if( sockerr )
            {
                strncpy( errbuf, net_strerror( sockerr ), 1001 );
                WSASetLastError( sockerr );
            }
            if ((sockerr == 0)
             || (strcmp ("Unknown network stack error", errbuf) == 0))
                strncpy( errbuf, strerror( errno ), 1001 );
#endif
            errbuf[1000] = 0;

            /* Escape '%' from the error string */
            for( char *percent = strchr( errbuf, '%' );
                 percent != NULL;
                 percent = strchr( percent + 2, '%' ) )
            {
                memmove( percent + 1, percent, strlen( percent ) + 1 );
            }

            errlen = strlen( errbuf );
            memmove( ptr + errlen, ptr + 2, strlen( ptr + 2 ) + 1 );
            memcpy( ptr, errbuf, errlen );
            break; /* Only once, so we don't overflow */
        }

        /* Looks for conversion specifier... */
        do
            ptr++;
        while( *ptr && ( strchr( "diouxXeEfFgGaAcspn%", *ptr ) == NULL ) );
        if( *ptr )
            ptr++; /* ...and skip it */
    }
#endif

    /* Fill message information fields */
    vlc_log_t msg;

    msg.i_object_id = (uintptr_t)obj;
    msg.psz_object_type = (obj != NULL) ? obj->psz_object_type : "generic";
    msg.psz_module = module;
    msg.psz_header = NULL;

    for (vlc_object_t *o = obj; o != NULL; o = o->p_parent)
        if (o->psz_header != NULL)
        {
            msg.psz_header = o->psz_header;
            break;
        }

    /* Pass message to the callback */
    libvlc_priv_t *priv = obj ? libvlc_priv (obj->p_libvlc) : NULL;

#ifdef _WIN32
    va_list ap;

    va_copy (ap, args);
    Win32DebugOutputMsg (priv ? &priv->log.verbose : NULL, type, &msg, format, ap);
    va_end (ap);
#endif

    if (priv) {
        vlc_rwlock_rdlock (&priv->log.lock);
        priv->log.cb (priv->log.opaque, type, &msg, format, args);
        vlc_rwlock_unlock (&priv->log.lock);
    }

    uselocale (locale);
    freelocale (c);
}
Beispiel #3
0
 * Copyright (c) 2015, Gary Guo 
 * All rights reserved. 
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met: 
 * 
 *  * Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer. 
 *  * Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in the 
 *    documentation and/or other materials provided with the distribution. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY 
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
 * DAMAGE. 
 */

#include <string.h>
#include <locale.h>

size_t strxfrm(char * restrict s1, const char * restrict s2, size_t n) {
	return strxfrm_l(s1, s2, n, uselocale((locale_t)0));
}
Beispiel #4
0
char *
_real_gettext_u(const char *domain, const char *msgid1, const char *msgid2,
    unsigned long int ln, int category, int plural, locale_t loc)
{
	char	msgfile[MAXPATHLEN]; 	/* 1024 */
	char	mydomain[TEXTDOMAINMAX + 1]; /* 256 + 1 */
	char	*cur_binding;	/* points to current binding in list */
	const char *cur_locale;
	char	*cur_domain, *result, *nlspath;
	char	*msgloc, *cb, *cur_domain_binding;
	char	*language;
	unsigned int	n = (unsigned int)ln;	/* we don't need long for n */
	uint32_t	cur_domain_len, cblen;
	uint32_t	hash_domain;
	struct msg_pack	*mp, omp;

#ifdef GETTEXT_DEBUG
	gprintf(0, "*************** _real_gettext_u(\"%s\", \"%s\", "
	    "\"%s\", %d, %d, %d)\n",
	    domain ? domain : "NULL", msgid1 ? msgid1 : "NULL",
	    msgid2 ? msgid2 : "NULL", n, category, plural);
	gprintf(0, "***************** global_gt: 0x%p\n", global_gt);
	printgt(global_gt, 1);
#endif

	if (msgid1 == NULL)
		return (NULL);

	mp = memset(&omp, 0, sizeof (omp));	/* msg pack */

	/*
	 * category may be LC_MESSAGES or LC_TIME
	 * locale contains the value of 'category'
	 */
	if (loc == NULL)
		loc = uselocale(NULL);
	cur_locale = current_locale(loc, category);

	language = getenv("LANGUAGE"); /* for GNU */
	if (language) {
		if (!*language || strchr(language, '/') != NULL) {
			/*
			 * LANGUAGE is an empty string or
			 * LANGUAGE contains '/'.
			 * Ignore it.
			 */
			language = NULL;
		}
	}

	/*
	 * Query the current domain if domain argument is NULL pointer
	 */
	mydomain[0] = '\0';
	if (domain == NULL) {
		/*
		 * if NULL is specified for domainname,
		 * use the currently bound domain.
		 */
		cur_domain = _textdomain_u(NULL, mydomain);
	} else if (!*domain) {
		/*
		 * if an empty string is specified
		 */
		cur_domain = DEFAULT_DOMAIN;
	} else {
		cur_domain = (char *)domain;
	}

	hash_domain = get_hashid(cur_domain, &cur_domain_len);
	if (cur_domain_len > TEXTDOMAINMAX) {
		/* domain is invalid, return msg_id */
		DFLTMSG(result, msgid1, msgid2, n, plural);
		return (result);
	}

	nlspath = getenv("NLSPATH"); /* get the content of NLSPATH */
	if (nlspath == NULL || !*nlspath) {
		/* no NLSPATH is defined in the environ */
		if ((*cur_locale == 'C') && (*(cur_locale + 1) == '\0')) {
			/*
			 * If C locale,
			 * return the original msgid immediately.
			 */
			DFLTMSG(result, msgid1, msgid2, n, plural);
			return (result);
		}
		nlspath = NULL;
	} else {
		/* NLSPATH is set */
		int	ret;

		msgloc = current_locale(loc, LC_MESSAGES);

		ret = process_nlspath(cur_domain, msgloc,
		    (const char *)nlspath, &cur_binding);
		if (ret == -1) {
			/* error occurred */
			DFLTMSG(result, msgid1, msgid2, n, plural);
			return (result);
		} else if (ret == 0) {
			nlspath = NULL;
		}
	}

	cur_domain_binding = _real_bindtextdomain_u(cur_domain,
	    NULL, TP_BINDING);
	if (cur_domain_binding == NULL) {
		DFLTMSG(result, msgid1, msgid2, n, plural);
		return (result);
	}

	mp->msgid1 = msgid1;
	mp->msgid2 = msgid2;
	mp->msgfile = msgfile;
	mp->domain = cur_domain;
	mp->binding = cur_domain_binding;
	mp->locale = cur_locale;
	mp->language = language;
	mp->domain_len = cur_domain_len;
	mp->n = n;
	mp->category = category;
	mp->plural = plural;
	mp->hash_domain = hash_domain;

	/*
	 * Spec1170 requires that we use NLSPATH if it's defined, to
	 * override any system default variables.  If NLSPATH is not
	 * defined or if a message catalog is not found in any of the
	 * components (bindings) specified by NLSPATH, dcgettext_u() will
	 * search for the message catalog in either a) the binding path set
	 * by any previous application calls to bindtextdomain() or
	 * b) the default binding path (/usr/lib/locale).  Save the original
	 * binding path so that we can search it if the message catalog
	 * is not found via NLSPATH.  The original binding is restored before
	 * returning from this routine because the gettext routines should
	 * not change the binding set by the application.  This allows
	 * bindtextdomain() to be called once for all gettext() calls in the
	 * application.
	 */

	/*
	 * First, examine NLSPATH
	 */
	if (nlspath) {
		/*
		 * NLSPATH binding has been successfully built
		 */
#ifdef GETTEXT_DEBUG
		gprintf(0, "************************** examining NLSPATH\n");
		gprintf(0, "       cur_binding: \"%s\"\n",
		    cur_binding ? cur_binding : "(null)");
#endif

		mp->nlsp = 1;
		/*
		 * cur_binding always ends with ':' before a null
		 * termination.
		 */
		while (*cur_binding) {
			cb = cur_binding;
			while (*cur_binding != ':')
				cur_binding++;
			cblen = cur_binding - cb;
			cur_binding++;
			if (cblen >= MAXPATHLEN) {
				/* cur_binding too long */
				DFLTMSG(result, msgid1, msgid2, n, plural);
				return (result);
			}

			(void) memcpy(mp->msgfile, cb, cblen);
			*(mp->msgfile + cblen) = '\0';

#ifdef GETTEXT_DEBUG
			gprintf(0, "*******************"
			    "********************* \n");
			gprintf(0, "       msgfile: \"%s\"\n",
			    msgfile ? msgfile : "(null)");
			gprintf(0, "*******************"
			    "********************* \n");
#endif
			result = handle_mo(mp);
			if (result) {
				return (result);
			}
		}
	}

	mp->nlsp = 0;
	mp->binding = cur_domain_binding;
	/*
	 * Next, examine LANGUAGE
	 */
	if (language) {
		char	*ret_msg;
		ret_msg = handle_lang(mp);
		if (ret_msg != NULL) {
			/* valid msg found in GNU MO */
			return (ret_msg);
		}
		/*
		 * handle_lang() may have overridden locale
		 */
		mp->locale = cur_locale;
		mp->status = 0;
	}

	/*
	 * Finally, handle a single binding
	 */
#ifdef GETTEXT_DEBUG
	*mp->msgfile = '\0';
#endif
	if (mk_msgfile(mp) == NULL) {
		DFLTMSG(result, msgid1, msgid2, n, plural);
		return (result);
	}

	result = handle_mo(mp);
	if (result) {
		return (result);
	}
	DFLTMSG(result, msgid1, msgid2, n, plural);
	return (result);
} /* _real_gettext_u */
/*****************************************************************************
 * config_SaveConfigFile: Save a module's config options.
 *****************************************************************************
 * It's no use to save the config options that kept their default values, so
 * we'll try to be a bit clever here.
 *
 * When we save we mustn't delete the config options of the modules that
 * haven't been loaded. So we cannot just create a new config file with the
 * config structures we've got in memory.
 * I don't really know how to deal with this nicely, so I will use a completly
 * dumb method ;-)
 * I will load the config file in memory, but skipping all the sections of the
 * modules we want to save. Then I will create a brand new file, dump the file
 * loaded in memory and then append the sections of the modules we want to
 * save.
 * Really stupid no ?
 *****************************************************************************/
static int SaveConfigFile (vlc_object_t *p_this)
{
    char *permanent = NULL, *temporary = NULL;

    if( config_PrepareDir( p_this ) )
    {
        msg_Err( p_this, "no configuration directory" );
        return -1;
    }

    /* List all available modules */
    module_t **list = module_list_get (NULL);

    char *bigbuf = NULL;
    size_t bigsize = 0;
    FILE *file = config_OpenConfigFile (p_this);
    if (file != NULL)
    {
        struct stat st;

        /* Some users make vlcrc read-only to prevent changes.
         * The atomic replacement scheme breaks this "feature",
         * so we check for read-only by hand. */
        if (fstat (fileno (file), &st)
         || !(st.st_mode & S_IWUSR))
        {
            msg_Err (p_this, "configuration file is read-only");
            goto error;
        }

        bigsize = (st.st_size < LONG_MAX) ? st.st_size : 0;
        bigbuf = malloc (bigsize + 1);
        if (bigbuf == NULL)
            goto error;

        /* backup file into memory, we only need to backup the sections we
         * won't save later on */
        char *p_index = bigbuf;
        char *line = NULL;
        size_t bufsize;
        ssize_t linelen;
        bool backup = false;

        while ((linelen = getline (&line, &bufsize, file)) != -1)
        {
            char *p_index2;

            if ((line[0] == '[') && (p_index2 = strchr(line,']')))
            {
                module_t *module;

                /* we found a new section, check if we need to do a backup */
                backup = true;
                for (int i = 0; (module = list[i]) != NULL; i++)
                {
                    const char *objname = module_get_object (module);

                    if (!strncmp (line + 1, objname, strlen (objname)))
                    {
                        backup = false; /* no, we will rewrite it! */
                        break;
                    }
                }
            }

            /* save line if requested and line is valid (doesn't begin with a
             * space, tab, or eol) */
            if (backup && !memchr ("\n\t ", line[0], 3))
            {
                memcpy (p_index, line, linelen);
                p_index += linelen;
            }
        }
        fclose (file);
        file = NULL;
        free (line);
        *p_index = '\0';
        bigsize = p_index - bigbuf;
    }

    /*
     * Save module config in file
     */
    permanent = config_GetConfigFile (p_this);
    if (!permanent)
    {
        module_list_free (list);
        goto error;
    }

    if (asprintf (&temporary, "%s.%u", permanent, getpid ()) == -1)
    {
        temporary = NULL;
        module_list_free (list);
        goto error;
    }

    /* Configuration lock must be taken before vlcrc serializer below. */
    vlc_rwlock_rdlock (&config_lock);

    /* The temporary configuration file is per-PID. Therefore SaveConfigFile()
     * should be serialized against itself within a given process. */
    static vlc_mutex_t lock = VLC_STATIC_MUTEX;
    vlc_mutex_lock (&lock);

    int fd = vlc_open (temporary, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR);
    if (fd == -1)
    {
        vlc_rwlock_unlock (&config_lock);
        vlc_mutex_unlock (&lock);
        module_list_free (list);
        goto error;
    }
    file = fdopen (fd, "wt");
    if (file == NULL)
    {
        msg_Err (p_this, "cannot create configuration file: %m");
        vlc_rwlock_unlock (&config_lock);
        close (fd);
        vlc_mutex_unlock (&lock);
        module_list_free (list);
        goto error;
    }

    fprintf( file,
        "\xEF\xBB\xBF###\n"
        "###  "PACKAGE_NAME" "PACKAGE_VERSION"\n"
        "###\n"
        "\n"
        "###\n"
        "### lines beginning with a '#' character are comments\n"
        "###\n"
        "\n" );

    /* Ensure consistent number formatting... */
    locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
    locale_t baseloc = uselocale (loc);

    /* We would take the config lock here. But this would cause a lock
     * inversion with the serializer above and config_AutoSaveConfigFile().
    vlc_rwlock_rdlock (&config_lock);*/

    /* Look for the selected module, if NULL then save everything */
    module_t *p_parser;
    for (int i = 0; (p_parser = list[i]) != NULL; i++)
    {
        module_config_t *p_item, *p_end;

        if( !p_parser->i_config_items )
            continue;

        fprintf( file, "[%s]", module_get_object (p_parser) );
        if( p_parser->psz_longname )
            fprintf( file, " # %s\n\n", p_parser->psz_longname );
        else
            fprintf( file, "\n\n" );

        for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize;
             p_item < p_end;
             p_item++ )
        {
            if (!CONFIG_ITEM(p_item->i_type)   /* ignore hint */
             || p_item->b_removed              /* ignore deprecated option */
             || p_item->b_unsaveable)          /* ignore volatile option */
                continue;

            if (IsConfigIntegerType (p_item->i_type))
            {
                int64_t val = p_item->value.i;
                config_Write (file, p_item->psz_text,
                             (CONFIG_CLASS(p_item->i_type) == CONFIG_ITEM_BOOL)
                                  ? N_("boolean") : N_("integer"),
                              val == p_item->orig.i,
                              p_item->psz_name, "%"PRId64, val);
            }
            else
            if (IsConfigFloatType (p_item->i_type))
            {
                float val = p_item->value.f;
                config_Write (file, p_item->psz_text, N_("float"),
                              val == p_item->orig.f,
                              p_item->psz_name, "%f", val);
            }
            else
            {
                const char *psz_value = p_item->value.psz;
                bool modified;

                assert (IsConfigStringType (p_item->i_type));

                modified = !!strcmp (psz_value ? psz_value : "",
                                     p_item->orig.psz ? p_item->orig.psz : "");
                config_Write (file, p_item->psz_text, N_("string"),
                              !modified, p_item->psz_name, "%s",
                              psz_value ? psz_value : "");
            }
            p_item->b_dirty = false;
        }
    }
    vlc_rwlock_unlock (&config_lock);

    module_list_free (list);
    if (loc != (locale_t)0)
    {
        uselocale (baseloc);
        freelocale (loc);
    }

    /*
     * Restore old settings from the config in file
     */
    if (bigsize)
        fwrite (bigbuf, 1, bigsize, file);

    /*
     * Flush to disk and replace atomically
     */
    fflush (file); /* Flush from run-time */
    if (ferror (file))
    {
        vlc_unlink (temporary);
        vlc_mutex_unlock (&lock);
        msg_Err (p_this, "cannot write configuration file");
        clearerr (file);
        goto error;
    }
#if defined(__APPLE__) || defined(__ANDROID__)
    fsync (fd); /* Flush from OS */
#else
    fdatasync (fd); /* Flush from OS */
#endif
#if defined (WIN32) || defined (__OS2__)
    /* Windows cannot (re)move open files nor overwrite existing ones */
    fclose (file);
    vlc_unlink (permanent);
#endif
    /* Atomically replace the file... */
    if (vlc_rename (temporary, permanent))
        vlc_unlink (temporary);
    /* (...then synchronize the directory, err, TODO...) */
    /* ...and finally close the file */
    vlc_mutex_unlock (&lock);
#if !defined (WIN32) && !defined (__OS2__)
    fclose (file);
#endif

    free (temporary);
    free (permanent);
    free (bigbuf);
    return 0;

error:
    if( file )
        fclose( file );
    free (temporary);
    free (permanent);
    free (bigbuf);
    return -1;
}
Beispiel #6
0
wint_t
btowc(int c)
{
	return (btowc_l(c, uselocale(NULL)));
}
Beispiel #7
0
int
toupper(int c)
{
	return (isascii(c) ? __trans_upper[c] : toupper_l(c, uselocale(NULL)));
}
Beispiel #8
0
wctrans_t
wctrans(const char *charclass)
{
    return (wctrans_l(charclass, uselocale(NULL)));
}
Beispiel #9
0
/**
 * Composes a string with a format string (like printf) in the buffer pointed
 * by buf (taking buf_size as the maximum buffer capacity to fill).
 * If the resulting string would be longer than n - 1 characters, the remaining
 * characters are discarded and not stored, but counted for the value returned
 * by the function.
 * A terminating NUL character is automatically appended after the content
 * written.
 * Internally, the function retrieves arguments from the list identified by
 * args as if va_arg was used on it, and thus the state of args is likely to
 * be altered by the call.
 * In any case, arg should have been initialized by va_start at some point
 * before the call, and it is expected to be released by va_end at some point
 * after the call.
 *
 * This version ignores the current locale and uses the locale "C" for Linux,
 * FreeBSD, OSX and Android.
 *
 * @param buf Pointer to a buffer where the resulting C string is stored.
 * @param buf_size Maximum number of bytes to be used in the buffer. The
 *        generated string has a length of at most buf_size - 1, leaving space
 *        for the additional terminating NUL character.
 * @param format C string that contains a format string (see printf).
 * @param args A value identifying a variable arguments list initialized with
 *        va_start.
 *
 * @return On success, the number of characters that would have been written if
 *         buf_size had been sufficiently large, not counting the terminating
 *         NUL character. On failure, a negative number is returned.
 *         Notice that only when this returned value is non-negative and less
 *         than buf_size, the string has been completely written.
 *
 * @since 0.6.0
 */
SR_API int sr_vsnprintf_ascii(char *buf, size_t buf_size,
	const char *format, va_list args)
{
#if defined(_WIN32)
	int ret;

#if 0
	/*
	 * TODO: This part compiles with mingw-w64 but doesn't run with Win7.
	 *       Doesn't start because of "Procedure entry point _create_locale
	 *       not found in msvcrt.dll".
	 *       mingw-w64 should link to msvcr100.dll not msvcrt.dll!.
	 * See: https://msdn.microsoft.com/en-us/en-en/library/1kt27hek.aspx
	 */
	_locale_t locale;

	locale = _create_locale(LC_NUMERIC, "C");
	ret = _vsnprintf_l(buf, buf_size, format, locale, args);
	_free_locale(locale);
#endif

	/* vsprintf uses the current locale, may cause issues for floats. */
	ret = vsnprintf(buf, buf_size, format, args);

	return ret;
#elif defined(__APPLE__)
	/*
	 * See:
	 * https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/printf_l.3.html
	 * https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/xlocale.3.html
	 */
	int ret;
	locale_t locale;

	locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
	ret = vsnprintf_l(buf, buf_size, locale, format, args);
	freelocale(locale);

	return ret;
#elif defined(__FreeBSD__) && __FreeBSD_version >= 901000
	/*
	 * See:
	 * https://www.freebsd.org/cgi/man.cgi?query=printf_l&apropos=0&sektion=3&manpath=FreeBSD+9.1-RELEASE
	 * https://www.freebsd.org/cgi/man.cgi?query=xlocale&apropos=0&sektion=3&manpath=FreeBSD+9.1-RELEASE
	 */
	int ret;
	locale_t locale;

	locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
	ret = vsnprintf_l(buf, buf_size, locale, format, args);
	freelocale(locale);

	return ret;
#elif defined(__ANDROID__)
	/*
	 * The Bionic libc only has two locales ("C" aka "POSIX" and "C.UTF-8"
	 * aka "en_US.UTF-8"). The decimal point is hard coded as ".".
	 * See: https://android.googlesource.com/platform/bionic/+/master/libc/bionic/locale.cpp
	 */
	int ret;

	ret = vsnprintf(buf, buf_size, format, args);

	return ret;
#elif defined(__linux__)
	int ret;
	locale_t old_locale, temp_locale;

	/* Switch to C locale for proper float/double conversion. */
	temp_locale = newlocale(LC_NUMERIC, "C", NULL);
	old_locale = uselocale(temp_locale);

	ret = vsnprintf(buf, buf_size, format, args);

	/* Switch back to original locale. */
	uselocale(old_locale);
	freelocale(temp_locale);

	return ret;
#elif defined(__unix__) || defined(__unix)
	/*
	 * This is a fallback for all other BSDs, *nix and FreeBSD <= 9.0, by
	 * using the current locale for snprintf(). This may not work correctly
	 * for floats!
	 */
	int ret;

	ret = vsnprintf(buf, buf_size, format, args);

	return ret;
#else
	/* No implementation for unknown systems! */
	return -1;
#endif
}
Beispiel #10
0
/* Test the gl_locale_name() function.  */
static void
test_locale_name (void)
{
  const char *name;

  /* Check that gl_locale_name returns non-NULL.  */
  ASSERT (gl_locale_name (LC_MESSAGES, "LC_MESSAGES") != NULL);

  /* Get into a defined state,  */
  setlocale (LC_ALL, "en_US.UTF-8");
#if HAVE_NEWLOCALE
  uselocale (LC_GLOBAL_LOCALE);
#endif

  /* Check that when all environment variables are unset,
     gl_locale_name returns the default locale.  */
  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  unsetenv ("LC_MESSAGES");
  unsetenv ("LC_NUMERIC");
  unsetenv ("LANG");
  setlocale (LC_ALL, "");
  ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
                  gl_locale_name_default ()) == 0);
  ASSERT (strcmp (gl_locale_name (LC_NUMERIC, "LC_NUMERIC"),
                  gl_locale_name_default ()) == 0);

  /* Check that an empty environment variable is treated like an unset
     environment variable.  */

  setenv ("LC_ALL", "", 1);
  unsetenv ("LC_CTYPE");
  unsetenv ("LC_MESSAGES");
  unsetenv ("LANG");
  setlocale (LC_ALL, "");
  ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
                  gl_locale_name_default ()) == 0);

  unsetenv ("LC_ALL");
  setenv ("LC_CTYPE", "", 1);
  unsetenv ("LC_MESSAGES");
  unsetenv ("LANG");
  setlocale (LC_ALL, "");
  ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
                  gl_locale_name_default ()) == 0);

  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  setenv ("LC_MESSAGES", "", 1);
  unsetenv ("LANG");
  setlocale (LC_ALL, "");
  ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
                  gl_locale_name_default ()) == 0);

  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  unsetenv ("LC_MESSAGES");
  setenv ("LANG", "", 1);
  setlocale (LC_ALL, "");
  ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"),
                  gl_locale_name_default ()) == 0);

  /* Check that LC_ALL overrides the others, and LANG is overridden by the
     others.  */

  setenv ("LC_ALL", "C", 1);
  unsetenv ("LC_CTYPE");
  unsetenv ("LC_MESSAGES");
  unsetenv ("LANG");
  setlocale (LC_ALL, "");
  ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);

  unsetenv ("LC_ALL");
  setenv ("LC_CTYPE", "C", 1);
  setenv ("LC_MESSAGES", "C", 1);
  unsetenv ("LANG");
  setlocale (LC_ALL, "");
  ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);

  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  unsetenv ("LC_MESSAGES");
  setenv ("LANG", "C", 1);
  setlocale (LC_ALL, "");
  ASSERT (strcmp (gl_locale_name (LC_MESSAGES, "LC_MESSAGES"), "C") == 0);

  /* Check mixed situations.  */

  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
  setenv ("LANG", "de_DE.UTF-8", 1);
  if (setlocale (LC_ALL, "") != NULL)
    {
      name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
      ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
      name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
      ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
    }

  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
  unsetenv ("LANG");
  if (setlocale (LC_ALL, "") != NULL)
    {
      name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
      ASSERT (strcmp (name, gl_locale_name_default ()) == 0);
      name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
      ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
    }

#if HAVE_NEWLOCALE
  /* Check that gl_locale_name considers the thread locale.  */
  {
    locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
    if (locale != NULL)
      {
        uselocale (locale);
        name = gl_locale_name (LC_CTYPE, "LC_CTYPE");
        ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
        name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES");
        ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
      }
  }

  /* Check that gl_locale_name distinguishes different categories of the
     thread locale, and that the name is the right one for each.  */
  {
    unsigned int i;

    for (i = 0; i < SIZEOF (categories); i++)
      {
        int category_mask = categories[i].mask;
        locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
        if (locale != NULL)
          {
            locale = newlocale (category_mask, "de_DE.UTF-8", locale);
            if (locale != NULL)
              {
                unsigned int j;

                uselocale (locale);
                for (j = 0; j < SIZEOF (categories); j++)
                  {
                    const char *name_j =
                      gl_locale_name (categories[j].cat, categories[j].string);
                    if (j == i)
                      ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0);
                    else
                      ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0);
                  }
              }
          }
      }
  }
#endif
}
Beispiel #11
0
wint_t
towctrans(wint_t wc, wctrans_t desc)
{
    return (towctrans_l(wc, desc, uselocale(NULL)));
}
Beispiel #12
0
/* Test the gl_locale_name_environ() function.  */
static void
test_locale_name_environ (void)
{
  const char *name;

  /* Get into a defined state,  */
  setlocale (LC_ALL, "en_US.UTF-8");
#if HAVE_NEWLOCALE
  uselocale (LC_GLOBAL_LOCALE);
#endif

  /* Check that when all environment variables are unset,
     gl_locale_name_environ returns NULL.  */
  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  unsetenv ("LC_MESSAGES");
  unsetenv ("LC_NUMERIC");
  unsetenv ("LANG");
  ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);
  ASSERT (gl_locale_name_environ (LC_NUMERIC, "LC_NUMERIC") == NULL);

  /* Check that an empty environment variable is treated like an unset
     environment variable.  */

  setenv ("LC_ALL", "", 1);
  unsetenv ("LC_CTYPE");
  unsetenv ("LC_MESSAGES");
  unsetenv ("LANG");
  ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);

  unsetenv ("LC_ALL");
  setenv ("LC_CTYPE", "", 1);
  unsetenv ("LC_MESSAGES");
  unsetenv ("LANG");
  ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);

  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  setenv ("LC_MESSAGES", "", 1);
  unsetenv ("LANG");
  ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);

  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  unsetenv ("LC_MESSAGES");
  setenv ("LANG", "", 1);
  ASSERT (gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES") == NULL);

  /* Check that LC_ALL overrides the others, and LANG is overridden by the
     others.  */

  setenv ("LC_ALL", "C", 1);
  unsetenv ("LC_CTYPE");
  unsetenv ("LC_MESSAGES");
  unsetenv ("LANG");
  name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
  ASSERT (strcmp (name, "C") == 0);

  unsetenv ("LC_ALL");
  setenv ("LC_CTYPE", "C", 1);
  setenv ("LC_MESSAGES", "C", 1);
  unsetenv ("LANG");
  name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
  ASSERT (strcmp (name, "C") == 0);

  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  unsetenv ("LC_MESSAGES");
  setenv ("LANG", "C", 1);
  name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
  ASSERT (strcmp (name, "C") == 0);

  /* Check mixed situations.  */

  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
  setenv ("LANG", "de_DE.UTF-8", 1);
  name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE");
  ASSERT (strcmp (name, "de_DE.UTF-8") == 0);
  name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
  ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);

  unsetenv ("LC_ALL");
  unsetenv ("LC_CTYPE");
  setenv ("LC_MESSAGES", "fr_FR.UTF-8", 1);
  unsetenv ("LANG");
  name = gl_locale_name_environ (LC_CTYPE, "LC_CTYPE");
  ASSERT (name == NULL);
  name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
  ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);

#if HAVE_NEWLOCALE
  /* Check that gl_locale_name_environ ignores the thread locale.  */
  {
    locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
    if (locale != NULL)
      {
        unsetenv ("LC_ALL");
        unsetenv ("LC_CTYPE");
        unsetenv ("LC_MESSAGES");
        setenv ("LANG", "C", 1);
        setlocale (LC_ALL, "");
        uselocale (locale);
        name = gl_locale_name_environ (LC_MESSAGES, "LC_MESSAGES");
        ASSERT (strcmp (name, "C") == 0);
      }
  }
#endif
}
Beispiel #13
0
/* Test the gl_locale_name_thread() function.  */
static void
test_locale_name_thread (void)
{
  /* Get into a defined state,  */
  setlocale (LC_ALL, "en_US.UTF-8");

#if HAVE_NEWLOCALE
  /* Check that gl_locale_name_thread returns NULL when no thread locale is
     set.  */
  uselocale (LC_GLOBAL_LOCALE);
  ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL);
  ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL);

  /* Check that gl_locale_name_thread considers the thread locale.  */
  {
    locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
    if (locale != NULL)
      {
        const char *name;

        uselocale (locale);
        name = gl_locale_name_thread (LC_CTYPE, "LC_CTYPE");
        ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
        name = gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES");
        ASSERT (strcmp (name, "fr_FR.UTF-8") == 0);
      }
  }

  /* Check that gl_locale_name_thread distinguishes different categories of the
     thread locale, and that the name is the right one for each.  */
  {
    unsigned int i;

    for (i = 0; i < SIZEOF (categories); i++)
      {
        int category_mask = categories[i].mask;
        locale_t locale = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", NULL);
        if (locale != NULL)
          {
            locale = newlocale (category_mask, "de_DE.UTF-8", locale);
            if (locale != NULL)
              {
                unsigned int j;

                uselocale (locale);
                for (j = 0; j < SIZEOF (categories); j++)
                  {
                    const char *name_j =
                      gl_locale_name_thread (categories[j].cat,
                                             categories[j].string);
                    if (j == i)
                      ASSERT (strcmp (name_j, "de_DE.UTF-8") == 0);
                    else
                      ASSERT (strcmp (name_j, "fr_FR.UTF-8") == 0);
                  }
              }
          }
      }
  }

  /* Check that gl_locale_name_thread returns a string that is allocated with
     indefinite extent.  */
  {
    /* Try many locale names in turn, in order to defeat possible caches.  */
    static const char * const choices[] =
      {
        "C",
        "POSIX",
        "af_ZA",
        "af_ZA.UTF-8",
        "am_ET",
        "am_ET.UTF-8",
        "be_BY",
        "be_BY.UTF-8",
        "bg_BG",
        "bg_BG.UTF-8",
        "ca_ES",
        "ca_ES.UTF-8",
        "cs_CZ",
        "cs_CZ.UTF-8",
        "da_DK",
        "da_DK.UTF-8",
        "de_AT",
        "de_AT.UTF-8",
        "de_CH",
        "de_CH.UTF-8",
        "de_DE",
        "de_DE.UTF-8",
        "el_GR",
        "el_GR.UTF-8",
        "en_AU",
        "en_AU.UTF-8",
        "en_CA",
        "en_CA.UTF-8",
        "en_GB",
        "en_GB.UTF-8",
        "en_IE",
        "en_IE.UTF-8",
        "en_NZ",
        "en_NZ.UTF-8",
        "en_US",
        "en_US.UTF-8",
        "es_ES",
        "es_ES.UTF-8",
        "et_EE",
        "et_EE.UTF-8",
        "eu_ES",
        "eu_ES.UTF-8",
        "fi_FI",
        "fi_FI.UTF-8",
        "fr_BE",
        "fr_BE.UTF-8",
        "fr_CA",
        "fr_CA.UTF-8",
        "fr_CH",
        "fr_CH.UTF-8",
        "fr_FR",
        "fr_FR.UTF-8",
        "he_IL",
        "he_IL.UTF-8",
        "hr_HR",
        "hr_HR.UTF-8",
        "hu_HU",
        "hu_HU.UTF-8",
        "hy_AM",
        "is_IS",
        "is_IS.UTF-8",
        "it_CH",
        "it_CH.UTF-8",
        "it_IT",
        "it_IT.UTF-8",
        "ja_JP.UTF-8",
        "kk_KZ",
        "kk_KZ.UTF-8",
        "ko_KR.UTF-8",
        "lt_LT",
        "lt_LT.UTF-8",
        "nl_BE",
        "nl_BE.UTF-8",
        "nl_NL",
        "nl_NL.UTF-8",
        "no_NO",
        "no_NO.UTF-8",
        "pl_PL",
        "pl_PL.UTF-8",
        "pt_BR",
        "pt_BR.UTF-8",
        "pt_PT",
        "pt_PT.UTF-8",
        "ro_RO",
        "ro_RO.UTF-8",
        "ru_RU",
        "ru_RU.UTF-8",
        "sk_SK",
        "sk_SK.UTF-8",
        "sl_SI",
        "sl_SI.UTF-8",
        "sv_SE",
        "sv_SE.UTF-8",
        "tr_TR",
        "tr_TR.UTF-8",
        "uk_UA",
        "uk_UA.UTF-8",
        "zh_CN",
        "zh_CN.UTF-8",
        "zh_HK",
        "zh_HK.UTF-8",
        "zh_TW",
        "zh_TW.UTF-8"
      };
    /* Remember which locales are available.  */
    unsigned char /* bool */ available[SIZEOF (choices)];
    /* Array of remembered results of gl_locale_name_thread.  */
    const char *unsaved_names[SIZEOF (choices)][SIZEOF (categories)];
    /* Array of remembered results of gl_locale_name_thread, stored in safe
       memory.  */
    char *saved_names[SIZEOF (choices)][SIZEOF (categories)];
    unsigned int j;

    for (j = 0; j < SIZEOF (choices); j++)
      {
        locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL);
        available[j] = (locale != NULL);
        if (locale != NULL)
          {
            unsigned int i;

            uselocale (locale);
            for (i = 0; i < SIZEOF (categories); i++)
              {
                unsaved_names[j][i] = gl_locale_name_thread (categories[i].cat, categories[i].string);
                saved_names[j][i] = strdup (unsaved_names[j][i]);
              }
            uselocale (LC_GLOBAL_LOCALE);
            freelocale (locale);
          }
      }
    /* Verify the unsaved_names are still valid.  */
    for (j = 0; j < SIZEOF (choices); j++)
      if (available[j])
        {
          unsigned int i;

          for (i = 0; i < SIZEOF (categories); i++)
            ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0);
        }
    /* Allocate many locales, without freeing them.  This is an attempt at
       overwriting as much of the previously allocated memory as possible.  */
    for (j = SIZEOF (choices); j > 0; )
      {
        j--;
        if (available[j])
          {
            locale_t locale = newlocale (LC_ALL_MASK, choices[j], NULL);
            unsigned int i;

            ASSERT (locale != NULL);
            uselocale (locale);
            for (i = 0; i < SIZEOF (categories); i++)
              {
                const char *name = gl_locale_name_thread (categories[i].cat, categories[i].string);
                ASSERT (strcmp (unsaved_names[j][i], name) == 0);
              }
            uselocale (LC_GLOBAL_LOCALE);
          }
      }
    /* Verify the unsaved_names are still valid.  */
    for (j = 0; j < SIZEOF (choices); j++)
      if (available[j])
        {
          unsigned int i;

          for (i = 0; i < SIZEOF (categories); i++)
            ASSERT (strcmp (unsaved_names[j][i], saved_names[j][i]) == 0);
        }
  }
#else
  /* Check that gl_locale_name_thread always returns NULL.  */
  ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL);
  ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL);
#endif
}
Beispiel #14
0
int
strcoll(const char *s1, const char *s2)
{
	return (strcoll_l(s1, s2, uselocale(NULL)));
}
Beispiel #15
0
int isxdigit(int c) {
	return isxdigit_l(c, uselocale((locale_t)0));
}
Beispiel #16
0
/**
 * Emit a log message. This function is the variable argument list equivalent
 * to vlc_Log().
 */
void vlc_vaLog (vlc_object_t *obj, int type, const char *module,
                const char *format, va_list args)
{
    if (obj != NULL && obj->i_flags & OBJECT_FLAGS_QUIET)
        return;

    /* C locale to get error messages in English in the logs */
    locale_t c = newlocale (LC_MESSAGES_MASK, "C", (locale_t)0);
    locale_t locale = uselocale (c);

#ifndef __GLIBC__
    /* Expand %m to strerror(errno) - only once */
    char buf[strlen(format) + 2001], *ptr;
    strcpy (buf, format);
    ptr = (char*)buf;
    format = (const char*) buf;

    for( ;; )
    {
        ptr = strchr( ptr, '%' );
        if( ptr == NULL )
            break;

        if( ptr[1] == 'm' )
        {
            char errbuf[2001];
            size_t errlen;

#ifndef WIN32
            strerror_r( errno, errbuf, 1001 );
#else
            int sockerr = WSAGetLastError( );
            if( sockerr )
            {
                strncpy( errbuf, net_strerror( sockerr ), 1001 );
                WSASetLastError( sockerr );
            }
            if ((sockerr == 0)
             || (strcmp ("Unknown network stack error", errbuf) == 0))
                strncpy( errbuf, strerror( errno ), 1001 );
#endif
            errbuf[1000] = 0;

            /* Escape '%' from the error string */
            for( char *percent = strchr( errbuf, '%' );
                 percent != NULL;
                 percent = strchr( percent + 2, '%' ) )
            {
                memmove( percent + 1, percent, strlen( percent ) + 1 );
            }

            errlen = strlen( errbuf );
            memmove( ptr + errlen, ptr + 2, strlen( ptr + 2 ) + 1 );
            memcpy( ptr, errbuf, errlen );
            break; /* Only once, so we don't overflow */
        }

        /* Looks for conversion specifier... */
        do
            ptr++;
        while( *ptr && ( strchr( "diouxXeEfFgGaAcspn%", *ptr ) == NULL ) );
        if( *ptr )
            ptr++; /* ...and skip it */
    }
#endif

    /* Fill message information fields */
    msg_item_t msg;

    msg.i_object_id = (uintptr_t)obj;
    msg.psz_object_type = (obj != NULL) ? obj->psz_object_type : "generic";
    msg.psz_module = module;
    msg.psz_header = NULL;

    for (vlc_object_t *o = obj; o != NULL; o = o->p_parent)
        if (o->psz_header != NULL)
        {
            msg.psz_header = o->psz_header;
            break;
        }

    /* Pass message to subscribers */
    libvlc_priv_t *priv = libvlc_priv (obj->p_libvlc);

    va_list ap;

    va_copy (ap, args);
    if (priv->b_color)
        PrintColorMsg (&priv->i_verbose, type, &msg, format, ap);
    else
        PrintMsg (&priv->i_verbose, type, &msg, format, ap);
    va_end (ap);

    vlc_rwlock_rdlock (&msg_lock);
    for (msg_subscription_t *sub = msg_head; sub != NULL; sub = sub->next)
    {
        va_copy (ap, args);
        sub->func (sub->opaque, type, &msg, format, ap);
        va_end (ap);
    }
    vlc_rwlock_unlock (&msg_lock);

    uselocale (locale);
    freelocale (c);
}
Beispiel #17
0
/**
 * ProjectM update thread which do the rendering
 * @param p_this: the p_thread object
 */
static void *Thread( void *p_data )
{
    filter_t  *p_filter = (filter_t*)p_data;
    filter_sys_t *p_sys = p_filter->p_sys;

    video_format_t fmt;
    vlc_gl_t *gl;
    unsigned int i_last_width  = 0;
    unsigned int i_last_height = 0;
    locale_t loc;
    locale_t oldloc;

    projectM *p_projectm;
#ifndef HAVE_PROJECTM2
    char *psz_config;
#else
    char *psz_preset_path;
    char *psz_title_font;
    char *psz_menu_font;
    projectM::Settings settings;
#endif

    vlc_savecancel();

    /* Create the openGL provider */
    p_sys->p_vout =
        (vout_thread_t *)vlc_object_create( p_filter, sizeof(vout_thread_t) );
    if( !p_sys->p_vout )
        goto error;

    /* */
    video_format_Init( &fmt, 0 );
    video_format_Setup( &fmt, VLC_CODEC_RGB32,
                        p_sys->i_width, p_sys->i_height, 0, 1 );
    fmt.i_sar_num = 1;
    fmt.i_sar_den = 1;

    vout_display_state_t state;
    memset( &state, 0, sizeof(state) );
    state.cfg.display.sar.num = 1;
    state.cfg.display.sar.den = 1;
    state.cfg.is_display_filled = true;
    state.cfg.zoom.num = 1;
    state.cfg.zoom.den = 1;
    state.sar.num = 1;
    state.sar.den = 1;

    p_sys->p_vd = vout_NewDisplay( p_sys->p_vout, &fmt, &state, "opengl",
                                   300000, 1000000 );
    if( !p_sys->p_vd )
    {
        vlc_object_release( p_sys->p_vout );
        goto error;
    }
    var_Create( p_sys->p_vout, "fullscreen", VLC_VAR_BOOL );
    var_AddCallback( p_sys->p_vout, "fullscreen", VoutCallback, p_sys->p_vd );

    gl = vout_GetDisplayOpengl( p_sys->p_vd );
    if( !gl )
    {
        var_DelCallback( p_sys->p_vout, "fullscreen", VoutCallback, p_sys->p_vd );
        vout_DeleteDisplay( p_sys->p_vd, NULL );
        vlc_object_release( p_sys->p_vout );
        goto error;
    }

    /* Work-around the projectM locale bug */
    loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
    oldloc = uselocale (loc);

    /* Create the projectM object */
#ifndef HAVE_PROJECTM2
    psz_config = var_InheritString( p_filter, "projectm-config" );
    p_projectm = new projectM( psz_config );
    free( psz_config );
#else
    psz_preset_path = var_InheritString( p_filter, "projectm-preset-path" );
#ifdef _WIN32
    if ( psz_preset_path == NULL )
    {
        char *psz_data_path = config_GetDataDir();
        asprintf( &psz_preset_path, "%s" DIR_SEP "visualization", psz_data_path );
        free( psz_data_path );
    }
#endif

    psz_title_font                = var_InheritString( p_filter, "projectm-title-font" );
    psz_menu_font                 = var_InheritString( p_filter, "projectm-menu-font" );

    settings.meshX                = var_InheritInteger( p_filter, "projectm-meshx" );
    settings.meshY                = var_InheritInteger( p_filter, "projectm-meshy" );
    settings.fps                  = 35;
    settings.textureSize          = var_InheritInteger( p_filter, "projectm-texture-size" );
    settings.windowWidth          = p_sys->i_width;
    settings.windowHeight         = p_sys->i_height;
    settings.presetURL            = psz_preset_path;
    settings.titleFontURL         = psz_title_font;
    settings.menuFontURL          = psz_menu_font;
    settings.smoothPresetDuration = 5;
    settings.presetDuration       = 30;
    settings.beatSensitivity      = 10;
    settings.aspectCorrection     = 1;
    settings.easterEgg            = 1;
    settings.shuffleEnabled       = 1;

    p_projectm = new projectM( settings );

    free( psz_menu_font );
    free( psz_title_font );
    free( psz_preset_path );
#endif /* HAVE_PROJECTM2 */

    p_sys->i_buffer_size = p_projectm->pcm()->maxsamples;
    p_sys->p_buffer = (float*)calloc( p_sys->i_buffer_size,
                                      sizeof( float ) );

    vlc_sem_post( &p_sys->ready );

    /* Choose a preset randomly or projectM will always show the first one */
    if ( p_projectm->getPlaylistSize() > 0 )
        p_projectm->selectPreset( (unsigned)vlc_mrand48() % p_projectm->getPlaylistSize() );

    /* */
    for( ;; )
    {
        const mtime_t i_deadline = mdate() + CLOCK_FREQ / 50; /* 50 fps max */
        /* Manage the events */
        vout_ManageDisplay( p_sys->p_vd, true );
        if( p_sys->p_vd->cfg->display.width  != i_last_width ||
                p_sys->p_vd->cfg->display.height != i_last_height )
        {
            /* FIXME it is not perfect as we will have black bands */
            vout_display_place_t place;
            vout_display_PlacePicture( &place, &p_sys->p_vd->source, p_sys->p_vd->cfg, false );
            p_projectm->projectM_resetGL( place.width, place.height );

            i_last_width  = p_sys->p_vd->cfg->display.width;
            i_last_height = p_sys->p_vd->cfg->display.height;
        }

        /* Render the image and swap the buffers */
        vlc_mutex_lock( &p_sys->lock );
        if( p_sys->i_nb_samples > 0 )
        {
            p_projectm->pcm()->addPCMfloat( p_sys->p_buffer,
                                            p_sys->i_nb_samples );
            p_sys->i_nb_samples = 0;
        }
        if( p_sys->b_quit )
        {
            vlc_mutex_unlock( &p_sys->lock );

            delete p_projectm;
            var_DelCallback( p_sys->p_vout, "fullscreen", VoutCallback, p_sys->p_vd );
            vout_DeleteDisplay( p_sys->p_vd, NULL );
            vlc_object_release( p_sys->p_vout );
            if (loc != (locale_t)0)
            {
                uselocale (oldloc);
                freelocale (loc);
            }
            return NULL;
        }
        vlc_mutex_unlock( &p_sys->lock );

        p_projectm->renderFrame();

        /* */
        mwait( i_deadline );

        if( !vlc_gl_Lock(gl) )
        {
            vlc_gl_Swap( gl );
            vlc_gl_Unlock( gl );
        }
    }
    abort();

error:
    p_sys->b_error = true;
    vlc_sem_post( &p_sys->ready );
    return NULL;
}
Beispiel #18
0
/**
 * Add a message to a queue
 *
 * This function provides basic functionnalities to other msg_* functions.
 * It adds a message to a queue (after having printed all stored messages if it
 * is full). If the message can't be converted to string in memory, it issues
 * a warning.
 */
void msg_GenericVa (vlc_object_t *p_this, int i_type,
                           const char *psz_module,
                           const char *psz_format, va_list _args)
{
    char *       psz_str = NULL;                 /* formatted message string */
    va_list      args;

    assert (p_this);

    if( p_this->i_flags & OBJECT_FLAGS_QUIET ||
        (p_this->i_flags & OBJECT_FLAGS_NODBG && i_type == VLC_MSG_DBG) )
        return;

    msg_bank_t *bank = libvlc_bank (p_this->p_libvlc);
    locale_t locale = uselocale (bank->locale);

#ifndef __GLIBC__
    /* Expand %m to strerror(errno) - only once */
    char buf[strlen( psz_format ) + 2001], *ptr;
    strcpy( buf, psz_format );
    ptr = (char*)buf;
    psz_format = (const char*) buf;

    for( ;; )
    {
        ptr = strchr( ptr, '%' );
        if( ptr == NULL )
            break;

        if( ptr[1] == 'm' )
        {
            char errbuf[2001];
            size_t errlen;

#ifndef WIN32
            strerror_r( errno, errbuf, 1001 );
#else
            int sockerr = WSAGetLastError( );
            if( sockerr )
            {
                strncpy( errbuf, net_strerror( sockerr ), 1001 );
                WSASetLastError( sockerr );
            }
            if ((sockerr == 0)
             || (strcmp ("Unknown network stack error", errbuf) == 0))
                strncpy( errbuf, strerror( errno ), 1001 );
#endif
            errbuf[1000] = 0;

            /* Escape '%' from the error string */
            for( char *percent = strchr( errbuf, '%' );
                 percent != NULL;
                 percent = strchr( percent + 2, '%' ) )
            {
                memmove( percent + 1, percent, strlen( percent ) + 1 );
            }

            errlen = strlen( errbuf );
            memmove( ptr + errlen, ptr + 2, strlen( ptr + 2 ) + 1 );
            memcpy( ptr, errbuf, errlen );
            break; /* Only once, so we don't overflow */
        }

        /* Looks for conversion specifier... */
        do
            ptr++;
        while( *ptr && ( strchr( "diouxXeEfFgGaAcspn%", *ptr ) == NULL ) );
        if( *ptr )
            ptr++; /* ...and skip it */
    }
#endif

    /* Convert message to string  */
    vlc_va_copy( args, _args );
    if( vasprintf( &psz_str, psz_format, args ) == -1 )
        psz_str = NULL;
    va_end( args );

    if( psz_str == NULL )
    {
        int canc = vlc_savecancel (); /* Do not print half of a message... */
#ifdef __GLIBC__
        fprintf( stderr, "main warning: can't store message (%m): " );
#else
        char psz_err[1001];
#ifndef WIN32
        /* we're not using GLIBC, so we are sure that the error description
         * will be stored in the buffer we provide to strerror_r() */
        strerror_r( errno, psz_err, 1001 );
#else
        strncpy( psz_err, strerror( errno ), 1001 );
#endif
        psz_err[1000] = '\0';
        fprintf( stderr, "main warning: can't store message (%s): ", psz_err );
#endif
        vlc_va_copy( args, _args );
        /* We should use utf8_vfprintf - but it calls malloc()... */
        vfprintf( stderr, psz_format, args );
        va_end( args );
        fputs( "\n", stderr );
        vlc_restorecancel (canc);
        uselocale (locale);
        return;
    }
    uselocale (locale);

    /* Fill message information fields */
    msg_item_t msg;

    msg.i_type = i_type;
    msg.i_object_id = (uintptr_t)p_this;
    msg.psz_object_type = p_this->psz_object_type;
    msg.psz_module = psz_module;
    msg.psz_msg = psz_str;
    msg.psz_header = NULL;

    for (vlc_object_t *o = p_this; o != NULL; o = o->p_parent)
        if (o->psz_header != NULL)
        {
            msg.psz_header = o->psz_header;
            break;
        }

    PrintMsg( p_this, &msg );

    vlc_rwlock_rdlock (&bank->lock);
    for (int i = 0; i < bank->i_sub; i++)
    {
        msg_subscription_t *sub = bank->pp_sub[i];
        libvlc_priv_t *priv = libvlc_priv( sub->instance );
        msg_bank_t *bank = priv->msg_bank;
        void *val = vlc_dictionary_value_for_key( &bank->enabled_objects,
                                                  msg.psz_module );
        if( val == kObjectPrintingDisabled ) continue;
        if( val != kObjectPrintingEnabled  ) /*if not allowed */
        {
            val = vlc_dictionary_value_for_key( &bank->enabled_objects,
                                                msg.psz_object_type );
            if( val == kObjectPrintingDisabled ) continue;
            if( val == kObjectPrintingEnabled  ); /* Allowed */
            else if( !bank->all_objects_enabled ) continue;
        }
        switch( msg.i_type )
        {
            case VLC_MSG_INFO:
            case VLC_MSG_ERR:
                if( sub->verbosity < 0 ) continue;
                break;
            case VLC_MSG_WARN:
                if( sub->verbosity < 1 ) continue;
                break;
            case VLC_MSG_DBG:
                if( sub->verbosity < 2 ) continue;
                break;
        }

        sub->func (sub->opaque, &msg);
    }
    vlc_rwlock_unlock (&bank->lock);
    free (msg.psz_msg);
}
Beispiel #19
0
static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
{
	// Non-uid template parameters will write to the dummy data (=> gets optimized out)
	vertex_shader_uid_data dummy_data;
	vertex_shader_uid_data* uid_data = out.template GetUidData<vertex_shader_uid_data>();
	if (uid_data == nullptr)
		uid_data = &dummy_data;

	out.SetBuffer(text);
	const bool is_writing_shadercode = (out.GetBuffer() != nullptr);
#ifndef ANDROID
	locale_t locale;
	locale_t old_locale;
	if (is_writing_shadercode)
	{
		locale = newlocale(LC_NUMERIC_MASK, "C", nullptr); // New locale for compilation
		old_locale = uselocale(locale); // Apply the locale for this thread
	}
#endif

	if (is_writing_shadercode)
		text[sizeof(text) - 1] = 0x7C;  // canary

	_assert_(bpmem.genMode.numtexgens == xfmem.numTexGen.numTexGens);
	_assert_(bpmem.genMode.numcolchans == xfmem.numChan.numColorChans);

	out.Write("%s", s_lighting_struct);

	// uniforms
	if (api_type == API_OPENGL)
		out.Write("layout(std140%s) uniform VSBlock {\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 2" : "");
	else
		out.Write("cbuffer VSBlock {\n");
	out.Write(s_shader_uniforms);
	out.Write("};\n");

	GenerateVSOutputStruct(out, api_type);

	uid_data->numTexGens = xfmem.numTexGen.numTexGens;
	uid_data->components = components;
	uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting;

	if (api_type == API_OPENGL)
	{
		out.Write("in float4 rawpos; // ATTR%d,\n", SHADER_POSITION_ATTRIB);
		if (components & VB_HAS_POSMTXIDX)
			out.Write("in int posmtx; // ATTR%d,\n", SHADER_POSMTX_ATTRIB);
		if (components & VB_HAS_NRM0)
			out.Write("in float3 rawnorm0; // ATTR%d,\n", SHADER_NORM0_ATTRIB);
		if (components & VB_HAS_NRM1)
			out.Write("in float3 rawnorm1; // ATTR%d,\n", SHADER_NORM1_ATTRIB);
		if (components & VB_HAS_NRM2)
			out.Write("in float3 rawnorm2; // ATTR%d,\n", SHADER_NORM2_ATTRIB);

		if (components & VB_HAS_COL0)
			out.Write("in float4 color0; // ATTR%d,\n", SHADER_COLOR0_ATTRIB);
		if (components & VB_HAS_COL1)
			out.Write("in float4 color1; // ATTR%d,\n", SHADER_COLOR1_ATTRIB);

		for (int i = 0; i < 8; ++i)
		{
			u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
			if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
				out.Write("in float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i, SHADER_TEXTURE0_ATTRIB + i);
		}

		uid_data->stereo = g_ActiveConfig.iStereoMode > 0;
		if (g_ActiveConfig.iStereoMode > 0)
		{
			out.Write("centroid out VS_OUTPUT o;\n");
		}
		else
		{
			// Let's set up attributes
			for (size_t i = 0; i < 8; ++i)
			{
				if (i < xfmem.numTexGen.numTexGens)
				{
					out.Write("centroid out float3 uv%d;\n", i);
				}
			}

			out.Write("centroid out float4 clipPos;\n");
			if (g_ActiveConfig.bEnablePixelLighting)
				out.Write("centroid out float4 Normal;\n");
			out.Write("centroid out float4 colors_02;\n");
			out.Write("centroid out float4 colors_12;\n");
		}

		out.Write("void main()\n{\n");

		if (g_ActiveConfig.iStereoMode <= 0)
			out.Write("VS_OUTPUT o;\n");
	}
	else // D3D
	{
		out.Write("VS_OUTPUT main(\n");

		// inputs
		if (components & VB_HAS_NRM0)
			out.Write("  float3 rawnorm0 : NORMAL0,\n");
		if (components & VB_HAS_NRM1)
			out.Write("  float3 rawnorm1 : NORMAL1,\n");
		if (components & VB_HAS_NRM2)
			out.Write("  float3 rawnorm2 : NORMAL2,\n");
		if (components & VB_HAS_COL0)
			out.Write("  float4 color0 : COLOR0,\n");
		if (components & VB_HAS_COL1)
			out.Write("  float4 color1 : COLOR1,\n");
		for (int i = 0; i < 8; ++i)
		{
			u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
			if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
				out.Write("  float%d tex%d : TEXCOORD%d,\n", hastexmtx ? 3 : 2, i, i);
		}
		if (components & VB_HAS_POSMTXIDX)
			out.Write("  int posmtx : BLENDINDICES,\n");
		out.Write("  float4 rawpos : POSITION) {\n");

		out.Write("VS_OUTPUT o;\n");
	}

	// transforms
	if (components & VB_HAS_POSMTXIDX)
	{
		if (is_writing_shadercode && (DriverDetails::HasBug(DriverDetails::BUG_NODYNUBOACCESS) && !DriverDetails::HasBug(DriverDetails::BUG_ANNIHILATEDUBOS)) )
		{
			// This'll cause issues, but  it can't be helped
			out.Write("float4 pos = float4(dot(" I_TRANSFORMMATRICES"[0], rawpos), dot(" I_TRANSFORMMATRICES"[1], rawpos), dot(" I_TRANSFORMMATRICES"[2], rawpos), 1);\n");
			if (components & VB_HAS_NRMALL)
				out.Write("float3 N0 = " I_NORMALMATRICES"[0].xyz, N1 = " I_NORMALMATRICES"[1].xyz, N2 = " I_NORMALMATRICES"[2].xyz;\n");
		}
		else
		{
			out.Write("float4 pos = float4(dot(" I_TRANSFORMMATRICES"[posmtx], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+1], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+2], rawpos), 1);\n");

			if (components & VB_HAS_NRMALL)
			{
				out.Write("int normidx = posmtx >= 32 ? (posmtx-32) : posmtx;\n");
				out.Write("float3 N0 = " I_NORMALMATRICES"[normidx].xyz, N1 = " I_NORMALMATRICES"[normidx+1].xyz, N2 = " I_NORMALMATRICES"[normidx+2].xyz;\n");
			}
		}

		if (components & VB_HAS_NRM0)
			out.Write("float3 _norm0 = normalize(float3(dot(N0, rawnorm0), dot(N1, rawnorm0), dot(N2, rawnorm0)));\n");
		if (components & VB_HAS_NRM1)
			out.Write("float3 _norm1 = float3(dot(N0, rawnorm1), dot(N1, rawnorm1), dot(N2, rawnorm1));\n");
		if (components & VB_HAS_NRM2)
			out.Write("float3 _norm2 = float3(dot(N0, rawnorm2), dot(N1, rawnorm2), dot(N2, rawnorm2));\n");
	}
	else
	{
		out.Write("float4 pos = float4(dot(" I_POSNORMALMATRIX"[0], rawpos), dot(" I_POSNORMALMATRIX"[1], rawpos), dot(" I_POSNORMALMATRIX"[2], rawpos), 1.0);\n");
		if (components & VB_HAS_NRM0)
			out.Write("float3 _norm0 = normalize(float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm0), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm0), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm0)));\n");
		if (components & VB_HAS_NRM1)
			out.Write("float3 _norm1 = float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm1), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm1), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm1));\n");
		if (components & VB_HAS_NRM2)
			out.Write("float3 _norm2 = float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm2), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm2), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm2));\n");
	}

	if (!(components & VB_HAS_NRM0))
		out.Write("float3 _norm0 = float3(0.0, 0.0, 0.0);\n");


	out.Write("o.pos = float4(dot(" I_PROJECTION"[0], pos), dot(" I_PROJECTION"[1], pos), dot(" I_PROJECTION"[2], pos), dot(" I_PROJECTION"[3], pos));\n");

	out.Write("int4 lacc;\n"
			"float3 ldir, h;\n"
			"float dist, dist2, attn;\n");

	uid_data->numColorChans = xfmem.numChan.numColorChans;
	if (xfmem.numChan.numColorChans == 0)
	{
		if (components & VB_HAS_COL0)
			out.Write("o.colors_0 = color0;\n");
		else
			out.Write("o.colors_0 = float4(1.0, 1.0, 1.0, 1.0);\n");
	}

	GenerateLightingShader<T>(out, uid_data->lighting, components, "color", "o.colors_");

	if (xfmem.numChan.numColorChans < 2)
	{
		if (components & VB_HAS_COL1)
			out.Write("o.colors_1 = color1;\n");
		else
			out.Write("o.colors_1 = o.colors_0;\n");
	}
	// special case if only pos and tex coord 0 and tex coord input is AB11
	// donko - this has caused problems in some games. removed for now.
	bool texGenSpecialCase = false;
	/*bool texGenSpecialCase =
		((g_main_cp_state.vtx_desc.Hex & 0x60600L) == g_main_cp_state.vtx_desc.Hex) && // only pos and tex coord 0
		(g_main_cp_state.vtx_desc.Tex0Coord != NOT_PRESENT) &&
		(xfmem.texcoords[0].texmtxinfo.inputform == XF_TEXINPUT_AB11);
		*/

	// transform texcoords
	out.Write("float4 coord = float4(0.0, 0.0, 1.0, 1.0);\n");
	for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
	{
		TexMtxInfo& texinfo = xfmem.texMtxInfo[i];

		out.Write("{\n");
		out.Write("coord = float4(0.0, 0.0, 1.0, 1.0);\n");
		uid_data->texMtxInfo[i].sourcerow = xfmem.texMtxInfo[i].sourcerow;
		switch (texinfo.sourcerow)
		{
		case XF_SRCGEOM_INROW:
			_assert_( texinfo.inputform == XF_TEXINPUT_ABC1 );
			out.Write("coord = rawpos;\n"); // pos.w is 1
			break;
		case XF_SRCNORMAL_INROW:
			if (components & VB_HAS_NRM0)
			{
				_assert_( texinfo.inputform == XF_TEXINPUT_ABC1 );
				out.Write("coord = float4(rawnorm0.xyz, 1.0);\n");
			}
			break;
		case XF_SRCCOLORS_INROW:
			_assert_( texinfo.texgentype == XF_TEXGEN_COLOR_STRGBC0 || texinfo.texgentype == XF_TEXGEN_COLOR_STRGBC1 );
			break;
		case XF_SRCBINORMAL_T_INROW:
			if (components & VB_HAS_NRM1)
			{
				_assert_( texinfo.inputform == XF_TEXINPUT_ABC1 );
				out.Write("coord = float4(rawnorm1.xyz, 1.0);\n");
			}
			break;
		case XF_SRCBINORMAL_B_INROW:
			if (components & VB_HAS_NRM2)
			{
				_assert_( texinfo.inputform == XF_TEXINPUT_ABC1 );
				out.Write("coord = float4(rawnorm2.xyz, 1.0);\n");
			}
			break;
		default:
			_assert_(texinfo.sourcerow <= XF_SRCTEX7_INROW);
			if (components & (VB_HAS_UV0<<(texinfo.sourcerow - XF_SRCTEX0_INROW)) )
				out.Write("coord = float4(tex%d.x, tex%d.y, 1.0, 1.0);\n", texinfo.sourcerow - XF_SRCTEX0_INROW, texinfo.sourcerow - XF_SRCTEX0_INROW);
			break;
		}

		// first transformation
		uid_data->texMtxInfo[i].texgentype = xfmem.texMtxInfo[i].texgentype;
		switch (texinfo.texgentype)
		{
			case XF_TEXGEN_EMBOSS_MAP: // calculate tex coords into bump map

				if (components & (VB_HAS_NRM1|VB_HAS_NRM2))
				{
					// transform the light dir into tangent space
					uid_data->texMtxInfo[i].embosslightshift = xfmem.texMtxInfo[i].embosslightshift;
					uid_data->texMtxInfo[i].embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift;
					out.Write("ldir = normalize(" LIGHT_POS".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(texinfo.embosslightshift));
					out.Write("o.tex%d.xyz = o.tex%d.xyz + float3(dot(ldir, _norm1), dot(ldir, _norm2), 0.0);\n", i, texinfo.embosssourceshift);
				}
				else
				{
					_assert_(0); // should have normals
					uid_data->texMtxInfo[i].embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift;
					out.Write("o.tex%d.xyz = o.tex%d.xyz;\n", i, texinfo.embosssourceshift);
				}

				break;
			case XF_TEXGEN_COLOR_STRGBC0:
				_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
				out.Write("o.tex%d.xyz = float3(o.colors_0.x, o.colors_0.y, 1);\n", i);
				break;
			case XF_TEXGEN_COLOR_STRGBC1:
				_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
				out.Write("o.tex%d.xyz = float3(o.colors_1.x, o.colors_1.y, 1);\n", i);
				break;
			case XF_TEXGEN_REGULAR:
			default:
				uid_data->texMtxInfo_n_projection |= xfmem.texMtxInfo[i].projection << i;
				if (components & (VB_HAS_TEXMTXIDX0<<i))
				{
					out.Write("int tmp = int(tex%d.z);\n", i);
					if (texinfo.projection == XF_TEXPROJ_STQ)
						out.Write("o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES"[tmp]), dot(coord, " I_TRANSFORMMATRICES"[tmp+1]), dot(coord, " I_TRANSFORMMATRICES"[tmp+2]));\n", i);
					else
						out.Write("o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES"[tmp]), dot(coord, " I_TRANSFORMMATRICES"[tmp+1]), 1);\n", i);
				}
				else
				{
					if (texinfo.projection == XF_TEXPROJ_STQ)
						out.Write("o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]));\n", i, 3*i, 3*i+1, 3*i+2);
					else
						out.Write("o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]), 1);\n", i, 3*i, 3*i+1);
				}
				break;
		}

		uid_data->dualTexTrans_enabled = xfmem.dualTexTrans.enabled;
		// CHECKME: does this only work for regular tex gen types?
		if (xfmem.dualTexTrans.enabled && texinfo.texgentype == XF_TEXGEN_REGULAR)
		{
			const PostMtxInfo& postInfo = xfmem.postMtxInfo[i];

			uid_data->postMtxInfo[i].index = xfmem.postMtxInfo[i].index;
			int postidx = postInfo.index;
			out.Write("float4 P0 = " I_POSTTRANSFORMMATRICES"[%d];\n"
				"float4 P1 = " I_POSTTRANSFORMMATRICES"[%d];\n"
				"float4 P2 = " I_POSTTRANSFORMMATRICES"[%d];\n",
				postidx&0x3f, (postidx+1)&0x3f, (postidx+2)&0x3f);

			if (texGenSpecialCase)
			{
				// no normalization
				// q of input is 1
				// q of output is unknown

				// multiply by postmatrix
				out.Write("o.tex%d.xyz = float3(dot(P0.xy, o.tex%d.xy) + P0.z + P0.w, dot(P1.xy, o.tex%d.xy) + P1.z + P1.w, 0.0);\n", i, i, i);
			}
			else
			{
				uid_data->postMtxInfo[i].normalize = xfmem.postMtxInfo[i].normalize;
				if (postInfo.normalize)
					out.Write("o.tex%d.xyz = normalize(o.tex%d.xyz);\n", i, i);

				// multiply by postmatrix
				out.Write("o.tex%d.xyz = float3(dot(P0.xyz, o.tex%d.xyz) + P0.w, dot(P1.xyz, o.tex%d.xyz) + P1.w, dot(P2.xyz, o.tex%d.xyz) + P2.w);\n", i, i, i, i);
			}
		}

		out.Write("}\n");
	}

	// clipPos/w needs to be done in pixel shader, not here
	out.Write("o.clipPos = float4(pos.x,pos.y,o.pos.z,o.pos.w);\n");

	if (g_ActiveConfig.bEnablePixelLighting)
	{
		out.Write("o.Normal = float4(_norm0.x,_norm0.y,_norm0.z,pos.z);\n");

		if (components & VB_HAS_COL0)
			out.Write("o.colors_0 = color0;\n");

		if (components & VB_HAS_COL1)
			out.Write("o.colors_1 = color1;\n");
	}

	//write the true depth value, if the game uses depth textures pixel shaders will override with the correct values
	//if not early z culling will improve speed
	if (api_type == API_D3D)
	{
		out.Write("o.pos.z = o.pos.w + o.pos.z;\n");
	}
	else // OGL
	{
		// this results in a scale from -1..0 to -1..1 after perspective
		// divide
		out.Write("o.pos.z = o.pos.w + o.pos.z * 2.0;\n");

		// the next steps of the OGL pipeline are:
		// (x_c,y_c,z_c,w_c) = o.pos  //switch to OGL spec terminology
		// clipping to -w_c <= (x_c,y_c,z_c) <= w_c
		// (x_d,y_d,z_d) = (x_c,y_c,z_c)/w_c//perspective divide
		// z_w = (f-n)/2*z_d + (n+f)/2
		// z_w now contains the value to go to the 0..1 depth buffer

		//trying to get the correct semantic while not using glDepthRange
		//seems to get rather complicated
	}

	// The console GPU places the pixel center at 7/12 in screen space unless
	// antialiasing is enabled, while D3D and OpenGL place it at 0.5. This results
	// in some primitives being placed one pixel too far to the bottom-right,
	// which in turn can be critical if it happens for clear quads.
	// Hence, we compensate for this pixel center difference so that primitives
	// get rasterized correctly.
	out.Write("o.pos.xy = o.pos.xy - " I_PIXELCENTERCORRECTION".xy;\n");

	if (api_type == API_OPENGL)
	{
		if (g_ActiveConfig.iStereoMode <= 0)
		{
			// Bit ugly here
			// TODO: Make pretty
			// Will look better when we bind uniforms in GLSL 1.3
			// clipPos/w needs to be done in pixel shader, not here

			for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
				out.Write("uv%d.xyz = o.tex%d;\n", i, i);

			out.Write("clipPos = o.clipPos;\n");

			if (g_ActiveConfig.bEnablePixelLighting)
				out.Write("Normal = o.Normal;\n");

			out.Write("colors_02 = o.colors_0;\n");
			out.Write("colors_12 = o.colors_1;\n");
		}

		out.Write("gl_Position = o.pos;\n");
	}
	else // D3D
	{
		out.Write("return o;\n");
	}
	out.Write("}\n");

	if (is_writing_shadercode)
	{
		if (text[sizeof(text) - 1] != 0x7C)
			PanicAlert("VertexShader generator - buffer too small, canary has been eaten!");

#ifndef ANDROID
		uselocale(old_locale); // restore locale
		freelocale(locale);
#endif
	}
}
Beispiel #20
0
struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src,
                                  int flags)
{
    struct mp_archive *mpa = talloc_zero(NULL, struct mp_archive);
    mpa->log = log;
    mpa->locale = newlocale(LC_ALL_MASK, "C.UTF-8", (locale_t)0);
    if (!mpa->locale) {
        mpa->locale = newlocale(LC_CTYPE_MASK, "", (locale_t)0);
        if (!mpa->locale)
            goto err;
    }
    mpa->arch = archive_read_new();
    mpa->primary_src = src;
    if (!mpa->arch)
        goto err;

    // first volume is the primary streame
    if (!add_volume(log ,mpa, src, src->url))
        goto err;

    // try to open other volumes
    char** volumes = find_volumes(src);
    for (int i = 0; volumes[i]; i++) {
        if (!add_volume(log, mpa, NULL, volumes[i])) {
            talloc_free(volumes);
            goto err;
        }
    }
    talloc_free(volumes);

    locale_t oldlocale = uselocale(mpa->locale);

    archive_read_support_format_7zip(mpa->arch);
    archive_read_support_format_iso9660(mpa->arch);
    archive_read_support_format_rar(mpa->arch);
    archive_read_support_format_zip(mpa->arch);
    archive_read_support_filter_bzip2(mpa->arch);
    archive_read_support_filter_gzip(mpa->arch);
    archive_read_support_filter_xz(mpa->arch);
    if (flags & MP_ARCHIVE_FLAG_UNSAFE) {
        archive_read_support_format_gnutar(mpa->arch);
        archive_read_support_format_tar(mpa->arch);
    }

    archive_read_set_read_callback(mpa->arch, read_cb);
    archive_read_set_skip_callback(mpa->arch, skip_cb);
    archive_read_set_switch_callback(mpa->arch, switch_cb);
    archive_read_set_open_callback(mpa->arch, open_cb);
    archive_read_set_close_callback(mpa->arch, close_cb);
    if (mpa->primary_src->seekable)
        archive_read_set_seek_callback(mpa->arch, seek_cb);
    bool fail = archive_read_open1(mpa->arch) < ARCHIVE_OK;

    uselocale(oldlocale);

    if (fail)
        goto err;
    return mpa;

err:
    mp_archive_free(mpa);
    return NULL;
}
Beispiel #21
0
/*
 * char2wchar --- convert multibyte characters to wide characters
 *
 * This has almost the API of mbstowcs_l(), except that *from need not be
 * null-terminated; instead, the number of input bytes is specified as
 * fromlen.  Also, we ereport() rather than returning -1 for invalid
 * input encoding.	tolen is the maximum number of wchar_t's to store at *to.
 * The output will be zero-terminated iff there is room.
 */
size_t
char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen,
		   pg_locale_t locale)
{
	size_t		result;

	if (tolen == 0)
		return 0;

#ifdef WIN32
	/* See WIN32 "Unicode" comment above */
	if (GetDatabaseEncoding() == PG_UTF8)
	{
		/* Win32 API does not work for zero-length input */
		if (fromlen == 0)
			result = 0;
		else
		{
			result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
			/* A zero return is failure */
			if (result == 0)
				result = -1;
		}

		if (result != -1)
		{
			Assert(result < tolen);
			/* Append trailing null wchar (MultiByteToWideChar() does not) */
			to[result] = 0;
		}
	}
	else
#endif   /* WIN32 */
	{
		/* mbstowcs requires ending '\0' */
		char	   *str = pnstrdup(from, fromlen);

		if (locale == (pg_locale_t) 0)
		{
			/* Use mbstowcs directly for the default locale */
			result = mbstowcs(to, str, tolen);
		}
		else
		{
#ifdef HAVE_LOCALE_T
#ifdef HAVE_MBSTOWCS_L
			/* Use mbstowcs_l for nondefault locales */
			result = mbstowcs_l(to, str, tolen, locale);
#else							/* !HAVE_MBSTOWCS_L */
			/* We have to temporarily set the locale as current ... ugh */
			locale_t	save_locale = uselocale(locale);

			result = mbstowcs(to, str, tolen);

			uselocale(save_locale);
#endif   /* HAVE_MBSTOWCS_L */
#else							/* !HAVE_LOCALE_T */
			/* Can't have locale != 0 without HAVE_LOCALE_T */
			elog(ERROR, "mbstowcs_l is not available");
			result = 0;			/* keep compiler quiet */
#endif   /* HAVE_LOCALE_T */
		}

		pfree(str);
	}

	if (result == -1)
	{
		/*
		 * Invalid multibyte character encountered.  We try to give a useful
		 * error message by letting pg_verifymbstr check the string.  But it's
		 * possible that the string is OK to us, and not OK to mbstowcs ---
		 * this suggests that the LC_CTYPE locale is different from the
		 * database encoding.  Give a generic error message if verifymbstr
		 * can't find anything wrong.
		 */
		pg_verifymbstr(from, fromlen, false);	/* might not return */
		/* but if it does ... */
		ereport(ERROR,
				(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
				 errmsg("invalid multibyte character for locale"),
				 errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
	}

	return result;
}
Beispiel #22
0
/* Copyright (c) 2013-2015 Jeffrey Pfau
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "formatting.h"

#include <float.h>
#include <time.h>

int ftostr_l(char* restrict str, size_t size, float f, locale_t locale) {
#ifdef HAVE_SNPRINTF_L
	return snprintf_l(str, size, locale, "%.*g", FLT_DIG, f);
#elif defined(HAVE_LOCALE)
	locale_t old = uselocale(locale);
	int res = snprintf(str, size, "%.*g", FLT_DIG, f);
	uselocale(old);
	return res;
#elif defined(HAVE_SETLOCALE)
	char* old = setlocale(LC_NUMERIC, locale);
	int res = snprintf(str, size, "%.*g", FLT_DIG, f);
	setlocale(LC_NUMERIC, old);
	return res;
#else
	UNUSED(locale);
	return snprintf(str, size, "%.*g", FLT_DIG, f);
#endif
}

#ifndef HAVE_STRTOF_L
float strtof_l(const char* restrict str, char** restrict end, locale_t locale) {
Beispiel #23
0
/*****************************************************************************
 * config_LoadConfigFile: loads the configuration file.
 *****************************************************************************
 * This function is called to load the config options stored in the config
 * file.
 *****************************************************************************/
int config_LoadConfigFile( vlc_object_t *p_this )
{
    FILE *file;

    file = config_OpenConfigFile (p_this);
    if (file == NULL)
        return VLC_EGENERIC;

    /* Look for UTF-8 Byte Order Mark */
    char * (*convert) (const char *) = strdupnull;
    char bom[3];

    if ((fread (bom, 1, 3, file) != 3)
     || memcmp (bom, "\xEF\xBB\xBF", 3))
    {
        convert = FromLocaleDup;
        rewind (file); /* no BOM, rewind */
    }

    char *line = NULL;
    size_t bufsize;
    ssize_t linelen;

    /* Ensure consistent number formatting... */
    locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
    locale_t baseloc = uselocale (loc);

    vlc_rwlock_wrlock (&config_lock);
    while ((linelen = getline (&line, &bufsize, file)) != -1)
    {
        line[linelen - 1] = '\0'; /* trim newline */

        /* Ignore comments, section and empty lines */
        if (memchr ("#[", line[0], 3) != NULL)
            continue;

        /* look for option name */
        const char *psz_option_name = line;

        char *ptr = strchr (line, '=');
        if (ptr == NULL)
            continue; /* syntax error */
        *ptr = '\0';

        module_config_t *item = config_FindConfig (p_this, psz_option_name);
        if (item == NULL)
            continue;

        const char *psz_option_value = ptr + 1;
        switch (CONFIG_CLASS(item->i_type))
        {
            case CONFIG_ITEM_BOOL:
            case CONFIG_ITEM_INTEGER:
            {
                int64_t l;

                errno = 0;
                l = strtoi (psz_option_value);
                if ((l > item->max.i) || (l < item->min.i))
                    errno = ERANGE;
                if (errno)
                    msg_Warn (p_this, "Integer value (%s) for %s: %m",
                              psz_option_value, psz_option_name);
                else
                    item->value.i = l;
                break;
            }

            case CONFIG_ITEM_FLOAT:
                if (!*psz_option_value)
                    break;                    /* ignore empty option */
                item->value.f = (float)atof (psz_option_value);
                break;

            default:
                free ((char *)item->value.psz);
                item->value.psz = convert (psz_option_value);
                break;
        }
    }
    vlc_rwlock_unlock (&config_lock);
    free (line);

    if (ferror (file))
    {
        msg_Err (p_this, "error reading configuration: %m");
        clearerr (file);
    }
    fclose (file);

    if (loc != (locale_t)0)
    {
        uselocale (baseloc);
        freelocale (loc);
    }
    return 0;
}
Beispiel #24
0
static void
virLocaleRevert(virLocale *oldlocale)
{
    uselocale(*oldlocale);
}
Beispiel #25
0
/**
 * ProjectM update thread which do the rendering
 * @param p_this: the p_thread object
 */
static void *Thread( void *p_data )
{
    filter_t  *p_filter = (filter_t*)p_data;
    filter_sys_t *p_sys = p_filter->p_sys;
    vlc_gl_t *gl = p_sys->gl;
    locale_t loc;
    locale_t oldloc;

    projectM *p_projectm;
#ifndef HAVE_PROJECTM2
    char *psz_config;
#else
    char *psz_preset_path;
    char *psz_title_font;
    char *psz_menu_font;
    projectM::Settings settings;
#endif

    vlc_gl_MakeCurrent( gl );

    /* Work-around the projectM locale bug */
    loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
    oldloc = uselocale (loc);

    /* Create the projectM object */
#ifndef HAVE_PROJECTM2
    psz_config = var_InheritString( p_filter, "projectm-config" );
    p_projectm = new projectM( psz_config );
    free( psz_config );
#else
    psz_preset_path = var_InheritString( p_filter, "projectm-preset-path" );
#ifdef _WIN32
    if ( psz_preset_path == NULL )
    {
        char *psz_data_path = config_GetDataDir();
        asprintf( &psz_preset_path, "%s" DIR_SEP "visualization", psz_data_path );
        free( psz_data_path );
    }
#endif

    psz_title_font                = var_InheritString( p_filter, "projectm-title-font" );
    psz_menu_font                 = var_InheritString( p_filter, "projectm-menu-font" );

    settings.meshX                = var_InheritInteger( p_filter, "projectm-meshx" );
    settings.meshY                = var_InheritInteger( p_filter, "projectm-meshy" );
    settings.fps                  = 35;
    settings.textureSize          = var_InheritInteger( p_filter, "projectm-texture-size" );
    settings.windowWidth          = var_InheritInteger( p_filter, "projectm-width" );
    settings.windowHeight         = var_CreateGetInteger( p_filter, "projectm-height" );
    settings.presetURL            = psz_preset_path;
    settings.titleFontURL         = psz_title_font;
    settings.menuFontURL          = psz_menu_font;
    settings.smoothPresetDuration = 5;
    settings.presetDuration       = 30;
    settings.beatSensitivity      = 10;
    settings.aspectCorrection     = 1;
    settings.easterEgg            = 1;
    settings.shuffleEnabled       = 1;
    settings.softCutRatingsEnabled= false;

    p_projectm = new projectM( settings );

    free( psz_menu_font );
    free( psz_title_font );
    free( psz_preset_path );
#endif /* HAVE_PROJECTM2 */

    p_sys->i_buffer_size = p_projectm->pcm()->maxsamples;
    p_sys->p_buffer = (float*)calloc( p_sys->i_buffer_size,
                                      sizeof( float ) );

    /* Choose a preset randomly or projectM will always show the first one */
    if ( p_projectm->getPlaylistSize() > 0 )
        p_projectm->selectPreset( (unsigned)vlc_mrand48() % p_projectm->getPlaylistSize() );

    /* */
    for( ;; )
    {
        const mtime_t i_deadline = mdate() + CLOCK_FREQ / 50; /* 50 fps max */

        /* Manage the events */
        unsigned width, height;
        bool quit;

        if( vlc_gl_surface_CheckSize( gl, &width, &height ) )
            p_projectm->projectM_resetGL( width, height );

        /* Render the image and swap the buffers */
        vlc_mutex_lock( &p_sys->lock );
        if( p_sys->i_nb_samples > 0 )
        {
            p_projectm->pcm()->addPCMfloat( p_sys->p_buffer,
                                            p_sys->i_nb_samples );
            p_sys->i_nb_samples = 0;
        }
        quit = p_sys->b_quit;
        vlc_mutex_unlock( &p_sys->lock );

        if( quit )
            break;

        p_projectm->renderFrame();

        /* */
        mwait( i_deadline );

        if( !vlc_gl_Lock(gl) )
        {
            vlc_gl_Swap( gl );
            vlc_gl_Unlock( gl );
        }
    }

    delete p_projectm;

    if (loc != (locale_t)0)
    {
        uselocale (oldloc);
        freelocale (loc);
    }

    vlc_gl_ReleaseCurrent( gl );
    return NULL;
}
Beispiel #26
0
static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components)
{
	// Non-uid template parameters will write to the dummy data (=> gets optimized out)
	pixel_shader_uid_data dummy_data;
	pixel_shader_uid_data& uid_data = (&out.template GetUidData<pixel_shader_uid_data>() != nullptr)
										? out.template GetUidData<pixel_shader_uid_data>() : dummy_data;

	out.SetBuffer(text);
	const bool is_writing_shadercode = (out.GetBuffer() != nullptr);
#ifndef ANDROID
	locale_t locale;
	locale_t old_locale;
	if (is_writing_shadercode)
	{
		locale = newlocale(LC_NUMERIC_MASK, "C", nullptr); // New locale for compilation
		old_locale = uselocale(locale); // Apply the locale for this thread
	}
#endif

	if (is_writing_shadercode)
		text[sizeof(text) - 1] = 0x7C;  // canary

	unsigned int numStages = bpmem.genMode.numtevstages + 1;
	unsigned int numTexgen = bpmem.genMode.numtexgens;

	out.Write("//Pixel Shader for TEV stages\n");
	out.Write("//%i TEV stages, %i texgens, %i IND stages\n",
		numStages, numTexgen, bpmem.genMode.numindstages);

	uid_data.dstAlphaMode = dstAlphaMode;
	uid_data.genMode_numindstages = bpmem.genMode.numindstages;
	uid_data.genMode_numtevstages = bpmem.genMode.numtevstages;
	uid_data.genMode_numtexgens = bpmem.genMode.numtexgens;

	// dot product for integer vectors
	out.Write("int idot(int3 x, int3 y)\n"
	          "{\n"
	          "\tint3 tmp = x * y;\n"
	          "\treturn tmp.x + tmp.y + tmp.z;\n"
	          "}\n");

	out.Write("int idot(int4 x, int4 y)\n"
	          "{\n"
	          "\tint4 tmp = x * y;\n"
	          "\treturn tmp.x + tmp.y + tmp.z + tmp.w;\n"
	          "}\n\n");

	// rounding + casting to integer at once in a single function
	out.Write("int  iround(float  x) { return int (round(x)); }\n"
	          "int2 iround(float2 x) { return int2(round(x)); }\n"
	          "int3 iround(float3 x) { return int3(round(x)); }\n"
	          "int4 iround(float4 x) { return int4(round(x)); }\n\n");

	if (ApiType == API_OPENGL)
	{
		// Declare samplers
		for (int i = 0; i < 8; ++i)
			out.Write("uniform sampler2D samp%d;\n", i);
	}
	else // D3D
	{
		// Declare samplers
		for (int i = 0; i < 8; ++i)
			out.Write("sampler samp%d : register(s%d);\n", i, i);

		out.Write("\n");
		for (int i = 0; i < 8; ++i)
			out.Write("Texture2D Tex%d : register(t%d);\n", i, i);
	}
	out.Write("\n");

	if (ApiType == API_OPENGL)
		out.Write("layout(std140%s) uniform PSBlock {\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 1" : "");
	else
		out.Write("cbuffer PSBlock {\n");
	out.Write(
		"\tint4 " I_COLORS"[4];\n"
		"\tint4 " I_KCOLORS"[4];\n"
		"\tint4 " I_ALPHA";\n"
		"\tfloat4 " I_TEXDIMS"[8];\n"
		"\tint4 " I_ZBIAS"[2];\n"
		"\tint4 " I_INDTEXSCALE"[2];\n"
		"\tint4 " I_INDTEXMTX"[6];\n"
		"\tint4 " I_FOGCOLOR";\n"
		"\tint4 " I_FOGI";\n"
		"\tfloat4 " I_FOGF"[2];\n" );
	if (g_ActiveConfig.bEnablePixelLighting) 
	{
		out.Write(
		// For pixel lighting - TODO: Should only be defined when per pixel lighting is enabled!
		"\tint4 " I_PLIGHT_COLORS"[8];\n"
		"\tfloat4 " I_PLIGHTS"[32];\n"
		"\tint4 " I_PMATERIALS"[4];\n"
		"};\n");
	} else {
		out.Write( "};\n" );
	}

	const bool forced_early_z = g_ActiveConfig.backend_info.bSupportsEarlyZ && bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED);
	const bool per_pixel_depth = (bpmem.ztex2.op != ZTEXTURE_DISABLE && bpmem.UseLateDepthTest()) || (!g_ActiveConfig.bFastDepthCalc && bpmem.zmode.testenable && !forced_early_z);

	if (forced_early_z)
	{
		// Zcomploc (aka early_ztest) is a way to control whether depth test is done before
		// or after texturing and alpha test. PC graphics APIs used to provide no way to emulate
		// this feature properly until 2012: Depth tests were always done after alpha testing.
		// Most importantly, it was not possible to write to the depth buffer without also writing
		// a color value (unless color writing was disabled altogether).

		// OpenGL has a flag which allows the driver to still update the depth buffer if alpha
		// test fails. The driver isn't required to do this, but I (degasus) assume all of them do
		// because it's the much faster code path for the GPU.

		// D3D11 also has a way to force the driver to enable early-z, so we're fine here.
		if(ApiType == API_OPENGL)
		{
			out.Write("layout(early_fragment_tests) in;\n");
		}
		else
		{
			out.Write("[earlydepthstencil]\n");
		}
	}
	else if (bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED) && is_writing_shadercode)
	{
		static bool warn_once = true;
		if (warn_once)
			WARN_LOG(VIDEO, "Early z test enabled but not possible to emulate with current configuration. Make sure to enable fast depth calculations. If this message still shows up your hardware isn't able to emulate the feature properly (a GPU with D3D 11.0 / OGL 4.2 support is required).");
		warn_once = false;
	}

	if (ApiType == API_OPENGL)
	{
		out.Write("out vec4 ocol0;\n");
		if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
			out.Write("out vec4 ocol1;\n");

		if (per_pixel_depth)
			out.Write("#define depth gl_FragDepth\n");

		// We use the flag "centroid" to fix some MSAA rendering bugs. With MSAA, the
		// pixel shader will be executed for each pixel which has at least one passed sample.
		// So there may be rendered pixels where the center of the pixel isn't in the primitive.
		// As the pixel shader usually renders at the center of the pixel, this position may be
		// outside the primitive. This will lead to sampling outside the texture, sign changes, ...
		// As a workaround, we interpolate at the centroid of the coveraged pixel, which
		// is always inside the primitive.
		// Without MSAA, this flag is defined to have no effect.
		out.Write("centroid in float4 colors_02;\n");
		out.Write("centroid in float4 colors_12;\n");

		// compute window position if needed because binding semantic WPOS is not widely supported
		// Let's set up attributes
		for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
		{
			out.Write("centroid in float3 uv%d;\n", i);
		}
		out.Write("centroid in float4 clipPos;\n");
		if (g_ActiveConfig.bEnablePixelLighting)
		{
			out.Write("centroid in float4 Normal;\n");
		}

		out.Write("void main()\n{\n");
		out.Write("\tfloat4 rawpos = gl_FragCoord;\n");
	}
	else // D3D
	{
		out.Write("void main(\n");
		out.Write("  out float4 ocol0 : SV_Target0,%s%s\n  in float4 rawpos : SV_Position,\n",
			dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n  out float4 ocol1 : SV_Target1," : "",
			per_pixel_depth ? "\n  out float depth : SV_Depth," : "");

		out.Write("  in centroid float4 colors_0 : COLOR0,\n");
		out.Write("  in centroid float4 colors_1 : COLOR1");

		// compute window position if needed because binding semantic WPOS is not widely supported
		for (unsigned int i = 0; i < numTexgen; ++i)
			out.Write(",\n  in centroid float3 uv%d : TEXCOORD%d", i, i);
		out.Write(",\n  in centroid float4 clipPos : TEXCOORD%d", numTexgen);
		if (g_ActiveConfig.bEnablePixelLighting)
			out.Write(",\n  in centroid float4 Normal : TEXCOORD%d", numTexgen + 1);
		out.Write("        ) {\n");
	}

	out.Write("\tint4 c0 = " I_COLORS"[1], c1 = " I_COLORS"[2], c2 = " I_COLORS"[3], prev = " I_COLORS"[0];\n"
	          "\tint4 rastemp = int4(0, 0, 0, 0), textemp = int4(0, 0, 0, 0), konsttemp = int4(0, 0, 0, 0);\n"
	          "\tint3 comp16 = int3(1, 256, 0), comp24 = int3(1, 256, 256*256);\n"
	          "\tint alphabump=0;\n"
	          "\tint3 tevcoord=int3(0, 0, 0);\n"
	          "\tint2 wrappedcoord=int2(0,0), tempcoord=int2(0,0);\n"
	          "\tint4 tevin_a=int4(0,0,0,0),tevin_b=int4(0,0,0,0),tevin_c=int4(0,0,0,0),tevin_d=int4(0,0,0,0);\n\n"); // tev combiner inputs

	if (ApiType == API_OPENGL)
	{
		// On Mali, global variables must be initialized as constants.
		// This is why we initialize these variables locally instead.
		out.Write("\tfloat4 colors_0 = colors_02;\n");
		out.Write("\tfloat4 colors_1 = colors_12;\n");
	}

	if (g_ActiveConfig.bEnablePixelLighting)
	{
		out.Write("\tfloat3 _norm0 = normalize(Normal.xyz);\n\n");
		out.Write("\tfloat3 pos = float3(clipPos.x,clipPos.y,Normal.w);\n");

		out.Write("\tint4 lacc;\n"
				"\tfloat3 ldir, h;\n"
				"\tfloat dist, dist2, attn;\n");

		out.SetConstantsUsed(C_PLIGHT_COLORS, C_PLIGHT_COLORS+7); // TODO: Can be optimized further
		out.SetConstantsUsed(C_PLIGHTS, C_PLIGHTS+31); // TODO: Can be optimized further
		out.SetConstantsUsed(C_PMATERIALS, C_PMATERIALS+3);
		uid_data.components = components;
		GenerateLightingShader<T>(out, uid_data.lighting, components, I_PMATERIALS, I_PLIGHT_COLORS, I_PLIGHTS, "colors_", "colors_");
	}

	// HACK to handle cases where the tex gen is not enabled
	if (numTexgen == 0)
	{
		out.Write("\tint2 fixpoint_uv0 = int2(0, 0);\n\n");
	}
	else
	{
		out.SetConstantsUsed(C_TEXDIMS, C_TEXDIMS+numTexgen-1);
		for (unsigned int i = 0; i < numTexgen; ++i)
		{
			out.Write("\tint2 fixpoint_uv%d = iround(", i);
			// optional perspective divides
			uid_data.texMtxInfo_n_projection |= xfmem.texMtxInfo[i].projection << i;
			if (xfmem.texMtxInfo[i].projection == XF_TEXPROJ_STQ)
			{
				out.Write("(uv%d.z == 0.0 ? uv%d.xy : uv%d.xy / uv%d.z)", i, i, i, i);
			}
			else
			{
				out.Write("uv%d.xy", i);
			}
			out.Write(" * " I_TEXDIMS"[%d].zw * 128.0);\n\n", i);
			// TODO: S24 overflows here?
		}
	}

	// indirect texture map lookup
	int nIndirectStagesUsed = 0;
	if (bpmem.genMode.numindstages > 0)
	{
		for (unsigned int i = 0; i < numStages; ++i)
		{
			if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
				nIndirectStagesUsed |= 1 << bpmem.tevind[i].bt;
		}
	}

	uid_data.nIndirectStagesUsed = nIndirectStagesUsed;
	for (u32 i = 0; i < bpmem.genMode.numindstages; ++i)
	{
		if (nIndirectStagesUsed & (1 << i))
		{
			unsigned int texcoord = bpmem.tevindref.getTexCoord(i);
			unsigned int texmap = bpmem.tevindref.getTexMap(i);

			uid_data.SetTevindrefValues(i, texcoord, texmap);
			if (texcoord < numTexgen)
			{
				out.SetConstantsUsed(C_INDTEXSCALE+i/2,C_INDTEXSCALE+i/2);
				out.Write("\ttempcoord = fixpoint_uv%d >> " I_INDTEXSCALE"[%d].%s;\n", texcoord, i / 2, (i & 1) ? "zw" : "xy");
			}
			else
				out.Write("\ttempcoord = int2(0, 0);\n");

			out.Write("\tint3 iindtex%d = ", i);
			SampleTexture<T>(out, "(float2(tempcoord)/128.0)", "abg", texmap, ApiType);
		}
	}

	// Uid fields for BuildSwapModeTable are set in WriteStage
	char swapModeTable[4][5];
	const char* swapColors = "rgba";
	for (int i = 0; i < 4; i++)
	{
		swapModeTable[i][0] = swapColors[bpmem.tevksel[i*2].swap1];
		swapModeTable[i][1] = swapColors[bpmem.tevksel[i*2].swap2];
		swapModeTable[i][2] = swapColors[bpmem.tevksel[i*2+1].swap1];
		swapModeTable[i][3] = swapColors[bpmem.tevksel[i*2+1].swap2];
		swapModeTable[i][4] = '\0';
	}

	for (unsigned int i = 0; i < numStages; i++)
		WriteStage<T>(out, uid_data, i, ApiType, swapModeTable); // build the equation for this stage

#define MY_STRUCT_OFFSET(str,elem) ((u32)((u64)&(str).elem-(u64)&(str)))
	bool enable_pl = g_ActiveConfig.bEnablePixelLighting;
	uid_data.num_values = (enable_pl) ? sizeof(uid_data) : MY_STRUCT_OFFSET(uid_data,stagehash[numStages]);


	if (numStages)
	{
		// The results of the last texenv stage are put onto the screen,
		// regardless of the used destination register
		if (bpmem.combiners[numStages - 1].colorC.dest != 0)
		{
			out.Write("\tprev.rgb = %s;\n", tevCOutputTable[bpmem.combiners[numStages - 1].colorC.dest]);
		}
		if (bpmem.combiners[numStages - 1].alphaC.dest != 0)
		{
			out.Write("\tprev.a = %s;\n", tevAOutputTable[bpmem.combiners[numStages - 1].alphaC.dest]);
		}
	}
	out.Write("\tprev = prev & 255;\n");

	AlphaTest::TEST_RESULT Pretest = bpmem.alpha_test.TestResult();
	uid_data.Pretest = Pretest;

	// NOTE: Fragment may not be discarded if alpha test always fails and early depth test is enabled
	// (in this case we need to write a depth value if depth test passes regardless of the alpha testing result)
	if (Pretest == AlphaTest::UNDETERMINED || (Pretest == AlphaTest::FAIL && bpmem.UseLateDepthTest()))
		WriteAlphaTest<T>(out, uid_data, ApiType, dstAlphaMode, per_pixel_depth);

	// FastDepth means to trust the depth generated in perspective division.
	// It should be correct, but it seems not to be as accurate as required. TODO: Find out why!
	// For disabled FastDepth we just calculate the depth value again.
	// The performance impact of this additional calculation doesn't matter, but it prevents
	// the host GPU driver from performing any early depth test optimizations.
	if (g_ActiveConfig.bFastDepthCalc)
		out.Write("\tint zCoord = iround(rawpos.z * float(0xFFFFFF));\n");
	else
	{
		out.SetConstantsUsed(C_ZBIAS+1, C_ZBIAS+1);
		// the screen space depth value = far z + (clip z / clip w) * z range
		out.Write("\tint zCoord = " I_ZBIAS"[1].x + iround((clipPos.z / clipPos.w) * float(" I_ZBIAS"[1].y));\n");
	}

	// depth texture can safely be ignored if the result won't be written to the depth buffer (early_ztest) and isn't used for fog either
	const bool skip_ztexture = !per_pixel_depth && !bpmem.fog.c_proj_fsel.fsel;

	uid_data.ztex_op = bpmem.ztex2.op;
	uid_data.per_pixel_depth = per_pixel_depth;
	uid_data.forced_early_z = forced_early_z;
	uid_data.fast_depth_calc = g_ActiveConfig.bFastDepthCalc;
	uid_data.early_ztest = bpmem.UseEarlyDepthTest();
	uid_data.fog_fsel = bpmem.fog.c_proj_fsel.fsel;

	// Note: z-textures are not written to depth buffer if early depth test is used
	if (per_pixel_depth && bpmem.UseEarlyDepthTest())
		out.Write("\tdepth = float(zCoord) / float(0xFFFFFF);\n");

	// Note: depth texture output is only written to depth buffer if late depth test is used
	// theoretical final depth value is used for fog calculation, though, so we have to emulate ztextures anyway
	if (bpmem.ztex2.op != ZTEXTURE_DISABLE && !skip_ztexture)
	{
		// use the texture input of the last texture stage (textemp), hopefully this has been read and is in correct format...
		out.SetConstantsUsed(C_ZBIAS, C_ZBIAS+1);
		out.Write("\tzCoord = idot(" I_ZBIAS"[0].xyzw, textemp.xyzw) + " I_ZBIAS"[1].w %s;\n",
									(bpmem.ztex2.op == ZTEXTURE_ADD) ? "+ zCoord" : "");
		out.Write("\tzCoord = zCoord & 0xFFFFFF;\n");
	}

	if (per_pixel_depth && bpmem.UseLateDepthTest())
		out.Write("\tdepth = float(zCoord) / float(0xFFFFFF);\n");

	if (dstAlphaMode == DSTALPHA_ALPHA_PASS)
	{
		out.SetConstantsUsed(C_ALPHA, C_ALPHA);
		out.Write("\tocol0 = float4(float3(prev.rgb), float(" I_ALPHA".a)) / 255.0;\n");
	}
	else
	{
		WriteFog<T>(out, uid_data);
		out.Write("\tocol0 = float4(prev) / 255.0;\n");
	}

	// Use dual-source color blending to perform dst alpha in a single pass
	if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
	{
		out.SetConstantsUsed(C_ALPHA, C_ALPHA);

		// Colors will be blended against the alpha from ocol1 and
		// the alpha from ocol0 will be written to the framebuffer.
		out.Write("\tocol1 = float4(prev) / 255.0;\n");
		out.Write("\tocol0.a = float(" I_ALPHA".a) / 255.0;\n");
	}

	out.Write("}\n");

	if (is_writing_shadercode)
	{
		if (text[sizeof(text) - 1] != 0x7C)
			PanicAlert("PixelShader generator - buffer too small, canary has been eaten!");

#ifndef ANDROID
		uselocale(old_locale); // restore locale
		freelocale(locale);
#endif
	}
}
// Tests that we can only have a consistent and correct fpos_t when using
// f*pos functions (i.e. fpos doesn't get inside a multi byte character).
TEST(stdio, consistent_fpos_t) {
  ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
  uselocale(LC_GLOBAL_LOCALE);

  FILE* fp = tmpfile();
  ASSERT_TRUE(fp != NULL);

  wchar_t mb_one_bytes = L'h';
  wchar_t mb_two_bytes = 0x00a2;
  wchar_t mb_three_bytes = 0x20ac;
  wchar_t mb_four_bytes = 0x24b62;

  // Write to file.
  ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fputwc(mb_one_bytes, fp)));
  ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fputwc(mb_two_bytes, fp)));
  ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fputwc(mb_three_bytes, fp)));
  ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fputwc(mb_four_bytes, fp)));

  rewind(fp);

  // Record each character position.
  fpos_t pos1;
  fpos_t pos2;
  fpos_t pos3;
  fpos_t pos4;
  fpos_t pos5;
  EXPECT_EQ(0, fgetpos(fp, &pos1));
  ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
  EXPECT_EQ(0, fgetpos(fp, &pos2));
  ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
  EXPECT_EQ(0, fgetpos(fp, &pos3));
  ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
  EXPECT_EQ(0, fgetpos(fp, &pos4));
  ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
  EXPECT_EQ(0, fgetpos(fp, &pos5));

#if defined(__BIONIC__)
  // Bionic's fpos_t is just an alias for off_t. This is inherited from OpenBSD
  // upstream. Glibc differs by storing the mbstate_t inside its fpos_t. In
  // Bionic (and upstream OpenBSD) the mbstate_t is stored inside the FILE
  // structure.
  ASSERT_EQ(0, static_cast<off_t>(pos1));
  ASSERT_EQ(1, static_cast<off_t>(pos2));
  ASSERT_EQ(3, static_cast<off_t>(pos3));
  ASSERT_EQ(6, static_cast<off_t>(pos4));
  ASSERT_EQ(10, static_cast<off_t>(pos5));
#endif

  // Exercise back and forth movements of the position.
  ASSERT_EQ(0, fsetpos(fp, &pos2));
  ASSERT_EQ(mb_two_bytes, static_cast<wchar_t>(fgetwc(fp)));
  ASSERT_EQ(0, fsetpos(fp, &pos1));
  ASSERT_EQ(mb_one_bytes, static_cast<wchar_t>(fgetwc(fp)));
  ASSERT_EQ(0, fsetpos(fp, &pos4));
  ASSERT_EQ(mb_four_bytes, static_cast<wchar_t>(fgetwc(fp)));
  ASSERT_EQ(0, fsetpos(fp, &pos3));
  ASSERT_EQ(mb_three_bytes, static_cast<wchar_t>(fgetwc(fp)));
  ASSERT_EQ(0, fsetpos(fp, &pos5));
  ASSERT_EQ(WEOF, fgetwc(fp));

  fclose(fp);
}
/*****************************************************************************
* Return EQ level for all bands as a Table
*****************************************************************************/
static int vlclua_equalizer_get( lua_State *L )
{
    const unsigned bands = 10;
    input_thread_t *p_input = vlclua_get_input_internal( L );
    if( !p_input )
        return 0;
    audio_output_t *p_aout = input_GetAout( p_input );
    vlc_object_release( p_input );
    if( !p_aout )
        return 0;

    char *psz_af = var_GetNonEmptyString( p_aout, "audio-filter" );
    if( !psz_af || strstr ( psz_af, "equalizer" ) == NULL )
    {
        free( psz_af );
        vlc_object_release( p_aout );
        return 0;
    }
    free( psz_af );

    char *psz_bands_origin, *psz_bands;
    psz_bands_origin = psz_bands = var_GetNonEmptyString( p_aout, "equalizer-bands" );
    if( !psz_bands )
    {
        vlc_object_release( p_aout );
        return 0;
    }

    bool error = false;
    locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
    locale_t oldloc = uselocale (loc);
    lua_newtable( L );
    for( unsigned i = 0; i < bands; i++ )
    {
        float level = strtof( psz_bands, &psz_bands );
        char *str;
        if( asprintf( &str , "%f" , level ) == -1 )
        {
            error = true;
            break;
        }
        lua_pushstring( L, str );
        free(str);
        if( asprintf( &str , "band id=\"%u\"", i ) == -1 )
        {
            error = true;
            break;
        }
        lua_setfield( L , -2 , str );
        free( str );
    }

    free( psz_bands_origin );
    if( loc != (locale_t)0 )
    {
        uselocale (oldloc);
        freelocale (loc);
    }
    vlc_object_release( p_aout );
    return error ? 0 : 1;
}
Beispiel #29
0
STATIC
#endif
const char *
locale_charset (void)
{
  const char *codeset;
  const char *aliases;

#if !(defined WINDOWS_NATIVE || defined OS2)

# if HAVE_LANGINFO_CODESET

  /* Most systems support nl_langinfo (CODESET) nowadays.  */
  codeset = nl_langinfo (CODESET);

#  ifdef __CYGWIN__
  /* Cygwin < 1.7 does not have locales.  nl_langinfo (CODESET) always
     returns "US-ASCII".  Return the suffix of the locale name from the
     environment variables (if present) or the codepage as a number.  */
  if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0)
    {
      const char *locale;
      static char buf[2 + 10 + 1];

      locale = getenv ("LC_ALL");
      if (locale == NULL || locale[0] == '\0')
        {
          locale = getenv ("LC_CTYPE");
          if (locale == NULL || locale[0] == '\0')
            locale = getenv ("LANG");
        }
      if (locale != NULL && locale[0] != '\0')
        {
          /* If the locale name contains an encoding after the dot, return
             it.  */
          const char *dot = strchr (locale, '.');

          if (dot != NULL)
            {
              const char *modifier;

              dot++;
              /* Look for the possible @... trailer and remove it, if any.  */
              modifier = strchr (dot, '@');
              if (modifier == NULL)
                return dot;
              if (modifier - dot < sizeof (buf))
                {
                  memcpy (buf, dot, modifier - dot);
                  buf [modifier - dot] = '\0';
                  return buf;
                }
            }
        }

      /* The Windows API has a function returning the locale's codepage as a
         number: GetACP().  This encoding is used by Cygwin, unless the user
         has set the environment variable CYGWIN=codepage:oem (which very few
         people do).
         Output directed to console windows needs to be converted (to
         GetOEMCP() if the console is using a raster font, or to
         GetConsoleOutputCP() if it is using a TrueType font).  Cygwin does
         this conversion transparently (see winsup/cygwin/fhandler_console.cc),
         converting to GetConsoleOutputCP().  This leads to correct results,
         except when SetConsoleOutputCP has been called and a raster font is
         in use.  */
      sprintf (buf, "CP%u", GetACP ());
      codeset = buf;
    }
#  endif

# else

  /* On old systems which lack it, use setlocale or getenv.  */
  const char *locale = NULL;

  /* But most old systems don't have a complete set of locales.  Some
     (like SunOS 4 or DJGPP) have only the C locale.  Therefore we don't
     use setlocale here; it would return "C" when it doesn't support the
     locale name the user has set.  */
#  if 0
  locale = setlocale (LC_CTYPE, NULL);
#  endif
  if (locale == NULL || locale[0] == '\0')
    {
      locale = getenv ("LC_ALL");
      if (locale == NULL || locale[0] == '\0')
        {
          locale = getenv ("LC_CTYPE");
          if (locale == NULL || locale[0] == '\0')
            locale = getenv ("LANG");
        }
    }

  /* On some old systems, one used to set locale = "iso8859_1". On others,
     you set it to "language_COUNTRY.charset". In any case, we resolve it
     through the charset.alias file.  */
  codeset = locale;

# endif

#elif defined WINDOWS_NATIVE

  static char buf[2 + 10 + 1];

  /* The Windows API has a function returning the locale's codepage as
     a number, but the value doesn't change according to what the
     'setlocale' call specified.  So we use it as a last resort, in
     case the string returned by 'setlocale' doesn't specify the
     codepage.  */
  char *current_locale = setlocale (LC_ALL, NULL);
  char *pdot;

  /* If they set different locales for different categories,
     'setlocale' will return a semi-colon separated list of locale
     values.  To make sure we use the correct one, we choose LC_CTYPE.  */
  if (strchr (current_locale, ';'))
    current_locale = setlocale (LC_CTYPE, NULL);

  pdot = strrchr (current_locale, '.');
  if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf))
    sprintf (buf, "CP%s", pdot + 1);
  else
    {
      /* The Windows API has a function returning the locale's codepage as a
        number: GetACP().
        When the output goes to a console window, it needs to be provided in
        GetOEMCP() encoding if the console is using a raster font, or in
        GetConsoleOutputCP() encoding if it is using a TrueType font.
        But in GUI programs and for output sent to files and pipes, GetACP()
        encoding is the best bet.  */
      sprintf (buf, "CP%u", GetACP ());
    }
  codeset = buf;

#elif defined OS2

  const char *locale;
  static char buf[2 + 10 + 1];
  ULONG cp[3];
  ULONG cplen;

  codeset = NULL;

  /* Allow user to override the codeset, as set in the operating system,
     with standard language environment variables.  */
  locale = getenv ("LC_ALL");
  if (locale == NULL || locale[0] == '\0')
    {
      locale = getenv ("LC_CTYPE");
      if (locale == NULL || locale[0] == '\0')
        locale = getenv ("LANG");
    }
  if (locale != NULL && locale[0] != '\0')
    {
      /* If the locale name contains an encoding after the dot, return it.  */
      const char *dot = strchr (locale, '.');

      if (dot != NULL)
        {
          const char *modifier;

          dot++;
          /* Look for the possible @... trailer and remove it, if any.  */
          modifier = strchr (dot, '@');
          if (modifier == NULL)
            return dot;
          if (modifier - dot < sizeof (buf))
            {
              memcpy (buf, dot, modifier - dot);
              buf [modifier - dot] = '\0';
              return buf;
            }
        }

      /* For the POSIX locale, don't use the system's codepage.  */
      if (strcmp (locale, "C") == 0 || strcmp (locale, "POSIX") == 0)
        codeset = "";
    }

  if (codeset == NULL)
    {
      /* OS/2 has a function returning the locale's codepage as a number.  */
      if (DosQueryCp (sizeof (cp), cp, &cplen))
        codeset = "";
      else
        {
          sprintf (buf, "CP%u", cp[0]);
          codeset = buf;
        }
    }

#endif

  if (codeset == NULL)
    /* The canonical name cannot be determined.  */
    codeset = "";

  /* Resolve alias. */
  for (aliases = get_charset_aliases ();
       *aliases != '\0';
       aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
    if (strcmp (codeset, aliases) == 0
        || (aliases[0] == '*' && aliases[1] == '\0'))
      {
        codeset = aliases + strlen (aliases) + 1;
        break;
      }

  /* Don't return an empty string.  GNU libc and GNU libiconv interpret
     the empty string as denoting "the locale's character encoding",
     thus GNU libiconv would call this function a second time.  */
  if (codeset[0] == '\0')
    codeset = "ASCII";

#ifdef DARWIN7
  /* Mac OS X sets MB_CUR_MAX to 1 when LC_ALL=C, and "UTF-8"
     (the default codeset) does not work when MB_CUR_MAX is 1.  */
  if (strcmp (codeset, "UTF-8") == 0 && MB_CUR_MAX_L (uselocale (NULL)) <= 1)
    codeset = "ASCII";
#endif

  return codeset;
}
Beispiel #30
0
/**
 * Add a message to a queue
 *
 * This function provides basic functionnalities to other msg_* functions.
 * It adds a message to a queue (after having printed all stored messages if it
 * is full). If the message can't be converted to string in memory, it issues
 * a warning.
 */
void msg_GenericVa (vlc_object_t *p_this, int i_type,
                           const char *psz_module,
                           const char *psz_format, va_list _args)
{
    size_t      i_header_size;             /* Size of the additionnal header */
    vlc_object_t *p_obj;
    char *       psz_str = NULL;                 /* formatted message string */
    char *       psz_header = NULL;
    va_list      args;

    assert (p_this);

    if( p_this->i_flags & OBJECT_FLAGS_QUIET ||
        (p_this->i_flags & OBJECT_FLAGS_NODBG && i_type == VLC_MSG_DBG) )
        return;

    msg_bank_t *bank = libvlc_bank (p_this->p_libvlc);
    locale_t locale = uselocale (bank->locale);

#ifndef __GLIBC__
    /* Expand %m to strerror(errno) - only once */
    char buf[strlen( psz_format ) + 2001], *ptr;
    strcpy( buf, psz_format );
    ptr = (char*)buf;
    psz_format = (const char*) buf;

    for( ;; )
    {
        ptr = strchr( ptr, '%' );
        if( ptr == NULL )
            break;

        if( ptr[1] == 'm' )
        {
            char errbuf[2001];
            size_t errlen;

#ifndef WIN32
            strerror_r( errno, errbuf, 1001 );
#else
            int sockerr = WSAGetLastError( );
            if( sockerr )
            {
                strncpy( errbuf, net_strerror( sockerr ), 1001 );
                WSASetLastError( sockerr );
            }
            if ((sockerr == 0)
             || (strcmp ("Unknown network stack error", errbuf) == 0))
                strncpy( errbuf, strerror( errno ), 1001 );
#endif
            errbuf[1000] = 0;

            /* Escape '%' from the error string */
            for( char *percent = strchr( errbuf, '%' );
                 percent != NULL;
                 percent = strchr( percent + 2, '%' ) )
            {
                memmove( percent + 1, percent, strlen( percent ) + 1 );
            }

            errlen = strlen( errbuf );
            memmove( ptr + errlen, ptr + 2, strlen( ptr + 2 ) + 1 );
            memcpy( ptr, errbuf, errlen );
            break; /* Only once, so we don't overflow */
        }

        /* Looks for conversion specifier... */
        do
            ptr++;
        while( *ptr && ( strchr( "diouxXeEfFgGaAcspn%", *ptr ) == NULL ) );
        if( *ptr )
            ptr++; /* ...and skip it */
    }
#endif

    /* Convert message to string  */
    vlc_va_copy( args, _args );
    if( vasprintf( &psz_str, psz_format, args ) == -1 )
        psz_str = NULL;
    va_end( args );

    if( psz_str == NULL )
    {
        int canc = vlc_savecancel (); /* Do not print half of a message... */
#ifdef __GLIBC__
        fprintf( stderr, "main warning: can't store message (%m): " );
#else
        char psz_err[1001];
#ifndef WIN32
        /* we're not using GLIBC, so we are sure that the error description
         * will be stored in the buffer we provide to strerror_r() */
        strerror_r( errno, psz_err, 1001 );
#else
        strncpy( psz_err, strerror( errno ), 1001 );
#endif
        psz_err[1000] = '\0';
        fprintf( stderr, "main warning: can't store message (%s): ", psz_err );
#endif
        vlc_va_copy( args, _args );
        /* We should use utf8_vfprintf - but it calls malloc()... */
        vfprintf( stderr, psz_format, args );
        va_end( args );
        fputs( "\n", stderr );
        vlc_restorecancel (canc);
        uselocale (locale);
        return;
    }
    uselocale (locale);

    msg_item_t * p_item = malloc (sizeof (*p_item));
    if (p_item == NULL)
        return; /* Uho! */

    vlc_gc_init (p_item, msg_Free);
    p_item->psz_module = p_item->psz_msg = p_item->psz_header = NULL;



    i_header_size = 0;
    p_obj = p_this;
    while( p_obj != NULL )
    {
        char *psz_old = NULL;
        if( p_obj->psz_header )
        {
            i_header_size += strlen( p_obj->psz_header ) + 4;
            if( psz_header )
            {
                psz_old = strdup( psz_header );
                psz_header = xrealloc( psz_header, i_header_size );
                snprintf( psz_header, i_header_size , "[%s] %s",
                          p_obj->psz_header, psz_old );
            }
            else
            {
                psz_header = xmalloc( i_header_size );
                snprintf( psz_header, i_header_size, "[%s]",
                          p_obj->psz_header );
            }
        }
        free( psz_old );
        p_obj = p_obj->p_parent;
    }

    /* Fill message information fields */
    p_item->i_type =        i_type;
    p_item->i_object_id =   (uintptr_t)p_this;
    p_item->psz_object_type = p_this->psz_object_type;
    p_item->psz_module =    strdup( psz_module );
    p_item->psz_msg =       psz_str;
    p_item->psz_header =    psz_header;

    PrintMsg( p_this, p_item );

    vlc_rwlock_rdlock (&bank->lock);
    for (int i = 0; i < bank->i_sub; i++)
    {
        msg_subscription_t *sub = bank->pp_sub[i];
        sub->func (sub->opaque, p_item, 0);
    }
    vlc_rwlock_unlock (&bank->lock);
    msg_Release (p_item);
}