<commit_before>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <miopen/config.h>
#include <miopen/env.hpp>
#include <miopen/errors.hpp>
#include <miopen/gcn_asm_utils.hpp>
#include <miopen/manage_ptr.hpp>
#include <miopen/write_file.hpp>
#include <miopen/kernel.hpp>
#include <miopen/logger.hpp>
#include <sstream>

#ifdef __linux__
#include <miopen/temp_file.hpp>

#include <paths.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#endif // __linux__

MIOPEN_DECLARE_ENV_VAR(MIOPEN_EXPERIMENTAL_GCN_ASM_PATH)

static std::string CleanupPath(const char* p);

// Redirecting both input and output is not supported.
static int ExecuteGcnAssembler(const std::string& p, std::istream* in, std::ostream* out);

std::string GetGcnAssemblerPathImpl()
{
    const auto asm_path_env_p = miopen::GetStringEnv(MIOPEN_EXPERIMENTAL_GCN_ASM_PATH{});
    if(asm_path_env_p != nullptr)
    {
        return CleanupPath(asm_path_env_p);
    }
#ifdef MIOPEN_AMDGCN_ASSEMBLER // string literal generated by CMake
    return CleanupPath(MIOPEN_AMDGCN_ASSEMBLER);
#else
    return "";
#endif
}

std::string GetGcnAssemblerPath()
{
    static const auto result = GetGcnAssemblerPathImpl();
    return result;
}

bool ValidateGcnAssemblerImpl()
{
#ifdef __linux__
    const auto path = GetGcnAssemblerPath();
    if(path.empty())
    {
        return false;
    }
    if(!std::ifstream(path).good())
    {
        return false;
    }

    std::stringstream clang_stdout;
    std::string clang_result_line;
    auto clang_rc = ExecuteGcnAssembler(path + " --version", nullptr, &clang_stdout);

    if(clang_rc != 0)
    {
        return false;
    }

    std::getline(clang_stdout, clang_result_line);
    if(clang_result_line.find("clang") != std::string::npos)
    {
        while(!clang_stdout.eof())
        {
            std::getline(clang_stdout, clang_result_line);
            if(clang_result_line.find("Target: ") != std::string::npos)
            {
                return clang_result_line.find("amdgcn") != std::string::npos;
            }
        }
    }
#endif // __linux__
    return false;
}

bool ValidateGcnAssembler()
{
    static bool result = ValidateGcnAssemblerImpl();
    return result;
}

static int ExecuteGcnAssembler(const std::string& p, std::istream* in, std::ostream* out)
{
#ifdef __linux__
    const auto redirect_stdin  = (in != nullptr);
    const auto redirect_stdout = (out != nullptr);

    assert(!(redirect_stdin && redirect_stdout));

    const auto file_mode = redirect_stdout ? "r" : "w";
    MIOPEN_MANAGE_PTR(FILE*, pclose) pipe{popen(p.c_str(), file_mode)};

    if(!pipe)
        MIOPEN_THROW("Error: X-AMDGCN-ASM: popen()");

    if(redirect_stdin || redirect_stdout)
    {
        std::array<char, 1024> buffer{};

        if(redirect_stdout)
        {
            while(feof(pipe.get()) == 0)
                if(fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
                    *out << buffer.data();
        }
        else
        {
            while(!in->eof())
            {
                in->read(buffer.data(), buffer.size() - 1);
                buffer[in->gcount()] = 0;

                if(fputs(buffer.data(), pipe.get()) == EOF)
                    MIOPEN_THROW("Error: X-AMDGCN-ASM: fputs()");
            }
        }
    }

    auto status = pclose(pipe.release());
    return WEXITSTATUS(status);
#else
    (void)p;
    (void)in;
    (void)out;
    return -1;
#endif // __linux__
}

static std::string CleanupPath(const char* p)
{
    std::string path(p);
    static const char bad[] = "!#$*;<>?@\\^`{|}";
    for(char* c = &path[0]; c < (&path[0] + path.length()); ++c)
    {
        if(std::iscntrl(*c) != 0)
        {
            *c = '_';
            continue;
        }
        for(const char* b = &bad[0]; b < (&bad[0] + sizeof(bad) - 1); ++b)
        {
            if(*b == *c)
            {
                *c = '_';
                break;
            }
        }
    }
    return path;
}

/*
 * Temporary function which emulates online assembly feature of OpenCL-on-ROCm being developed.
 * Not intended to be used in production code, so error handling is very straghtforward,
 * just catch whatever possible and throw an exception.
 */
void AmdgcnAssemble(std::string& source, const std::string& params)
{
#ifdef __linux__
    miopen::TempFile outfile("amdgcn-asm-out-XXXXXX");

    std::ostringstream workaround_options;
    if(GcnAssemblerHasBug34765())
    {
        GenerateClangDefsym(workaround_options, "WORKAROUND_BUG_34765", 1);
    }
    const auto args = " -x assembler -target amdgcn--amdhsa " + params + workaround_options.str() +
                      " - -o " + outfile.Path();

    std::istringstream clang_stdin(source);
    const auto clang_path = GetGcnAssemblerPath();
    const auto clang_rc   = ExecuteGcnAssembler(clang_path + " " + args, &clang_stdin, nullptr);
    if(clang_rc != 0)
        MIOPEN_THROW("Assembly error(" + std::to_string(clang_rc) + ")");

    std::ifstream file(outfile, std::ios::binary | std::ios::ate);
    bool outfile_read_failed = false;
    do
    {
        const auto size = file.tellg();
        if(size == -1)
        {
            outfile_read_failed = true;
            break;
        }
        source.resize(size, '\0');
        file.seekg(std::ios::beg);
        if(file.fail())
        {
            outfile_read_failed = true;
            break;
        }
        if(file.rdbuf()->sgetn(&source[0], size) != size)
        {
            outfile_read_failed = true;
            break;
        }
    } while(false);
    file.close();
    if(outfile_read_failed)
    {
        MIOPEN_THROW("Error: X-AMDGCN-ASM: outfile_read_failed");
    }
#else
    (void)source; // -warning
    (void)params; // -warning
    MIOPEN_THROW("Error: X-AMDGCN-ASM: online assembly under Windows is not supported");
#endif //__linux__
}

static void AmdgcnAssemble4BugDetection(std::string& source, const std::string& params)
{
#ifdef __linux__
    std::stringstream clang_stdout_unused;
    const auto clang_path = GetGcnAssemblerPath();
    const auto args       = " -x assembler -target amdgcn--amdhsa " + params + " " + source +
                      " 2>&1"; // Keep console clean from error messages.
    MIOPEN_LOG_I2(clang_path << " " << args);
    const int clang_rc =
        ExecuteGcnAssembler(clang_path + " " + args, nullptr, &clang_stdout_unused);
    if(clang_rc != 0)
        MIOPEN_THROW("Assembly error(" + std::to_string(clang_rc) + ")");
#else
    (void)source; // -warning
    (void)params; // -warning
    MIOPEN_THROW("Error: X-AMDGCN-ASM: online assembly under Windows is not supported");
#endif //__linux__
}

static bool GcnAssemblerHasBug34765Impl()
{
    auto p = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
    miopen::WriteFile(miopen::GetKernelSrc("bugzilla_34765_detect"), p);
    auto src = p.string();
    try
    {
        AmdgcnAssemble4BugDetection(src, "-mcpu=gfx900");
        return false;
    }
    catch(...)
    {
        MIOPEN_LOG_I("Detected");
        return true;
    }
}

bool GcnAssemblerHasBug34765()
{
    const static bool b = GcnAssemblerHasBug34765Impl();
    return b;
}

template <>
void GenerateClangDefsym<const std::string&>(std::ostream& stream,
                                             const std::string& name,
                                             const std::string& value)
{
    stream << " -Wa,-defsym," << name << "=" << value;
}

std::string MakeLutKey(int w, int h, int c, int n, int k, int u, int v, int dir, int CUs)
{
    std::ostringstream ss;
    ss << w << ";" << h << ";" << c << ";" << n << ";" << k << ";" << u << ";" << v << ";" << dir
       << ";" << CUs;
    return ss.str();
}

std::string MakeLutKey(int w, int h, int c, int n, int k, int dir, int CUs)
{
    return MakeLutKey(w, h, c, n, k, 1, 1, dir, CUs);
}
<commit_msg>fix-a-out(1) Assembly into /dev/null during bug detection.<commit_after>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <miopen/config.h>
#include <miopen/env.hpp>
#include <miopen/errors.hpp>
#include <miopen/gcn_asm_utils.hpp>
#include <miopen/manage_ptr.hpp>
#include <miopen/write_file.hpp>
#include <miopen/kernel.hpp>
#include <miopen/logger.hpp>
#include <sstream>

#ifdef __linux__
#include <miopen/temp_file.hpp>

#include <paths.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#endif // __linux__

MIOPEN_DECLARE_ENV_VAR(MIOPEN_EXPERIMENTAL_GCN_ASM_PATH)

static std::string CleanupPath(const char* p);

// Redirecting both input and output is not supported.
static int ExecuteGcnAssembler(const std::string& p, std::istream* in, std::ostream* out);

std::string GetGcnAssemblerPathImpl()
{
    const auto asm_path_env_p = miopen::GetStringEnv(MIOPEN_EXPERIMENTAL_GCN_ASM_PATH{});
    if(asm_path_env_p != nullptr)
    {
        return CleanupPath(asm_path_env_p);
    }
#ifdef MIOPEN_AMDGCN_ASSEMBLER // string literal generated by CMake
    return CleanupPath(MIOPEN_AMDGCN_ASSEMBLER);
#else
    return "";
#endif
}

std::string GetGcnAssemblerPath()
{
    static const auto result = GetGcnAssemblerPathImpl();
    return result;
}

bool ValidateGcnAssemblerImpl()
{
#ifdef __linux__
    const auto path = GetGcnAssemblerPath();
    if(path.empty())
    {
        return false;
    }
    if(!std::ifstream(path).good())
    {
        return false;
    }

    std::stringstream clang_stdout;
    std::string clang_result_line;
    auto clang_rc = ExecuteGcnAssembler(path + " --version", nullptr, &clang_stdout);

    if(clang_rc != 0)
    {
        return false;
    }

    std::getline(clang_stdout, clang_result_line);
    if(clang_result_line.find("clang") != std::string::npos)
    {
        while(!clang_stdout.eof())
        {
            std::getline(clang_stdout, clang_result_line);
            if(clang_result_line.find("Target: ") != std::string::npos)
            {
                return clang_result_line.find("amdgcn") != std::string::npos;
            }
        }
    }
#endif // __linux__
    return false;
}

bool ValidateGcnAssembler()
{
    static bool result = ValidateGcnAssemblerImpl();
    return result;
}

static int ExecuteGcnAssembler(const std::string& p, std::istream* in, std::ostream* out)
{
#ifdef __linux__
    const auto redirect_stdin  = (in != nullptr);
    const auto redirect_stdout = (out != nullptr);

    assert(!(redirect_stdin && redirect_stdout));

    const auto file_mode = redirect_stdout ? "r" : "w";
    MIOPEN_MANAGE_PTR(FILE*, pclose) pipe{popen(p.c_str(), file_mode)};

    if(!pipe)
        MIOPEN_THROW("Error: X-AMDGCN-ASM: popen()");

    if(redirect_stdin || redirect_stdout)
    {
        std::array<char, 1024> buffer{};

        if(redirect_stdout)
        {
            while(feof(pipe.get()) == 0)
                if(fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
                    *out << buffer.data();
        }
        else
        {
            while(!in->eof())
            {
                in->read(buffer.data(), buffer.size() - 1);
                buffer[in->gcount()] = 0;

                if(fputs(buffer.data(), pipe.get()) == EOF)
                    MIOPEN_THROW("Error: X-AMDGCN-ASM: fputs()");
            }
        }
    }

    auto status = pclose(pipe.release());
    return WEXITSTATUS(status);
#else
    (void)p;
    (void)in;
    (void)out;
    return -1;
#endif // __linux__
}

static std::string CleanupPath(const char* p)
{
    std::string path(p);
    static const char bad[] = "!#$*;<>?@\\^`{|}";
    for(char* c = &path[0]; c < (&path[0] + path.length()); ++c)
    {
        if(std::iscntrl(*c) != 0)
        {
            *c = '_';
            continue;
        }
        for(const char* b = &bad[0]; b < (&bad[0] + sizeof(bad) - 1); ++b)
        {
            if(*b == *c)
            {
                *c = '_';
                break;
            }
        }
    }
    return path;
}

/*
 * Temporary function which emulates online assembly feature of OpenCL-on-ROCm being developed.
 * Not intended to be used in production code, so error handling is very straghtforward,
 * just catch whatever possible and throw an exception.
 */
void AmdgcnAssemble(std::string& source, const std::string& params)
{
#ifdef __linux__
    miopen::TempFile outfile("amdgcn-asm-out-XXXXXX");

    std::ostringstream workaround_options;
    if(GcnAssemblerHasBug34765())
    {
        GenerateClangDefsym(workaround_options, "WORKAROUND_BUG_34765", 1);
    }
    const auto args = " -x assembler -target amdgcn--amdhsa " + params + workaround_options.str() +
                      " - -o " + outfile.Path();

    std::istringstream clang_stdin(source);
    const auto clang_path = GetGcnAssemblerPath();
    const auto clang_rc   = ExecuteGcnAssembler(clang_path + " " + args, &clang_stdin, nullptr);
    if(clang_rc != 0)
        MIOPEN_THROW("Assembly error(" + std::to_string(clang_rc) + ")");

    std::ifstream file(outfile, std::ios::binary | std::ios::ate);
    bool outfile_read_failed = false;
    do
    {
        const auto size = file.tellg();
        if(size == -1)
        {
            outfile_read_failed = true;
            break;
        }
        source.resize(size, '\0');
        file.seekg(std::ios::beg);
        if(file.fail())
        {
            outfile_read_failed = true;
            break;
        }
        if(file.rdbuf()->sgetn(&source[0], size) != size)
        {
            outfile_read_failed = true;
            break;
        }
    } while(false);
    file.close();
    if(outfile_read_failed)
    {
        MIOPEN_THROW("Error: X-AMDGCN-ASM: outfile_read_failed");
    }
#else
    (void)source; // -warning
    (void)params; // -warning
    MIOPEN_THROW("Error: X-AMDGCN-ASM: online assembly under Windows is not supported");
#endif //__linux__
}

static void AmdgcnAssemble4BugDetection(std::string& source, const std::string& params)
{
#ifdef __linux__
    std::stringstream clang_stdout_unused;
    const auto clang_path = GetGcnAssemblerPath();
    const auto args       = " -x assembler -target amdgcn--amdhsa " + params + " " + source +
                      " - -o /dev/null" + // We do not need output file
                      " 2>&1";            // Keep console clean from error messages.
    MIOPEN_LOG_I2(clang_path << " " << args);
    const int clang_rc =
        ExecuteGcnAssembler(clang_path + " " + args, nullptr, &clang_stdout_unused);
    if(clang_rc != 0)
        MIOPEN_THROW("Assembly error(" + std::to_string(clang_rc) + ")");
#else
    (void)source; // -warning
    (void)params; // -warning
    MIOPEN_THROW("Error: X-AMDGCN-ASM: online assembly under Windows is not supported");
#endif //__linux__
}

static bool GcnAssemblerHasBug34765Impl()
{
    auto p = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
    miopen::WriteFile(miopen::GetKernelSrc("bugzilla_34765_detect"), p);
    auto src = p.string();
    try
    {
        AmdgcnAssemble4BugDetection(src, "-mcpu=gfx900");
        return false;
    }
    catch(...)
    {
        MIOPEN_LOG_I("Detected");
        return true;
    }
}

bool GcnAssemblerHasBug34765()
{
    const static bool b = GcnAssemblerHasBug34765Impl();
    return b;
}

template <>
void GenerateClangDefsym<const std::string&>(std::ostream& stream,
                                             const std::string& name,
                                             const std::string& value)
{
    stream << " -Wa,-defsym," << name << "=" << value;
}

std::string MakeLutKey(int w, int h, int c, int n, int k, int u, int v, int dir, int CUs)
{
    std::ostringstream ss;
    ss << w << ";" << h << ";" << c << ";" << n << ";" << k << ";" << u << ";" << v << ";" << dir
       << ";" << CUs;
    return ss.str();
}

std::string MakeLutKey(int w, int h, int c, int n, int k, int dir, int CUs)
{
    return MakeLutKey(w, h, c, n, k, 1, 1, dir, CUs);
}
<|endoftext|>


<commit_before>/** @file iterativeSolvers.cpp

    @brief Example on how the solve a system of linear equation with the MINRES, GMRes and CG method.

    This file is part of the G+Smo library.

    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/.

    Author(s): J. Sogn
*/

#include <iostream>
#include <gismo.h>

using namespace gismo;

//Create a tri-diagonal matrix with -1 of the off diagonals and 2 in the diagonal.
//This matrix is equivalent to discretizing the 1D Poisson equation with homogenius
//Dirichlet boundary condition using a finite difference method. It is a SPD matrix.
//The solution is sin(pi*x);
void poissonDiscretization(gsSparseMatrix<> &mat, gsMatrix<> &rhs, index_t N)
{
    rhs.setZero(N,1);

    mat.resize(N,N);
    mat.setZero();
    real_t meshSize = 1./(N+1);
    real_t pi = M_PI;

    //Reserving space in the sparse matrix (Speeds up the assemble time of the matrix)
    gsVector<int> reserve = gsVector<int>::Constant(N,3);//Reserve 3 non-zero entry per column
    mat.reserve( reserve );

    mat(0,0) = 2;
    mat(0,1) = -1;
    mat(N-1, N-1) = 2;
    mat(N-1, N-2) = -1;
    for (index_t k = 1; k < N-1; ++k)
    {
        mat(k,k) = 2;
        mat(k,k-1) = -1;
        mat(k,k+1) = -1;
    }
    for (index_t k = 0; k < N; ++k)
    {
        rhs(k,0) = pi*pi*meshSize*meshSize*math::cos(meshSize*(1+k)*pi);
    }

    //Compress the matrix
    mat.makeCompressed();
}

//Print out information of the iterative solver
void gsIterativeSolverInfo(const gsIterativeSolver &method, std::string methodName, real_t time)
{
    gsInfo << methodName +": System size         : " << method.size() << "\n";
    gsInfo << methodName +": Tolerance           : " << method.tolerance() << "\n";
    gsInfo << methodName +": Residual error      : " << method.error() << "\n";
    gsInfo << methodName +": Number of iterations: " << method.iterations() << "\n";
    gsInfo << methodName +": Time to solve:      : " << time << "\n";
}

int main(int argc, char *argv[])
{
    //Size of linear system
    index_t N = 200;
    if (argc >= 2)
        N = atoi(argv[1]);

    gsSparseMatrix<> mat;
    gsMatrix<>       rhs;

    //Assemble the 1D Poisson equation
    poissonDiscretization(mat, rhs, N);

    //The minimal residual implementation requires a preconditioner.
    //We initialize an identity preconditioner (does nothing).
    gsIdentityPreconditioner preConMat(N);

    //Maximum number of iterations
    index_t maxIters = 3*N;
    //Tolerance
    real_t tol = math::pow(10.0, - REAL_DIG * 0.75);

    ///----------------------GISMO-SOLVERS----------------------///
    gsInfo << "Testing G+Smo's solvers:\n";

    //Initialize the MinRes solver
    gsMinimalResidual MinRes(mat,maxIters,tol);

    //Create the initial guess
    gsMatrix<> x0;
    x0.setZero(N,1);

    //Solve system with given preconditioner (solution is stored in x0)
    gsInfo << "\nMinRes: Started solving..."  << "\n";
    gsStopwatch clock;
    MinRes.solve(rhs,x0,preConMat);
    gsIterativeSolverInfo(MinRes, "MinRes", clock.stop());

    //Initialize the CG solver
    gsGMRes GMResSolver(mat,maxIters,tol);

    //Set the initial guess to zero
    x0.setZero(N,1);

    if (N < 200)
    {
        //Solve system with given preconditioner (solution is stored in x0)
        gsInfo << "\nGMRes: Started solving..."  << "\n";
        clock.restart();
        GMResSolver.solve(rhs,x0,preConMat);
        gsIterativeSolverInfo(GMResSolver, "GMRes", clock.stop());
    }
    else
        gsInfo << "\nSkipping GMRes due to high number of iterations...\n";

    //Initialize the CG solver
    gsConjugateGradient CGSolver(mat,maxIters,tol);

    //Set the initial guess to zero
    x0.setZero(N,1);

    //Solve system with given preconditioner (solution is stored in x0)
    gsInfo << "\nCG: Started solving..."  << "\n";
    clock.restart();
    CGSolver.solve(rhs,x0,preConMat);
    gsIterativeSolverInfo(CGSolver, "CG", clock.stop());

    ///----------------------EIGEN-ITERATIVE-SOLVERS----------------------///
    gsInfo << "Testing Eigen's interative solvers:\n";

    gsSparseSolver<>::CGIdentity EigenCGIsolver;
    EigenCGIsolver.setMaxIterations(maxIters);
    EigenCGIsolver.setTolerance(tol);
    gsInfo << "\nEigen's CG identity preconditioner: Started solving..."  << "\n";
    clock.restart();
    EigenCGIsolver.compute(mat);
    x0 = EigenCGIsolver.solve(rhs);
    gsInfo << "Eigen's CG: Tolerance           : " << EigenCGIsolver.tolerance() << "\n";
    gsInfo << "Eigen's CG: Residual error      : " << EigenCGIsolver.error() << "\n";
    gsInfo << "Eigen's CG: Number of iterations: " << EigenCGIsolver.iterations() << "\n";
    gsInfo << "Eigen's CG: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::CGDiagonal EigenCGDsolver;
    EigenCGDsolver.setMaxIterations(maxIters);
    EigenCGDsolver.setTolerance(tol);
    gsInfo << "\nEigen's CG diagonal preconditioner: Started solving..."  << "\n";
    clock.restart();
    EigenCGDsolver.compute(mat);
    x0 = EigenCGDsolver.solve(rhs);
    gsInfo << "Eigen's CG: Tolerance           : " << EigenCGDsolver.tolerance() << "\n";
    gsInfo << "Eigen's CG: Residual error      : " << EigenCGDsolver.error() << "\n";
    gsInfo << "Eigen's CG: Number of iterations: " << EigenCGDsolver.iterations() << "\n";
    gsInfo << "Eigen's CG: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::BiCGSTABIdentity EigenBCGIsolver;
    EigenBCGIsolver.setMaxIterations(maxIters);
    EigenBCGIsolver.setTolerance(tol);
    gsInfo << "\nEigen's bi conjugate gradient stabilized solver identity preconditioner: Started solving..."  << "\n";
    clock.restart();
    EigenBCGIsolver.compute(mat);
    x0 = EigenBCGIsolver.solve(rhs);
    gsInfo << "Eigen's BiCGSTAB: Tolerance           : " << EigenBCGIsolver.tolerance() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Residual error      : " << EigenBCGIsolver.error() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Number of iterations: " << EigenBCGIsolver.iterations() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::BiCGSTABDiagonal EigenBCGDsolver;
    EigenBCGDsolver.setMaxIterations(maxIters);
    EigenBCGDsolver.setTolerance(tol);
    gsInfo << "\nEigen's bi conjugate gradient stabilized solver diagonal preconditioner: Started solving..."  << "\n";
    clock.restart();
    EigenBCGDsolver.compute(mat);
    x0 = EigenBCGDsolver.solve(rhs);
    gsInfo << "Eigen's BiCGSTAB: Tolerance           : " << EigenBCGDsolver.tolerance() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Residual error      : " << EigenBCGDsolver.error() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Number of iterations: " << EigenBCGDsolver.iterations() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::BiCGSTABILUT EigenBCGILUsolver;
    //EigenBCGILUsolver.preconditioner().setFillfactor(1);
    EigenBCGILUsolver.setMaxIterations(maxIters);
    EigenBCGILUsolver.setTolerance(tol);
    gsInfo << "\nEigen's bi conjugate gradient stabilized solver ILU preconditioner: Started solving..."  << "\n";
    clock.restart();
    EigenBCGILUsolver.compute(mat);
    x0 = EigenBCGILUsolver.solve(rhs);
    gsInfo << "Eigen's BiCGSTAB: Tolerance           : " << EigenBCGILUsolver.tolerance() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Residual error      : " << EigenBCGILUsolver.error() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Number of iterations: " << EigenBCGILUsolver.iterations() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Time to solve       : " << clock.stop() << "\n";

    ///----------------------EIGEN-DIRECT-SOLVERS----------------------///
    gsSparseSolver<>::SimplicialLDLT EigenSLDLTsolver;
    gsInfo << "\nEigen's Simplicial LDLT: Started solving..."  << "\n";
    clock.restart();
    EigenSLDLTsolver.compute(mat);
    x0 = EigenSLDLTsolver.solve(rhs);
    gsInfo << "Eigen's Simplicial LDLT: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::QR solverQR;
    gsInfo << "\nEigen's QR: Started solving..."  << "\n";
    clock.restart();
    solverQR.compute(mat);
    x0 = solverQR.solve(rhs);
    gsInfo << "Eigen's QR: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::LU solverLU;
    gsInfo << "\nEigen's LU: Started solving..."  << "\n";
    clock.restart();
    solverLU.compute(mat);
    x0 = solverLU.solve(rhs);
    gsInfo << "Eigen's LU: Time to solve       : " << clock.stop() << "\n";

    return 0;
}
<commit_msg>Changed default value such that the GMRes will run<commit_after>/** @file iterativeSolvers.cpp

    @brief Example on how the solve a system of linear equation with the MINRES, GMRes and CG method.

    This file is part of the G+Smo library.

    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/.

    Author(s): J. Sogn
*/

#include <iostream>
#include <gismo.h>

using namespace gismo;

//Create a tri-diagonal matrix with -1 of the off diagonals and 2 in the diagonal.
//This matrix is equivalent to discretizing the 1D Poisson equation with homogenius
//Dirichlet boundary condition using a finite difference method. It is a SPD matrix.
//The solution is sin(pi*x);
void poissonDiscretization(gsSparseMatrix<> &mat, gsMatrix<> &rhs, index_t N)
{
    rhs.setZero(N,1);

    mat.resize(N,N);
    mat.setZero();
    real_t meshSize = 1./(N+1);
    real_t pi = M_PI;

    //Reserving space in the sparse matrix (Speeds up the assemble time of the matrix)
    gsVector<int> reserve = gsVector<int>::Constant(N,3);//Reserve 3 non-zero entry per column
    mat.reserve( reserve );

    mat(0,0) = 2;
    mat(0,1) = -1;
    mat(N-1, N-1) = 2;
    mat(N-1, N-2) = -1;
    for (index_t k = 1; k < N-1; ++k)
    {
        mat(k,k) = 2;
        mat(k,k-1) = -1;
        mat(k,k+1) = -1;
    }
    for (index_t k = 0; k < N; ++k)
    {
        rhs(k,0) = pi*pi*meshSize*meshSize*math::cos(meshSize*(1+k)*pi);
    }

    //Compress the matrix
    mat.makeCompressed();
}

//Print out information of the iterative solver
void gsIterativeSolverInfo(const gsIterativeSolver &method, std::string methodName, real_t time)
{
    gsInfo << methodName +": System size         : " << method.size() << "\n";
    gsInfo << methodName +": Tolerance           : " << method.tolerance() << "\n";
    gsInfo << methodName +": Residual error      : " << method.error() << "\n";
    gsInfo << methodName +": Number of iterations: " << method.iterations() << "\n";
    gsInfo << methodName +": Time to solve:      : " << time << "\n";
}

int main(int argc, char *argv[])
{
    //Size of linear system
    index_t N = 100;
    if (argc >= 2)
        N = atoi(argv[1]);

    gsSparseMatrix<> mat;
    gsMatrix<>       rhs;

    //Assemble the 1D Poisson equation
    poissonDiscretization(mat, rhs, N);

    //The minimal residual implementation requires a preconditioner.
    //We initialize an identity preconditioner (does nothing).
    gsIdentityPreconditioner preConMat(N);

    //Maximum number of iterations
    index_t maxIters = 3*N;
    //Tolerance
    real_t tol = math::pow(10.0, - REAL_DIG * 0.75);

    ///----------------------GISMO-SOLVERS----------------------///
    gsInfo << "Testing G+Smo's solvers:\n";

    //Initialize the MinRes solver
    gsMinimalResidual MinRes(mat,maxIters,tol);

    //Create the initial guess
    gsMatrix<> x0;
    x0.setZero(N,1);

    //Solve system with given preconditioner (solution is stored in x0)
    gsInfo << "\nMinRes: Started solving..."  << "\n";
    gsStopwatch clock;
    MinRes.solve(rhs,x0,preConMat);
    gsIterativeSolverInfo(MinRes, "MinRes", clock.stop());

    //Initialize the CG solver
    gsGMRes GMResSolver(mat,maxIters,tol);

    //Set the initial guess to zero
    x0.setZero(N,1);

    if (N < 200)
    {
        //Solve system with given preconditioner (solution is stored in x0)
        gsInfo << "\nGMRes: Started solving..."  << "\n";
        clock.restart();
        GMResSolver.solve(rhs,x0,preConMat);
        gsIterativeSolverInfo(GMResSolver, "GMRes", clock.stop());
    }
    else
        gsInfo << "\nSkipping GMRes due to high number of iterations...\n";

    //Initialize the CG solver
    gsConjugateGradient CGSolver(mat,maxIters,tol);

    //Set the initial guess to zero
    x0.setZero(N,1);

    //Solve system with given preconditioner (solution is stored in x0)
    gsInfo << "\nCG: Started solving..."  << "\n";
    clock.restart();
    CGSolver.solve(rhs,x0,preConMat);
    gsIterativeSolverInfo(CGSolver, "CG", clock.stop());

    ///----------------------EIGEN-ITERATIVE-SOLVERS----------------------///
    gsInfo << "Testing Eigen's interative solvers:\n";

    gsSparseSolver<>::CGIdentity EigenCGIsolver;
    EigenCGIsolver.setMaxIterations(maxIters);
    EigenCGIsolver.setTolerance(tol);
    gsInfo << "\nEigen's CG identity preconditioner: Started solving..."  << "\n";
    clock.restart();
    EigenCGIsolver.compute(mat);
    x0 = EigenCGIsolver.solve(rhs);
    gsInfo << "Eigen's CG: Tolerance           : " << EigenCGIsolver.tolerance() << "\n";
    gsInfo << "Eigen's CG: Residual error      : " << EigenCGIsolver.error() << "\n";
    gsInfo << "Eigen's CG: Number of iterations: " << EigenCGIsolver.iterations() << "\n";
    gsInfo << "Eigen's CG: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::CGDiagonal EigenCGDsolver;
    EigenCGDsolver.setMaxIterations(maxIters);
    EigenCGDsolver.setTolerance(tol);
    gsInfo << "\nEigen's CG diagonal preconditioner: Started solving..."  << "\n";
    clock.restart();
    EigenCGDsolver.compute(mat);
    x0 = EigenCGDsolver.solve(rhs);
    gsInfo << "Eigen's CG: Tolerance           : " << EigenCGDsolver.tolerance() << "\n";
    gsInfo << "Eigen's CG: Residual error      : " << EigenCGDsolver.error() << "\n";
    gsInfo << "Eigen's CG: Number of iterations: " << EigenCGDsolver.iterations() << "\n";
    gsInfo << "Eigen's CG: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::BiCGSTABIdentity EigenBCGIsolver;
    EigenBCGIsolver.setMaxIterations(maxIters);
    EigenBCGIsolver.setTolerance(tol);
    gsInfo << "\nEigen's bi conjugate gradient stabilized solver identity preconditioner: Started solving..."  << "\n";
    clock.restart();
    EigenBCGIsolver.compute(mat);
    x0 = EigenBCGIsolver.solve(rhs);
    gsInfo << "Eigen's BiCGSTAB: Tolerance           : " << EigenBCGIsolver.tolerance() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Residual error      : " << EigenBCGIsolver.error() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Number of iterations: " << EigenBCGIsolver.iterations() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::BiCGSTABDiagonal EigenBCGDsolver;
    EigenBCGDsolver.setMaxIterations(maxIters);
    EigenBCGDsolver.setTolerance(tol);
    gsInfo << "\nEigen's bi conjugate gradient stabilized solver diagonal preconditioner: Started solving..."  << "\n";
    clock.restart();
    EigenBCGDsolver.compute(mat);
    x0 = EigenBCGDsolver.solve(rhs);
    gsInfo << "Eigen's BiCGSTAB: Tolerance           : " << EigenBCGDsolver.tolerance() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Residual error      : " << EigenBCGDsolver.error() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Number of iterations: " << EigenBCGDsolver.iterations() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::BiCGSTABILUT EigenBCGILUsolver;
    //EigenBCGILUsolver.preconditioner().setFillfactor(1);
    EigenBCGILUsolver.setMaxIterations(maxIters);
    EigenBCGILUsolver.setTolerance(tol);
    gsInfo << "\nEigen's bi conjugate gradient stabilized solver ILU preconditioner: Started solving..."  << "\n";
    clock.restart();
    EigenBCGILUsolver.compute(mat);
    x0 = EigenBCGILUsolver.solve(rhs);
    gsInfo << "Eigen's BiCGSTAB: Tolerance           : " << EigenBCGILUsolver.tolerance() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Residual error      : " << EigenBCGILUsolver.error() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Number of iterations: " << EigenBCGILUsolver.iterations() << "\n";
    gsInfo << "Eigen's BiCGSTAB: Time to solve       : " << clock.stop() << "\n";

    ///----------------------EIGEN-DIRECT-SOLVERS----------------------///
    gsSparseSolver<>::SimplicialLDLT EigenSLDLTsolver;
    gsInfo << "\nEigen's Simplicial LDLT: Started solving..."  << "\n";
    clock.restart();
    EigenSLDLTsolver.compute(mat);
    x0 = EigenSLDLTsolver.solve(rhs);
    gsInfo << "Eigen's Simplicial LDLT: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::QR solverQR;
    gsInfo << "\nEigen's QR: Started solving..."  << "\n";
    clock.restart();
    solverQR.compute(mat);
    x0 = solverQR.solve(rhs);
    gsInfo << "Eigen's QR: Time to solve       : " << clock.stop() << "\n";

    gsSparseSolver<>::LU solverLU;
    gsInfo << "\nEigen's LU: Started solving..."  << "\n";
    clock.restart();
    solverLU.compute(mat);
    x0 = solverLU.solve(rhs);
    gsInfo << "Eigen's LU: Time to solve       : " << clock.stop() << "\n";

    return 0;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtMultimedia module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "player.h"

#include "playlistmodel.h"

#include <qmediaplayer.h>
#include <qmediaplaylist.h>
#include <qmediametadata.h>
#include <qabstractmediaservice.h>

#include "qmediawidgetendpoint.h"

#include <QtGui>

Player::Player(QWidget *parent)
    : QWidget(parent)
    , slider(0)
{
    player = new QMediaPlayer;
    metaData = new QMediaMetadata(player);

    connect(player, SIGNAL(durationChanged(qint64)), SLOT(durationChanged(qint64)));
    connect(player, SIGNAL(positionChanged(qint64)), SLOT(positionChanged(qint64)));
    connect(player, SIGNAL(playlistPositionChanged(int)), SLOT(playlistPositionChanged(int)));
    connect(metaData, SIGNAL(metadataAvailabilityChanged(bool)), SLOT(metadataAvailabilityChanged(bool)));

    QWidget *videoWidget = player->service()->createEndpoint<QMediaWidgetEndpoint *>();

    if (videoWidget) {
        qDebug() << "service supports video widgets, nice";
        player->service()->setVideoOutput(videoWidget);
    }

    playlistModel = new PlaylistModel(this);
    playlistModel->setPlaylist(player->mediaPlaylist());

    playlistView = new QTableView;
    playlistView->setModel(playlistModel);

    connect(playlistView, SIGNAL(activated(QModelIndex)), this, SLOT(jump(QModelIndex)));

    slider = new QSlider(Qt::Horizontal);
    slider->setRange(0, 0);

    connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(seek(int)));

    QPushButton *openButton = new QPushButton(tr("Open"));
    connect(openButton, SIGNAL(clicked()), this, SLOT(open()));

    QPushButton *playButton = new QPushButton(tr("Play"));
    connect(playButton, SIGNAL(clicked()), player, SLOT(play()));

    QPushButton *pauseButton = new QPushButton(tr("Pause"));
    connect(pauseButton, SIGNAL(clicked()), player, SLOT(pause()));

    QPushButton *stopButton = new QPushButton(tr("Stop"));
    connect(stopButton, SIGNAL(clicked()), player, SLOT(stop()));

    QPushButton *advanceButton = new QPushButton(tr("Advance"));
    connect(advanceButton, SIGNAL(clicked()), player, SLOT(advance()));

    QPushButton *backButton = new QPushButton(tr("Back"));
    connect(backButton, SIGNAL(clicked()), player, SLOT(back()));

    QLabel *volumeLabel = new QLabel(tr("Volume"));

    QSlider *volumeSlider = new QSlider(Qt::Horizontal);
    volumeSlider->setRange(0, 100);
    volumeSlider->setValue(player->volume());
    connect(volumeSlider, SIGNAL(valueChanged(int)), player, SLOT(setVolume(int)));

    QPushButton *muteButton = new QPushButton(tr("Mute"));
    muteButton->setCheckable(true);
    muteButton->setChecked(player->isMuted());
    connect(muteButton, SIGNAL(clicked(bool)), player, SLOT(setMuted(bool)));

    QBoxLayout *controlLayout = new QHBoxLayout;
    controlLayout->setMargin(0);
    controlLayout->addWidget(openButton);
    controlLayout->addWidget(playButton);
    controlLayout->addWidget(pauseButton);
    controlLayout->addWidget(stopButton);
    controlLayout->addWidget(volumeLabel);
    controlLayout->addWidget(volumeSlider);
    controlLayout->addWidget(muteButton);
    controlLayout->addWidget(backButton);
    controlLayout->addWidget(advanceButton);

    QBoxLayout *layout = new QVBoxLayout;
    if (videoWidget) {
        QSplitter *splitter = new QSplitter(Qt::Vertical);

        splitter->addWidget(videoWidget);
        splitter->addWidget(playlistView);

        /*
        connect(player, SIGNAL(videoAvailabilityChanged(bool)), videoWidget, SLOT(setVisible(bool)));
        videoWidget->setMinimumSize(64,64);
        videoWidget->setVisible(false);*/

        layout->addWidget(splitter);
    } else {
        layout->addWidget(playlistView);
    }
    layout->addWidget(slider);
    layout->addLayout(controlLayout);

    setLayout(layout);
}

Player::~Player()
{
    delete player;
}

void Player::open()
{
    QString fileName = QFileDialog::getOpenFileName();

    if (!fileName.isNull()) {
        player->mediaPlaylist()->append(QMediaSource("", QLatin1String("file:///") + fileName));
    }
}

void Player::durationChanged(qint64 duration)
{
    slider->setMaximum(duration / 1000);
}

void Player::positionChanged(qint64 progress)
{
    slider->setValue(progress / 1000);
}

void Player::metadataAvailabilityChanged(bool available)
{
	if (available)
		setWindowTitle(QString("%1 - %2").arg(metaData->metadata(QLatin1String("Artist")).toString()).
                                          arg(metaData->metadata(QLatin1String("Title")).toString()));
}

void Player::jump(const QModelIndex &index)
{
    if (index.isValid()) {
        player->setPlaylistPosition(index.row());
    }
}

void Player::playlistPositionChanged(int currentItem)
{
    playlistView->setCurrentIndex(playlistModel->index(currentItem,0));
}

void Player::seek(int seconds)
{
    player->setPosition(seconds*1000);
}
<commit_msg>Connect to player for volume related changes.<commit_after>/****************************************************************************
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtMultimedia module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "player.h"

#include "playlistmodel.h"

#include <qmediaplayer.h>
#include <qmediaplaylist.h>
#include <qmediametadata.h>
#include <qabstractmediaservice.h>

#include "qmediawidgetendpoint.h"

#include <QtGui>

Player::Player(QWidget *parent)
    : QWidget(parent)
    , slider(0)
{
    player = new QMediaPlayer;
    metaData = new QMediaMetadata(player);

    connect(player, SIGNAL(durationChanged(qint64)), SLOT(durationChanged(qint64)));
    connect(player, SIGNAL(positionChanged(qint64)), SLOT(positionChanged(qint64)));
    connect(player, SIGNAL(playlistPositionChanged(int)), SLOT(playlistPositionChanged(int)));
    connect(metaData, SIGNAL(metadataAvailabilityChanged(bool)), SLOT(metadataAvailabilityChanged(bool)));

    QWidget *videoWidget = player->service()->createEndpoint<QMediaWidgetEndpoint *>();

    if (videoWidget) {
        qDebug() << "service supports video widgets, nice";
        player->service()->setVideoOutput(videoWidget);
    }

    playlistModel = new PlaylistModel(this);
    playlistModel->setPlaylist(player->mediaPlaylist());

    playlistView = new QTableView;
    playlistView->setModel(playlistModel);

    connect(playlistView, SIGNAL(activated(QModelIndex)), this, SLOT(jump(QModelIndex)));

    slider = new QSlider(Qt::Horizontal);
    slider->setRange(0, 0);

    connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(seek(int)));

    QPushButton *openButton = new QPushButton(tr("Open"));
    connect(openButton, SIGNAL(clicked()), this, SLOT(open()));

    QPushButton *playButton = new QPushButton(tr("Play"));
    connect(playButton, SIGNAL(clicked()), player, SLOT(play()));

    QPushButton *pauseButton = new QPushButton(tr("Pause"));
    connect(pauseButton, SIGNAL(clicked()), player, SLOT(pause()));

    QPushButton *stopButton = new QPushButton(tr("Stop"));
    connect(stopButton, SIGNAL(clicked()), player, SLOT(stop()));

    QPushButton *advanceButton = new QPushButton(tr("Advance"));
    connect(advanceButton, SIGNAL(clicked()), player, SLOT(advance()));

    QPushButton *backButton = new QPushButton(tr("Back"));
    connect(backButton, SIGNAL(clicked()), player, SLOT(back()));

    QLabel *volumeLabel = new QLabel(tr("Volume"));

    QSlider *volumeSlider = new QSlider(Qt::Horizontal);
    volumeSlider->setRange(0, 100);
    volumeSlider->setValue(player->volume());
    connect(volumeSlider, SIGNAL(valueChanged(int)), player, SLOT(setVolume(int)));
    connect(player, SIGNAL(volumeChanged(int)), volumeSlider, SLOT(setValue(int)));

    QPushButton *muteButton = new QPushButton(tr("Mute"));
    muteButton->setCheckable(true);
    muteButton->setChecked(player->isMuted());
    connect(muteButton, SIGNAL(clicked(bool)), player, SLOT(setMuted(bool)));
    connect(player, SIGNAL(mutingChanged(bool)), muteButton, SLOT(setChecked(bool)));

    QBoxLayout *controlLayout = new QHBoxLayout;
    controlLayout->setMargin(0);
    controlLayout->addWidget(openButton);
    controlLayout->addWidget(playButton);
    controlLayout->addWidget(pauseButton);
    controlLayout->addWidget(stopButton);
    controlLayout->addWidget(volumeLabel);
    controlLayout->addWidget(volumeSlider);
    controlLayout->addWidget(muteButton);
    controlLayout->addWidget(backButton);
    controlLayout->addWidget(advanceButton);

    QBoxLayout *layout = new QVBoxLayout;
    if (videoWidget) {
        QSplitter *splitter = new QSplitter(Qt::Vertical);

        splitter->addWidget(videoWidget);
        splitter->addWidget(playlistView);

        /*
        connect(player, SIGNAL(videoAvailabilityChanged(bool)), videoWidget, SLOT(setVisible(bool)));
        videoWidget->setMinimumSize(64,64);
        videoWidget->setVisible(false);*/

        layout->addWidget(splitter);
    } else {
        layout->addWidget(playlistView);
    }
    layout->addWidget(slider);
    layout->addLayout(controlLayout);

    setLayout(layout);
}

Player::~Player()
{
    delete player;
}

void Player::open()
{
    QString fileName = QFileDialog::getOpenFileName();

    if (!fileName.isNull()) {
        player->mediaPlaylist()->append(QMediaSource("", QLatin1String("file:///") + fileName));
    }
}

void Player::durationChanged(qint64 duration)
{
    slider->setMaximum(duration / 1000);
}

void Player::positionChanged(qint64 progress)
{
    slider->setValue(progress / 1000);
}

void Player::metadataAvailabilityChanged(bool available)
{
	if (available)
		setWindowTitle(QString("%1 - %2").arg(metaData->metadata(QLatin1String("Artist")).toString()).
                                          arg(metaData->metadata(QLatin1String("Title")).toString()));
}

void Player::jump(const QModelIndex &index)
{
    if (index.isValid()) {
        player->setPlaylistPosition(index.row());
    }
}

void Player::playlistPositionChanged(int currentItem)
{
    playlistView->setCurrentIndex(playlistModel->index(currentItem,0));
}

void Player::seek(int seconds)
{
    player->setPosition(seconds*1000);
}
<|endoftext|>


<commit_before>/* bzflag
* Copyright (c) 1993 - 2009 Tim Riker
* Written By Dave Rodgers (aka: trepan)
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#include "common.h"

// there is no 'implementation header'

// common headers
#include "bzfgl.h"
#include "bzfio.h"

/////////////////////////
#define UNSAFE_GL_CONTEXT
/////////////////////////
#include "OpenGLGState.h"

//============================================================================//
//============================================================================//
//
//  for hooking debuggers
//

static void contextFreeError(const char* message)
{
  printf("contextFreeError(): %s\n", message);
}

static void contextInitError(const char* message)
{
  printf("contextInitError(): %s\n", message);
}

//============================================================================//
//============================================================================//
//
//  Display Lists
//

void bzNewList(GLuint list, GLenum mode)
{
  glNewList(list, mode);
  return;
}

GLuint bzGenLists(GLsizei count)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzGenLists() is having issues");
  }
  GLuint base = glGenLists(count);
  return base;
}

void bzDeleteLists(GLuint base, GLsizei count)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteLists() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteLists(base, count);
  } else {
    logDebugMessage(4,"bzDeleteLists(), no context\n");
  }
  return;
}

//============================================================================//
//============================================================================//
//
//  Textures
//

void bzGenTextures(GLsizei count, GLuint *textures)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzGenTextures() is having issues");
  }
  glGenTextures(count, textures);
  return;
}

void bzDeleteTextures(GLsizei count, const GLuint *textures)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteTextures() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteTextures(count, textures);
  } else {
    logDebugMessage(4,"bzDeleteTextures(), no context\n");
  }
  return;
}

//============================================================================//
//============================================================================//
//
//  Shaders
//

GLuint bzCreateShader(GLenum type)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzCreateShader() is having issues");
  }
  return glCreateShader(type);
}

void bzDeleteShader(GLuint shader)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteShader() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteShader(shader);
  } else {
    logDebugMessage(4,"bzDeleteShader(), no context\n");
  }
}

GLuint bzCreateProgram()
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzCreateProgram() is having issues");
  }
  return glCreateProgram();
}

void bzDeleteProgram(GLuint program)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteProgram() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteProgram(program);
  } else {
    logDebugMessage(4,"bzDeleteProgram(), no context\n");
  }
}

//============================================================================//
//============================================================================//
//
//  Occlusion Queries
//

void bzGenQueries(GLsizei n, GLuint* queries)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzGenQueries() is having issues");
  }
  glGenQueries(n, queries);
}

void bzDeleteQueries(GLsizei n, const GLuint* queries)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteProgram() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteQueries(n, queries);
  } else {
    logDebugMessage(4,"bzDeleteQueries(), no context\n");
  }
}

//============================================================================//
//============================================================================//
//
//  Frame Buffers
//

void bzGenFramebuffersEXT(GLsizei n, GLuint* fbos)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzGenFramebuffersEXT() is having issues");
  }
  glGenFramebuffersEXT(n, fbos);
}

void bzDeleteFramebuffersEXT(GLsizei n, const GLuint* fbos)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteFramebuffersEXT() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteFramebuffersEXT(n, fbos);
  } else {
    logDebugMessage(4,"bzDeleteFramebuffersEXT(), no context\n");
  }
}

//============================================================================//
//============================================================================//
//
//  Render Buffers
//

void bzGenRenderbuffersEXT(GLsizei n, GLuint* rbos)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzGenRenderbuffersEXT() is having issues");
  }
  glGenRenderbuffersEXT(n, rbos);
}

void bzDeleteRenderbuffersEXT(GLsizei n, const GLuint* rbos)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteRenderbuffersEXT() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteRenderbuffersEXT(n, rbos);
  } else {
    logDebugMessage(4,"bzDeleteRenderbuffersEXT(), no context\n");
  }
}

//============================================================================//
//============================================================================//
//
//  Matrices
//
// Test for matrix underflows (overflows are not yet tested)
//

#ifdef DEBUG_GL_MATRIX_STACKS

static GLenum matrixMode = GL_MODELVIEW;
static int matrixDepth[3] = {0, 0, 0};
static const int maxMatrixDepth[3] = {32, 2, 2}; // guaranteed

static inline int getMatrixSlot(GLenum mode)
{
  if (mode == GL_MODELVIEW) {
    return 0;
  } else if (mode == GL_PROJECTION) {
    return 1;
  } else if (mode == GL_TEXTURE) {
    return 2;
  } else {
    return -1;
  }
}

void bzPushMatrix()
{
  int slot = getMatrixSlot(matrixMode);
  if (slot < 0) {
    printf ("bzPushMatrix(): bad matrix mode: %i\n", matrixMode);
    return;
  }
  matrixDepth[slot]++;
  if (matrixDepth[slot] > maxMatrixDepth[slot]) {
    printf ("bzPushMatrix(): overflow (mode %i, depth %i)\n",
	    matrixMode, matrixDepth[slot]);
    return;
  }
  glPushMatrix();
}

void bzPopMatrix()
{
  int slot = getMatrixSlot(matrixMode);
  if (slot < 0) {
    printf ("bzPopMatrix(): bad matrix mode: %i\n", matrixMode);
    return;
  }
  matrixDepth[slot]--;
  if (matrixDepth[slot] < 0) {
    printf ("bzPopMatrix(): underflow (mode %i, depth %i)\n",
	    matrixMode, matrixDepth[slot]);
    return;
  }
  glPopMatrix();
}

void bzMatrixMode(GLenum mode)
{
  int slot = getMatrixSlot(matrixMode);
  if (slot < 0) {
    printf ("bzMatrixMode(): bad matrix mode: %i\n", mode);
    return;
  }
  matrixMode = mode;
  glMatrixMode(mode);
  logDebugMessage(3,"MatrixMode: %i %i %i\n", matrixDepth[0], matrixDepth[1], matrixDepth[2]);
}

#endif // DEBUG_GL_MATRIX_STACKS

//============================================================================//
//============================================================================//
<commit_msg>* moved the bzfgl.h #include  (after the UNSAFE_GL_CONTEXT #define)<commit_after>/* bzflag
* Copyright (c) 1993 - 2009 Tim Riker
* Written By Dave Rodgers (aka: trepan)
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#include "common.h"

// there is no 'implementation header'

// common headers
/////////////////////////
#define UNSAFE_GL_CONTEXT
/////////// for /////////
#include "bzfgl.h"
/////////////////////////
#include "bzfio.h"
#include "OpenGLGState.h"

//============================================================================//
//============================================================================//
//
//  for hooking debuggers
//

static void contextFreeError(const char* message)
{
  printf("contextFreeError(): %s\n", message);
}

static void contextInitError(const char* message)
{
  printf("contextInitError(): %s\n", message);
}

//============================================================================//
//============================================================================//
//
//  Display Lists
//

void bzNewList(GLuint list, GLenum mode)
{
  glNewList(list, mode);
  return;
}

GLuint bzGenLists(GLsizei count)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzGenLists() is having issues");
  }
  GLuint base = glGenLists(count);
  return base;
}

void bzDeleteLists(GLuint base, GLsizei count)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteLists() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteLists(base, count);
  } else {
    logDebugMessage(4,"bzDeleteLists(), no context\n");
  }
  return;
}

//============================================================================//
//============================================================================//
//
//  Textures
//

void bzGenTextures(GLsizei count, GLuint *textures)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzGenTextures() is having issues");
  }
  glGenTextures(count, textures);
  return;
}

void bzDeleteTextures(GLsizei count, const GLuint *textures)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteTextures() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteTextures(count, textures);
  } else {
    logDebugMessage(4,"bzDeleteTextures(), no context\n");
  }
  return;
}

//============================================================================//
//============================================================================//
//
//  Shaders
//

GLuint bzCreateShader(GLenum type)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzCreateShader() is having issues");
  }
  return glCreateShader(type);
}

void bzDeleteShader(GLuint shader)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteShader() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteShader(shader);
  } else {
    logDebugMessage(4,"bzDeleteShader(), no context\n");
  }
}

GLuint bzCreateProgram()
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzCreateProgram() is having issues");
  }
  return glCreateProgram();
}

void bzDeleteProgram(GLuint program)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteProgram() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteProgram(program);
  } else {
    logDebugMessage(4,"bzDeleteProgram(), no context\n");
  }
}

//============================================================================//
//============================================================================//
//
//  Occlusion Queries
//

void bzGenQueries(GLsizei n, GLuint* queries)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzGenQueries() is having issues");
  }
  glGenQueries(n, queries);
}

void bzDeleteQueries(GLsizei n, const GLuint* queries)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteProgram() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteQueries(n, queries);
  } else {
    logDebugMessage(4,"bzDeleteQueries(), no context\n");
  }
}

//============================================================================//
//============================================================================//
//
//  Frame Buffers
//

void bzGenFramebuffersEXT(GLsizei n, GLuint* fbos)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzGenFramebuffersEXT() is having issues");
  }
  glGenFramebuffersEXT(n, fbos);
}

void bzDeleteFramebuffersEXT(GLsizei n, const GLuint* fbos)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteFramebuffersEXT() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteFramebuffersEXT(n, fbos);
  } else {
    logDebugMessage(4,"bzDeleteFramebuffersEXT(), no context\n");
  }
}

//============================================================================//
//============================================================================//
//
//  Render Buffers
//

void bzGenRenderbuffersEXT(GLsizei n, GLuint* rbos)
{
  if (OpenGLGState::isExecutingFreeFuncs()) {
    contextFreeError("bzGenRenderbuffersEXT() is having issues");
  }
  glGenRenderbuffersEXT(n, rbos);
}

void bzDeleteRenderbuffersEXT(GLsizei n, const GLuint* rbos)
{
  if (OpenGLGState::isExecutingInitFuncs()) {
    contextInitError("bzDeleteRenderbuffersEXT() is having issues");
  }
  if (OpenGLGState::haveGLContext()) {
    glDeleteRenderbuffersEXT(n, rbos);
  } else {
    logDebugMessage(4,"bzDeleteRenderbuffersEXT(), no context\n");
  }
}

//============================================================================//
//============================================================================//
//
//  Matrices
//
// Test for matrix underflows (overflows are not yet tested)
//

#ifdef DEBUG_GL_MATRIX_STACKS

static GLenum matrixMode = GL_MODELVIEW;
static int matrixDepth[3] = {0, 0, 0};
static const int maxMatrixDepth[3] = {32, 2, 2}; // guaranteed

static inline int getMatrixSlot(GLenum mode)
{
  if (mode == GL_MODELVIEW) {
    return 0;
  } else if (mode == GL_PROJECTION) {
    return 1;
  } else if (mode == GL_TEXTURE) {
    return 2;
  } else {
    return -1;
  }
}

void bzPushMatrix()
{
  int slot = getMatrixSlot(matrixMode);
  if (slot < 0) {
    printf ("bzPushMatrix(): bad matrix mode: %i\n", matrixMode);
    return;
  }
  matrixDepth[slot]++;
  if (matrixDepth[slot] > maxMatrixDepth[slot]) {
    printf ("bzPushMatrix(): overflow (mode %i, depth %i)\n",
	    matrixMode, matrixDepth[slot]);
    return;
  }
  glPushMatrix();
}

void bzPopMatrix()
{
  int slot = getMatrixSlot(matrixMode);
  if (slot < 0) {
    printf ("bzPopMatrix(): bad matrix mode: %i\n", matrixMode);
    return;
  }
  matrixDepth[slot]--;
  if (matrixDepth[slot] < 0) {
    printf ("bzPopMatrix(): underflow (mode %i, depth %i)\n",
	    matrixMode, matrixDepth[slot]);
    return;
  }
  glPopMatrix();
}

void bzMatrixMode(GLenum mode)
{
  int slot = getMatrixSlot(matrixMode);
  if (slot < 0) {
    printf ("bzMatrixMode(): bad matrix mode: %i\n", mode);
    return;
  }
  matrixMode = mode;
  glMatrixMode(mode);
  logDebugMessage(3,"MatrixMode: %i %i %i\n", matrixDepth[0], matrixDepth[1], matrixDepth[2]);
}

#endif // DEBUG_GL_MATRIX_STACKS

//============================================================================//
//============================================================================//
<|endoftext|>


<commit_before>/*
    Copyright (C) 2010 Marco Ballesio <gibrovacco@gmail.com>
    Copyright (C) 2011 Collabora Ltd.
      @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>

    This library is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published
    by the Free Software Foundation; either version 2.1 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "player.h"
#include <QtCore/QDir>
#include <QGlib/Connect>
#include <QGlib/Error>
#include <QGst/Pipeline>
#include <QGst/ElementFactory>
#include <QGst/Bus>
#include <QGst/Message>
#include <QGst/Query>
#include <QGst/ClockTime>
#include <QGst/Event>
#include <QGst/StreamVolume>

Player::Player(QWidget *parent)
    : QGst::Ui::VideoWidget(parent)
{
    //this timer is used to tell the ui to change its position slider & label
    //every 100 ms, but only when the pipeline is playing
    connect(&m_positionTimer, SIGNAL(timeout()), this, SIGNAL(positionChanged()));
}

Player::~Player()
{
    if (m_pipeline) {
        m_pipeline->setState(QGst::StateNull);
        stopPipelineWatch();
    }
}

void Player::setUri(const QString & uri)
{
    QString realUri = uri;

    //if uri is not a real uri, assume it is a file path
    if (realUri.indexOf("://") < 0) {
        realUri = "file://" + QFileInfo(realUri).absoluteFilePath();
    }

    if (!m_pipeline) {
        m_pipeline = QGst::ElementFactory::make("playbin2").dynamicCast<QGst::Pipeline>();
        if (m_pipeline) {
            //let the video widget watch the pipeline for new video sinks
            watchPipeline(m_pipeline);

            //watch the bus for messages
            QGst::BusPtr bus = m_pipeline->bus();
            bus->addSignalWatch();
            QGlib::connect(bus, "message", this, &Player::onBusMessage);
        } else {
            qCritical() << "Failed to create the pipeline";
        }
    }

    if (m_pipeline) {
        m_pipeline->setProperty("uri", realUri);
    }
}

QTime Player::position() const
{
    if (m_pipeline) {
        //here we query the pipeline about its position
        //and we request that the result is returned in time format
        QGst::PositionQueryPtr query = QGst::PositionQuery::create(QGst::FormatTime);
        m_pipeline->query(query);
        return QGst::ClockTime(query->position()).toTime();
    } else {
        return QTime();
    }
}

void Player::setPosition(const QTime & pos)
{
    QGst::SeekEventPtr evt = QGst::SeekEvent::create(
        1.0, QGst::FormatTime, QGst::SeekFlagFlush,
        QGst::SeekTypeSet, QGst::ClockTime::fromTime(pos),
        QGst::SeekTypeNone, QGst::ClockTime::None
    );

    m_pipeline->sendEvent(evt);
}

int Player::volume() const
{
    if (m_pipeline) {
        QGst::StreamVolumePtr svp =
            m_pipeline.dynamicCast<QGst::StreamVolume>();

        if (svp) {
            return svp->volume(QGst::StreamVolumeFormatCubic) * 10;
        }
    }

    return 0;
}

void Player::setVolume(int volume)
{
    if (m_pipeline) {
        QGst::StreamVolumePtr svp =
            m_pipeline.dynamicCast<QGst::StreamVolume>();

        if(svp) {
            svp->setVolume((double)volume / 10, QGst::StreamVolumeFormatCubic);
        }
    }
}

QTime Player::length() const
{
    if (m_pipeline) {
        //here we query the pipeline about the content's duration
        //and we request that the result is returned in time format
        QGst::DurationQueryPtr query = QGst::DurationQuery::create(QGst::FormatTime);
        m_pipeline->query(query);
        return QGst::ClockTime(query->duration()).toTime();
    } else {
        return QTime();
    }
}

QGst::State Player::state() const
{
    return m_pipeline ? m_pipeline->currentState() : QGst::StateNull;
}

void Player::play()
{
    if (m_pipeline) {
        m_pipeline->setState(QGst::StatePlaying);
    }
}

void Player::pause()
{
    if (m_pipeline) {
        m_pipeline->setState(QGst::StatePaused);
    }
}

void Player::stop()
{
    if (m_pipeline) {
        m_pipeline->setState(QGst::StateNull);

        //once the pipeline stops, the bus is flushed so we will
        //not receive any StateChangedMessage about this.
        //so, to inform the ui, we have to emit this signal manually.
        Q_EMIT stateChanged();
    }
}

void Player::onBusMessage(const QGst::MessagePtr & message)
{
    switch (message->type()) {
    case QGst::MessageEos: //End of stream. We reached the end of the file.
        stop();
        break;
    case QGst::MessageError: //Some error occurred.
        qCritical() << message.staticCast<QGst::ErrorMessage>()->error();
        stop();
        break;
    case QGst::MessageStateChanged: //The element in message->source() has changed state
        if (message->source() == m_pipeline) {
            handlePipelineStateChange(message.staticCast<QGst::StateChangedMessage>());
        }
        break;
    default:
        break;
    }
}

void Player::handlePipelineStateChange(const QGst::StateChangedMessagePtr & scm)
{
    switch (scm->newState()) {
    case QGst::StatePlaying:
        //start the timer when the pipeline starts playing
        m_positionTimer.start(100);
        break;
    case QGst::StatePaused:
        //stop the timer when the pipeline pauses
        if(scm->oldState() == QGst::StatePlaying) {
            m_positionTimer.stop();
        }
        break;
    default:
        break;
    }

    Q_EMIT stateChanged();
}

#include "moc_player.cpp"
<commit_msg>Fix uri encoding in the player example.<commit_after>/*
    Copyright (C) 2010 Marco Ballesio <gibrovacco@gmail.com>
    Copyright (C) 2011 Collabora Ltd.
      @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>

    This library is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published
    by the Free Software Foundation; either version 2.1 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "player.h"
#include <QtCore/QDir>
#include <QtCore/QUrl>
#include <QGlib/Connect>
#include <QGlib/Error>
#include <QGst/Pipeline>
#include <QGst/ElementFactory>
#include <QGst/Bus>
#include <QGst/Message>
#include <QGst/Query>
#include <QGst/ClockTime>
#include <QGst/Event>
#include <QGst/StreamVolume>

Player::Player(QWidget *parent)
    : QGst::Ui::VideoWidget(parent)
{
    //this timer is used to tell the ui to change its position slider & label
    //every 100 ms, but only when the pipeline is playing
    connect(&m_positionTimer, SIGNAL(timeout()), this, SIGNAL(positionChanged()));
}

Player::~Player()
{
    if (m_pipeline) {
        m_pipeline->setState(QGst::StateNull);
        stopPipelineWatch();
    }
}

void Player::setUri(const QString & uri)
{
    QString realUri = uri;

    //if uri is not a real uri, assume it is a file path
    if (realUri.indexOf("://") < 0) {
        realUri = QUrl::fromLocalFile(realUri).toEncoded();
    }

    if (!m_pipeline) {
        m_pipeline = QGst::ElementFactory::make("playbin2").dynamicCast<QGst::Pipeline>();
        if (m_pipeline) {
            //let the video widget watch the pipeline for new video sinks
            watchPipeline(m_pipeline);

            //watch the bus for messages
            QGst::BusPtr bus = m_pipeline->bus();
            bus->addSignalWatch();
            QGlib::connect(bus, "message", this, &Player::onBusMessage);
        } else {
            qCritical() << "Failed to create the pipeline";
        }
    }

    if (m_pipeline) {
        m_pipeline->setProperty("uri", realUri);
    }
}

QTime Player::position() const
{
    if (m_pipeline) {
        //here we query the pipeline about its position
        //and we request that the result is returned in time format
        QGst::PositionQueryPtr query = QGst::PositionQuery::create(QGst::FormatTime);
        m_pipeline->query(query);
        return QGst::ClockTime(query->position()).toTime();
    } else {
        return QTime();
    }
}

void Player::setPosition(const QTime & pos)
{
    QGst::SeekEventPtr evt = QGst::SeekEvent::create(
        1.0, QGst::FormatTime, QGst::SeekFlagFlush,
        QGst::SeekTypeSet, QGst::ClockTime::fromTime(pos),
        QGst::SeekTypeNone, QGst::ClockTime::None
    );

    m_pipeline->sendEvent(evt);
}

int Player::volume() const
{
    if (m_pipeline) {
        QGst::StreamVolumePtr svp =
            m_pipeline.dynamicCast<QGst::StreamVolume>();

        if (svp) {
            return svp->volume(QGst::StreamVolumeFormatCubic) * 10;
        }
    }

    return 0;
}

void Player::setVolume(int volume)
{
    if (m_pipeline) {
        QGst::StreamVolumePtr svp =
            m_pipeline.dynamicCast<QGst::StreamVolume>();

        if(svp) {
            svp->setVolume((double)volume / 10, QGst::StreamVolumeFormatCubic);
        }
    }
}

QTime Player::length() const
{
    if (m_pipeline) {
        //here we query the pipeline about the content's duration
        //and we request that the result is returned in time format
        QGst::DurationQueryPtr query = QGst::DurationQuery::create(QGst::FormatTime);
        m_pipeline->query(query);
        return QGst::ClockTime(query->duration()).toTime();
    } else {
        return QTime();
    }
}

QGst::State Player::state() const
{
    return m_pipeline ? m_pipeline->currentState() : QGst::StateNull;
}

void Player::play()
{
    if (m_pipeline) {
        m_pipeline->setState(QGst::StatePlaying);
    }
}

void Player::pause()
{
    if (m_pipeline) {
        m_pipeline->setState(QGst::StatePaused);
    }
}

void Player::stop()
{
    if (m_pipeline) {
        m_pipeline->setState(QGst::StateNull);

        //once the pipeline stops, the bus is flushed so we will
        //not receive any StateChangedMessage about this.
        //so, to inform the ui, we have to emit this signal manually.
        Q_EMIT stateChanged();
    }
}

void Player::onBusMessage(const QGst::MessagePtr & message)
{
    switch (message->type()) {
    case QGst::MessageEos: //End of stream. We reached the end of the file.
        stop();
        break;
    case QGst::MessageError: //Some error occurred.
        qCritical() << message.staticCast<QGst::ErrorMessage>()->error();
        stop();
        break;
    case QGst::MessageStateChanged: //The element in message->source() has changed state
        if (message->source() == m_pipeline) {
            handlePipelineStateChange(message.staticCast<QGst::StateChangedMessage>());
        }
        break;
    default:
        break;
    }
}

void Player::handlePipelineStateChange(const QGst::StateChangedMessagePtr & scm)
{
    switch (scm->newState()) {
    case QGst::StatePlaying:
        //start the timer when the pipeline starts playing
        m_positionTimer.start(100);
        break;
    case QGst::StatePaused:
        //stop the timer when the pipeline pauses
        if(scm->oldState() == QGst::StatePlaying) {
            m_positionTimer.stop();
        }
        break;
    default:
        break;
    }

    Q_EMIT stateChanged();
}

#include "moc_player.cpp"
<|endoftext|>


<commit_before>// Copyright (c) 2011, Christian Rorvik
// Distributed under the Simplified BSD License (See accompanying file LICENSE.txt)

#include "crunch/concurrency/thread.hpp"
#include "crunch/concurrency/exceptions.hpp"

#include "crunch/base/assert.hpp"

#include "../../thread_data.hpp"

#include <memory>

#include <windows.h>

namespace Crunch { namespace Concurrency {

void Thread::Create(std::function<void ()>&& f)
{
    mData.reset(new Data(std::move(f)));
    mData->self = mData;

    mData->handle = ::CreateThread(NULL, 0, &Data::EntryPoint, mData.get(), 0, &mData->id);
    if (mData->handle == NULL)
    {
        mData->self.reset();
        mData.reset();
        throw ThreadResourceError();
    }
}

void Thread::Detach()
{
    if (mData)
    {
        CloseHandle(mData->handle);
        mData.reset();
    }
}

void Thread::Join()
{
    ThreadCancellationPoint();

    if (mData)
    {
        CRUNCH_ASSERT_ALWAYS(WaitForSingleObject(mData->handle, INFINITE) == WAIT_OBJECT_0);
        CloseHandle(mData->handle);
        mData.reset();
    }
}

ThreadId GetThreadId()
{
    return ::GetCurrentThreadId();
}

}}
<commit_msg>crunch_concurrency - Windows build fixes after ThreadId changes<commit_after>// Copyright (c) 2011, Christian Rorvik
// Distributed under the Simplified BSD License (See accompanying file LICENSE.txt)

#include "crunch/concurrency/thread.hpp"
#include "crunch/concurrency/exceptions.hpp"

#include "crunch/base/assert.hpp"

#include "../../thread_data.hpp"

#include <memory>

#include <windows.h>

namespace Crunch { namespace Concurrency {

void Thread::Create(std::function<void ()>&& f)
{
    mData.reset(new Data(std::move(f)));
    mData->self = mData;

    DWORD id;
    mData->handle = ::CreateThread(NULL, 0, &Data::EntryPoint, mData.get(), 0, &id);
    if (mData->handle == NULL)
    {
        mData->self.reset();
        mData.reset();
        throw ThreadResourceError();
    }
    mData->id = ThreadId(id);
}

void Thread::Detach()
{
    if (mData)
    {
        CloseHandle(mData->handle);
        mData.reset();
    }
}

void Thread::Join()
{
    ThreadCancellationPoint();

    if (mData)
    {
        CRUNCH_ASSERT_ALWAYS(WaitForSingleObject(mData->handle, INFINITE) == WAIT_OBJECT_0);
        CloseHandle(mData->handle);
        mData.reset();
    }
}

ThreadId GetThreadId()
{
    return ThreadId(::GetCurrentThreadId());
}

}}
<|endoftext|>


<commit_before>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2010 Aldebaran Robotics
*/

#ifndef QI_LOG_LOG_H
#define QI_LOG_LOG_H

#include <string>
#include <sstream>
#include <cstdarg>
#include <boost/function.hpp>
#include <qi/api.hpp>

#ifdef NO_QI_DEBUG
# define qiDebug(...)
# define qisDebug
#else
# define qiDebug(...)   qi::log::log(qi::log::debug,         __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
# define qisDebug       qi::log::LogStream(qi::log::debug,   __FILE__, __FUNCTION__, __LINE__).self()
#endif

#ifdef NO_QI_INFO
# define qiInfo(...)
# define qisInfo
#else
#define qiInfo(...)    qi::log::log(qi::log::info,          __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
#define qisInfo        qi::log::LogStream(qi::log::info,    __FILE__, __FUNCTION__, __LINE__).self()
#endif

#ifdef NO_QI_WARNING
# define qiWarning(...)
# define qisWarning
#else
# define qiWarning(...) qi::log::log(qi::log::warning,       __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
# define qisWarning     qi::log::LogStream(qi::log::warning, __FILE__, __FUNCTION__, __LINE__).self()
#endif

#ifdef NO_QI_ERROR
# define qiError(...)
# define qisError
#else
# define qiError(...)   qi::log::log(qi::log::error,         __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
# define qisError       qi::log::LogStream(qi::log::error,   __FILE__, __FUNCTION__, __LINE__).self()
#endif

#ifdef NO_QI_FATAL
# define qiFatal(...)
# define qisFatal
#else
# define qisFatal       qi::log::LogStream(qi::log::fatal, __FILE__, __FUNCTION__, __LINE__).self()
# define qiFatal(...)   qi::log::log(qi::log::fatal,       __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
#endif

namespace qi {

  namespace log {

    /**
     * Log Verbosity
     */
    enum QIAPI LogLevel {
      silent = 0,
      fatal,
      error,
      warning,
      info,
      debug,
    };

    /**
     * log handler ptr
     */
    typedef boost::function6<void,
                             qi::log::LogLevel,
                             const char *,
                             const char *,
                             int,
                             const char*,
                             va_list> LogFunctionPtr;

    /**
     * call this to make some log
     */
    QIAPI void log(const LogLevel    verb,
                   const char       *file,
                   const char       *fct,
                   const int         line,
                   const char       *fmt, ...);

    /** a very very basic log handler, this is not used
     *  and mostly for demo purpose but it's functionnal
     */
    QIAPI void defaultLogHandler(const LogLevel verb,
                                 const char    *file,
                                 const char    *fct,
                                 const int      line,
                                 const char    *fmt,
                                 va_list        vl);

    /**
     * set the function called when we need to log something
     */
    QIAPI void setLogHandler(LogFunctionPtr p);

    QIAPI const char *logLevelToString(const LogLevel verb);

    class QIAPI LogStream: public std::stringstream
    {
    public:

      /**
       * LogStream. Will log at object destruction
       * @param pLevel { debug = 5, info = 4, warning = 3, error = 2, fatal = 1, silent = 0 }
       * @param pFile __FILE__
       * @param pFunction __FUNCTION__
       * @param pLine __LINE__
       * @param pLogEntry log stream constructor and destructor (for scoped log)
       */
      LogStream(const LogLevel     level,
                const char        *file,
                const char        *function,
                const int          line);

      ~LogStream();

      // necessary to have sinfo et al. work with an anonymous object
      LogStream& self() { return *this; }

    private:
      LogLevel    _logLevel;
      const char *_file;
      const char *_function;
      int         _line;
    };

  }
}

#endif

<commit_msg>log: remove extra line breaks<commit_after>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2010 Aldebaran Robotics
*/

#ifndef QI_LOG_LOG_H
#define QI_LOG_LOG_H

#include <string>
#include <sstream>
#include <cstdarg>
#include <boost/function.hpp>
#include <qi/api.hpp>

#ifdef NO_QI_DEBUG
# define qiDebug(...)
# define qisDebug
#else
# define qiDebug(...)   qi::log::log(qi::log::debug,         __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
# define qisDebug       qi::log::LogStream(qi::log::debug,   __FILE__, __FUNCTION__, __LINE__).self()
#endif

#ifdef NO_QI_INFO
# define qiInfo(...)
# define qisInfo
#else
#define qiInfo(...)    qi::log::log(qi::log::info,          __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
#define qisInfo        qi::log::LogStream(qi::log::info,    __FILE__, __FUNCTION__, __LINE__).self()
#endif

#ifdef NO_QI_WARNING
# define qiWarning(...)
# define qisWarning
#else
# define qiWarning(...) qi::log::log(qi::log::warning,       __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
# define qisWarning     qi::log::LogStream(qi::log::warning, __FILE__, __FUNCTION__, __LINE__).self()
#endif

#ifdef NO_QI_ERROR
# define qiError(...)
# define qisError
#else
# define qiError(...)   qi::log::log(qi::log::error,         __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
# define qisError       qi::log::LogStream(qi::log::error,   __FILE__, __FUNCTION__, __LINE__).self()
#endif

#ifdef NO_QI_FATAL
# define qiFatal(...)
# define qisFatal
#else
# define qisFatal       qi::log::LogStream(qi::log::fatal, __FILE__, __FUNCTION__, __LINE__).self()
# define qiFatal(...)   qi::log::log(qi::log::fatal,       __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
#endif

namespace qi {
  namespace log {
    /**
     * Log Verbosity
     */
    enum QIAPI LogLevel {
      silent = 0,
      fatal,
      error,
      warning,
      info,
      debug,
    };

    /**
     * log handler ptr
     */
    typedef boost::function6<void,
                             qi::log::LogLevel,
                             const char *,
                             const char *,
                             int,
                             const char*,
                             va_list> LogFunctionPtr;

    /**
     * call this to make some log
     */
    QIAPI void log(const LogLevel    verb,
                   const char       *file,
                   const char       *fct,
                   const int         line,
                   const char       *fmt, ...);

    /** a very very basic log handler, this is not used
     *  and mostly for demo purpose but it's functionnal
     */
    QIAPI void defaultLogHandler(const LogLevel verb,
                                 const char    *file,
                                 const char    *fct,
                                 const int      line,
                                 const char    *fmt,
                                 va_list        vl);

    /**
     * set the function called when we need to log something
     */
    QIAPI void setLogHandler(LogFunctionPtr p);

    QIAPI const char *logLevelToString(const LogLevel verb);

    class QIAPI LogStream: public std::stringstream
    {
    public:

      /**
       * LogStream. Will log at object destruction
       * @param pLevel { debug = 5, info = 4, warning = 3, error = 2, fatal = 1, silent = 0 }
       * @param pFile __FILE__
       * @param pFunction __FUNCTION__
       * @param pLine __LINE__
       * @param pLogEntry log stream constructor and destructor (for scoped log)
       */
      LogStream(const LogLevel     level,
                const char        *file,
                const char        *function,
                const int          line);

      ~LogStream();

      // necessary to have sinfo et al. work with an anonymous object
      LogStream& self() { return *this; }

    private:
      LogLevel    _logLevel;
      const char *_file;
      const char *_function;
      int         _line;
    };

  }
}

#endif

<|endoftext|>