From 05430b7757616a3ea799dca7c499cffb4e3cef7c Mon Sep 17 00:00:00 2001
From: James Shiffer <2191476+scoliono@users.noreply.github.com>
Date: Tue, 6 Aug 2024 22:25:48 -0700
Subject: [PATCH] Initial commit
---
.gitignore | 93 ++++++++++++++
.gitmodules | 3 +
.idea/.gitignore | 8 ++
.idea/QtSettings.xml | 18 +++
.idea/VocaSTI.iml | 2 +
.idea/editor.xml | 103 +++++++++++++++
.idea/misc.xml | 12 ++
.idea/modules.xml | 8 ++
.idea/vcs.xml | 7 ++
CMakeLists.txt | 41 ++++++
README.md | 32 +++++
cmake/FindGLIB2.cmake | 87 +++++++++++++
cmake/FindGObject.cmake | 84 +++++++++++++
cmake/FindGStreamer.cmake | 173 ++++++++++++++++++++++++++
cmake/MacroFindGStreamerLibrary.cmake | 81 ++++++++++++
config_example.h | 11 ++
main.cpp | 90 ++++++++++++++
main.h | 33 +++++
miku.webp | Bin 0 -> 9350 bytes
qxmpp | 1 +
20 files changed, 887 insertions(+)
create mode 100644 .gitignore
create mode 100644 .gitmodules
create mode 100644 .idea/.gitignore
create mode 100644 .idea/QtSettings.xml
create mode 100644 .idea/VocaSTI.iml
create mode 100644 .idea/editor.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/modules.xml
create mode 100644 .idea/vcs.xml
create mode 100644 CMakeLists.txt
create mode 100644 README.md
create mode 100644 cmake/FindGLIB2.cmake
create mode 100644 cmake/FindGObject.cmake
create mode 100644 cmake/FindGStreamer.cmake
create mode 100644 cmake/MacroFindGStreamerLibrary.cmake
create mode 100644 config_example.h
create mode 100644 main.cpp
create mode 100644 main.h
create mode 100755 miku.webp
create mode 160000 qxmpp
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f07380b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,93 @@
+build/
+config.h
+
+CMakeLists.txt.user
+CMakeCache.txt
+CMakeFiles
+CMakeScripts
+Testing
+Makefile
+cmake_install.cmake
+install_manifest.txt
+compile_commands.json
+CTestTestfile.cmake
+_deps
+CMakeUserPresets.json
+
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..f7d733c
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "qxmpp"]
+ path = qxmpp
+ url = https://github.com/qxmpp-project/qxmpp
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/QtSettings.xml b/.idea/QtSettings.xml
new file mode 100644
index 0000000..d082c1d
--- /dev/null
+++ b/.idea/QtSettings.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/VocaSTI.iml b/.idea/VocaSTI.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/.idea/VocaSTI.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.idea/editor.xml b/.idea/editor.xml
new file mode 100644
index 0000000..855412d
--- /dev/null
+++ b/.idea/editor.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..59f2f77
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..ca2e226
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..3e5bcd3
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..a7dc784
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,41 @@
+cmake_minimum_required(VERSION 3.15)
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+project(VocaSTI VERSION 0.1.0 LANGUAGES CXX)
+
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+set(CMAKE_AUTOUIC ON)
+
+add_executable(VocaSTI
+ main.cpp
+ main.h
+ config.h
+)
+
+find_package(Qt6 COMPONENTS Core Network Xml REQUIRED)
+find_package(QXmppQt6 CONFIG REQUIRED)
+find_package(GStreamer REQUIRED)
+find_package(GLIB2 REQUIRED)
+find_package(GObject REQUIRED)
+
+target_link_libraries(VocaSTI
+ PRIVATE
+ Qt6::Core
+ Qt6::Network
+ Qt6::Xml
+ QXmpp::QXmpp
+ ${GSTREAMER_LIBRARY}
+ ${GLIB2_LIBRARIES}
+ ${GOBJECT_LIBRARIES}
+)
+
+target_include_directories(VocaSTI
+ PRIVATE
+ ${GSTREAMER_INCLUDE_DIRS}
+ ${GLIB2_INCLUDE_DIR}
+ ${GOBJECT_INCLUDE_DIR}
+ /usr/local/include/QXmppQt6
+)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d46002b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,32 @@
+# Vocaloid STI (Synthesizer Telephonic Interface)
+
+Call or text Hatsune Miku.
+
+[+1 (571) 669-3939](tel:+15716693939)
+
+
+
+## Build Instructions
+
+Make sure you have Qt 6, GStreamer and CMake installed.
+
+First, clone this repo and the qxmpp submodule. Inside of the qxmpp directory, run:
+
+```sh
+mkdir build
+cd build
+cmake .. -DWITH_GSTREAMER=ON -DQT_VERSION_MAJOR=6
+cmake --build . -j$(nproc)
+sudo cmake --build . --target install
+```
+
+Copy `config_example.h` to `config.h` and fill in the necessary credentials.
+
+Then from this repo's root, run:
+
+```sh
+mkdir build
+cd build
+cmake ..
+cmake --build . -j$(nproc)
+```
diff --git a/cmake/FindGLIB2.cmake b/cmake/FindGLIB2.cmake
new file mode 100644
index 0000000..30a5dfd
--- /dev/null
+++ b/cmake/FindGLIB2.cmake
@@ -0,0 +1,87 @@
+# SPDX-FileCopyrightText: 2008 Laurent Montel
+#
+# SPDX-License-Identifier: LicenseRef-MIT-variant
+
+# - Try to find the GLIB2 libraries
+# Once done this will define
+#
+# GLIB2_FOUND - system has glib2
+# GLIB2_INCLUDE_DIR - the glib2 include directory
+# GLIB2_LIBRARIES - glib2 library
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+
+if(GLIB2_INCLUDE_DIR AND GLIB2_LIBRARIES)
+ # Already in cache, be silent
+ set(GLIB2_FIND_QUIETLY TRUE)
+endif(GLIB2_INCLUDE_DIR AND GLIB2_LIBRARIES)
+
+if (NOT WIN32)
+ find_package(PkgConfig QUIET)
+ if(PKG_CONFIG_FOUND)
+ pkg_check_modules(PKG_GLIB QUIET glib-2.0)
+ endif()
+endif(NOT WIN32)
+
+find_path(GLIB2_MAIN_INCLUDE_DIR glib.h
+ PATH_SUFFIXES glib-2.0
+ HINTS ${PKG_GLIB_INCLUDE_DIRS} ${PKG_GLIB_INCLUDEDIR})
+
+# search the glibconfig.h include dir under the same root where the library is found
+find_library(GLIB2_LIBRARIES
+ NAMES glib-2.0
+ HINTS ${PKG_GLIB_LIBRARY_DIRS} ${PKG_GLIB_LIBDIR})
+
+find_path(GLIB2_INTERNAL_INCLUDE_DIR glibconfig.h
+ PATH_SUFFIXES glib-2.0/include ../lib/glib-2.0/include
+ HINTS ${PKG_GLIB_INCLUDE_DIRS} ${PKG_GLIB_LIBRARIES} ${CMAKE_SYSTEM_LIBRARY_PATH})
+
+set(GLIB2_INCLUDE_DIR ${GLIB2_MAIN_INCLUDE_DIR})
+
+# not sure if this include dir is optional or required
+# for now it is optional
+if(GLIB2_INTERNAL_INCLUDE_DIR)
+ set(GLIB2_INCLUDE_DIR ${GLIB2_INCLUDE_DIR} ${GLIB2_INTERNAL_INCLUDE_DIR})
+endif(GLIB2_INTERNAL_INCLUDE_DIR)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(GLIB2 DEFAULT_MSG GLIB2_LIBRARIES GLIB2_MAIN_INCLUDE_DIR)
+
+mark_as_advanced(GLIB2_INCLUDE_DIR GLIB2_LIBRARIES)
+
+
+find_program(GLIB2_GENMARSHAL_UTIL glib-genmarshal)
+
+macro(glib2_genmarshal output_name)
+ file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/genmarshal_tmp)
+ foreach(_declaration ${ARGN})
+ file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/genmarshal_tmp "${_declaration}\n")
+ endforeach()
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${output_name}.h ${CMAKE_CURRENT_BINARY_DIR}/${output_name}.c
+ COMMAND ${GLIB2_GENMARSHAL_UTIL} --header genmarshal_tmp > ${output_name}.h
+ COMMAND ${GLIB2_GENMARSHAL_UTIL} --body genmarshal_tmp > ${output_name}.c
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ )
+endmacro()
diff --git a/cmake/FindGObject.cmake b/cmake/FindGObject.cmake
new file mode 100644
index 0000000..6f43bc8
--- /dev/null
+++ b/cmake/FindGObject.cmake
@@ -0,0 +1,84 @@
+# SPDX-FileCopyrightText: Tim Beaulen
+# SPDX-FileCopyrightText: Helio Chissini de Castro
+#
+# SPDX-License-Identifier: LicenseRef-MIT-variant
+
+# - Try to find GObject
+# Once done this will define
+#
+# GOBJECT_FOUND - system has GObject
+# GOBJECT_INCLUDE_DIR - the GObject include directory
+# GOBJECT_LIBRARIES - the libraries needed to use GObject
+# GOBJECT_DEFINITIONS - Compiler switches required for using GObject
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+
+IF (GOBJECT_INCLUDE_DIR AND GOBJECT_LIBRARIES)
+ # in cache already
+ SET(GObject_FIND_QUIETLY TRUE)
+ELSE (GOBJECT_INCLUDE_DIR AND GOBJECT_LIBRARIES)
+ SET(GObject_FIND_QUIETLY FALSE)
+ENDIF (GOBJECT_INCLUDE_DIR AND GOBJECT_LIBRARIES)
+
+IF (NOT WIN32)
+ FIND_PACKAGE(PkgConfig REQUIRED)
+ # use pkg-config to get the directories and then use these values
+ # in the FIND_PATH() and FIND_LIBRARY() calls
+ PKG_CHECK_MODULES(PKG_GOBJECT2 REQUIRED gobject-2.0)
+ SET(GOBJECT_DEFINITIONS ${PKG_GOBJECT2_CFLAGS})
+ENDIF (NOT WIN32)
+
+FIND_PATH(GOBJECT_INCLUDE_DIR gobject/gobject.h
+ HINTS ${PKG_GOBJECT2_INCLUDE_DIRS} ${PKG_GOBJECT2_INCLUDEDIR}
+ PATHS /usr/include/glib-2.0/
+ PATH_SUFFIXES glib-2.0
+ )
+
+FIND_LIBRARY(_GObjectLibs NAMES gobject-2.0
+ HINTS
+ ${PKG_GOBJECT2_LIBRARY_DIRS}
+ ${PKG_GOBJECT2_LIBDIR}
+ )
+FIND_LIBRARY(_GModuleLibs NAMES gmodule-2.0
+ HINTS
+ ${PKG_GOBJECT2_LIBRARY_DIRS}
+ ${PKG_GOBJECT2_LIBDIR}
+ )
+FIND_LIBRARY(_GThreadLibs NAMES gthread-2.0
+ HINTS
+ ${PKG_GOBJECT2_LIBRARY_DIRS}
+ ${PKG_GOBJECT2_LIBDIR}
+ )
+FIND_LIBRARY(_GLibs NAMES glib-2.0
+ HINTS
+ ${PKG_GOBJECT2_LIBRARY_DIRS}
+ ${PKG_GOBJECT2_LIBDIR}
+ )
+
+SET (GOBJECT_LIBRARIES ${_GObjectLibs} ${_GModuleLibs} ${_GThreadLibs} ${_GLibs})
+
+MARK_AS_ADVANCED(GOBJECT_INCLUDE_DIR GOBJECT_LIBRARIES)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GObject DEFAULT_MSG GOBJECT_INCLUDE_DIR GOBJECT_LIBRARIES)
diff --git a/cmake/FindGStreamer.cmake b/cmake/FindGStreamer.cmake
new file mode 100644
index 0000000..3ae6ca6
--- /dev/null
+++ b/cmake/FindGStreamer.cmake
@@ -0,0 +1,173 @@
+# SPDX-FileCopyrightText: 2010 Collabora Ltd., George Kiagiadakis
+#
+# SPDX-License-Identifier: LicenseRef-MIT-variant
+
+# - Try to find GStreamer
+# Once done this will define
+#
+# GSTREAMER_FOUND - system has GStreamer
+# GSTREAMER_INCLUDE_DIR - the GStreamer main include directory
+# GSTREAMER_INCLUDE_DIRS - the GStreamer include directories
+# GSTREAMER_LIBRARY - the main GStreamer library
+# GSTREAMER_PLUGIN_DIR - the GStreamer plugin directory
+#
+# And for all the plugin libraries specified in the COMPONENTS
+# of find_package, this module will define:
+#
+# GSTREAMER__LIBRARY_FOUND - system has
+# GSTREAMER__LIBRARY - the library
+# GSTREAMER__INCLUDE_DIR - the include directory
+
+# Copyright (c) 2010, Collabora Ltd.
+# @author George Kiagiadakis
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+
+if (GSTREAMER_INCLUDE_DIR AND GSTREAMER_LIBRARY)
+ set(GStreamer_FIND_QUIETLY TRUE)
+else()
+ set(GStreamer_FIND_QUIETLY FALSE)
+endif()
+
+set(GSTREAMER_ABI_VERSION "1.0")
+
+
+# Find the main library
+find_package(PkgConfig)
+
+if (PKG_CONFIG_FOUND)
+ pkg_check_modules(PKG_GSTREAMER QUIET gstreamer-${GSTREAMER_ABI_VERSION})
+ if(PKG_GSTREAMER_FOUND)
+ exec_program(${PKG_CONFIG_EXECUTABLE}
+ ARGS --variable pluginsdir gstreamer-${GSTREAMER_ABI_VERSION}
+ OUTPUT_VARIABLE PKG_GSTREAMER_PLUGIN_DIR)
+ endif()
+ set(GSTREAMER_DEFINITIONS ${PKG_GSTREAMER_CFLAGS})
+endif()
+
+find_library(GSTREAMER_LIBRARY
+ NAMES gstreamer-${GSTREAMER_ABI_VERSION}
+ HINTS ${PKG_GSTREAMER_LIBRARY_DIRS} ${PKG_GSTREAMER_LIBDIR})
+
+find_path(GSTREAMER_INCLUDE_DIR
+ gst/gst.h
+ HINTS ${PKG_GSTREAMER_INCLUDE_DIRS} ${PKG_GSTREAMER_INCLUDEDIR}
+ PATH_SUFFIXES gstreamer-${GSTREAMER_ABI_VERSION})
+
+find_path(GSTREAMER_gstconfig_INCLUDE_DIR
+ gst/gstconfig.h
+ HINTS ${PKG_GSTREAMER_INCLUDE_DIRS} ${PKG_GSTREAMER_INCLUDEDIR}
+ PATH_SUFFIXES gstreamer-${GSTREAMER_ABI_VERSION})
+
+set(GSTREAMER_INCLUDE_DIRS ${GSTREAMER_INCLUDE_DIR} ${GSTREAMER_gstconfig_INCLUDE_DIR})
+list(REMOVE_DUPLICATES GSTREAMER_INCLUDE_DIRS)
+
+if (PKG_GSTREAMER_PLUGIN_DIR)
+ set(_GSTREAMER_PLUGIN_DIR ${PKG_GSTREAMER_PLUGIN_DIR})
+else()
+ get_filename_component(_GSTREAMER_LIB_DIR ${GSTREAMER_LIBRARY} PATH)
+ set(_GSTREAMER_PLUGIN_DIR ${_GSTREAMER_LIB_DIR}/gstreamer-${GSTREAMER_ABI_VERSION})
+endif()
+
+set(GSTREAMER_PLUGIN_DIR ${_GSTREAMER_PLUGIN_DIR}
+ CACHE PATH "The path to the gstreamer plugins installation directory")
+
+mark_as_advanced(GSTREAMER_LIBRARY
+ GSTREAMER_INCLUDE_DIR
+ GSTREAMER_gstconfig_INCLUDE_DIR
+ GSTREAMER_PLUGIN_DIR)
+
+
+# Find additional libraries
+include(MacroFindGStreamerLibrary)
+
+macro(_find_gst_component _name _header)
+ find_gstreamer_library(${_name} ${_header} ${GSTREAMER_ABI_VERSION} ${GStreamer_FIND_QUIETLY})
+ set(_GSTREAMER_EXTRA_VARIABLES ${_GSTREAMER_EXTRA_VARIABLES}
+ GSTREAMER_${_name}_LIBRARY GSTREAMER_${_name}_INCLUDE_DIR)
+endmacro()
+
+foreach(_component ${GStreamer_FIND_COMPONENTS})
+ if (${_component} STREQUAL "base")
+ _find_gst_component(BASE gstbasesink.h)
+ elseif (${_component} STREQUAL "check")
+ _find_gst_component(CHECK gstcheck.h)
+ elseif (${_component} STREQUAL "controller")
+ _find_gst_component(CONTROLLER gstargbcontrolbinding.h)
+ elseif (${_component} STREQUAL "net")
+ _find_gst_component(NET gstnet.h)
+ else()
+ message (AUTHOR_WARNING "FindGStreamerPluginsBase.cmake: Invalid component \"${_component}\" was specified")
+ endif()
+endforeach()
+
+
+# Version check
+if (GStreamer_FIND_VERSION)
+ if (PKG_GSTREAMER_FOUND)
+ if("${PKG_GSTREAMER_VERSION}" VERSION_LESS "${GStreamer_FIND_VERSION}")
+ if(NOT GStreamer_FIND_QUIETLY)
+ message(STATUS "Found GStreamer version ${PKG_GSTREAMER_VERSION}, but at least version ${GStreamer_FIND_VERSION} is required")
+ endif()
+ set(GSTREAMER_VERSION_COMPATIBLE FALSE)
+ else()
+ set(GSTREAMER_VERSION_COMPATIBLE TRUE)
+ endif()
+ elseif(GSTREAMER_INCLUDE_DIR)
+ include(CheckCXXSourceCompiles)
+
+ set(CMAKE_REQUIRED_INCLUDES ${GSTREAMER_INCLUDE_DIR})
+ string(REPLACE "." "," _comma_version ${GStreamer_FIND_VERSION})
+ # Hack to invalidate the cached value
+ set(GSTREAMER_VERSION_COMPATIBLE GSTREAMER_VERSION_COMPATIBLE)
+
+ check_cxx_source_compiles("
+#define G_BEGIN_DECLS
+#define G_END_DECLS
+#include
+
+#if GST_CHECK_VERSION(${_comma_version})
+int main() { return 0; }
+#else
+# error \"GStreamer version incompatible\"
+#endif
+" GSTREAMER_VERSION_COMPATIBLE)
+
+ if (NOT GSTREAMER_VERSION_COMPATIBLE AND NOT GStreamer_FIND_QUIETLY)
+ message(STATUS "GStreamer ${GStreamer_FIND_VERSION} is required, but the version found is older")
+ endif()
+ else()
+ # We didn't find gstreamer at all
+ set(GSTREAMER_VERSION_COMPATIBLE FALSE)
+ endif()
+else()
+ # No version constrain was specified, thus we consider the version compatible
+ set(GSTREAMER_VERSION_COMPATIBLE TRUE)
+endif()
+
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(GStreamer DEFAULT_MSG
+ GSTREAMER_LIBRARY GSTREAMER_INCLUDE_DIRS
+ GSTREAMER_VERSION_COMPATIBLE ${_GSTREAMER_EXTRA_VARIABLES})
diff --git a/cmake/MacroFindGStreamerLibrary.cmake b/cmake/MacroFindGStreamerLibrary.cmake
new file mode 100644
index 0000000..e69fc64
--- /dev/null
+++ b/cmake/MacroFindGStreamerLibrary.cmake
@@ -0,0 +1,81 @@
+# SPDX-FileCopyrightText: 2010 Collabora Ltd., George Kiagiadakis
+#
+# SPDX-License-Identifier: LicenseRef-MIT-variant
+
+# - macro find_gstreamer_library
+
+# Copyright (c) 2010, Collabora Ltd.
+# @author George Kiagiadakis
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+
+macro(find_gstreamer_library _name _header _abi_version _quiet)
+ string(TOLOWER ${_name} _lower_name)
+ string(TOUPPER ${_name} _upper_name)
+
+ if (GSTREAMER_${_upper_name}_LIBRARY AND GSTREAMER_${_upper_name}_INCLUDE_DIR)
+ set(_GSTREAMER_${_upper_name}_QUIET TRUE)
+ else()
+ set(_GSTREAMER_${_upper_name}_QUIET FALSE)
+ endif()
+
+ if (PKG_CONFIG_FOUND)
+ pkg_check_modules(PKG_GSTREAMER_${_upper_name} QUIET gstreamer-${_lower_name}-${_abi_version})
+ endif()
+
+ find_library(GSTREAMER_${_upper_name}_LIBRARY
+ NAMES gst${_lower_name}-${_abi_version}
+ HINTS ${PKG_GSTREAMER_${_upper_name}_LIBRARY_DIRS}
+ ${PKG_GSTREAMER_${_upper_name}_LIBDIR}
+ )
+
+ find_path(GSTREAMER_${_upper_name}_INCLUDE_DIR
+ gst/${_lower_name}/${_header}
+ HINTS ${PKG_GSTREAMER_${_upper_name}_INCLUDE_DIRS}
+ ${PKG_GSTREAMER_${_upper_name}_INCLUDEDIR}
+ PATH_SUFFIXES gstreamer-${_abi_version}
+ )
+
+ if (GSTREAMER_${_upper_name}_LIBRARY AND GSTREAMER_${_upper_name}_INCLUDE_DIR)
+ set(GSTREAMER_${_upper_name}_LIBRARY_FOUND TRUE)
+ else()
+ set(GSTREAMER_${_upper_name}_LIBRARY_FOUND FALSE)
+ endif()
+
+ if (NOT _GSTREAMER_${_upper_name}_QUIET AND NOT _quiet)
+ if (GSTREAMER_${_upper_name}_LIBRARY)
+ message(STATUS "Found GSTREAMER_${_upper_name}_LIBRARY: ${GSTREAMER_${_upper_name}_LIBRARY}")
+ else()
+ message(STATUS "Could NOT find GSTREAMER_${_upper_name}_LIBRARY")
+ endif()
+
+ if (GSTREAMER_${_upper_name}_INCLUDE_DIR)
+ message(STATUS "Found GSTREAMER_${_upper_name}_INCLUDE_DIR: ${GSTREAMER_${_upper_name}_INCLUDE_DIR}")
+ else()
+ message(STATUS "Could NOT find GSTREAMER_${_upper_name}_INCLUDE_DIR")
+ endif()
+ endif()
+
+ mark_as_advanced(GSTREAMER_${_upper_name}_LIBRARY GSTREAMER_${_upper_name}_INCLUDE_DIR)
+endmacro()
diff --git a/config_example.h b/config_example.h
new file mode 100644
index 0000000..e012081
--- /dev/null
+++ b/config_example.h
@@ -0,0 +1,11 @@
+//
+// Copy this file to "config.h"
+//
+
+#ifndef VOCASTI_CONFIG_H_
+#define VOCASTI_CONFIG_H_
+
+#define VOCASTI_XMPP_EMAIL "EMAIL@linux.ucla.edu"
+#define VOCASTI_XMPP_PASSWD "password"
+
+#endif // VOCASTI_CONFIG_H_
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..6458b92
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,90 @@
+#include "main.h"
+#include "config.h"
+#include
+#include
+#include
+#include
+
+
+VocaXmppClient::VocaXmppClient(QObject *parent)
+ : QXmppClient(parent), m_call(nullptr)
+{
+ // Add the extension for Jingle (Voice/Video calls).
+ addExtension(&m_callManager);
+
+ connect(this, &QXmppClient::messageReceived, this, &VocaXmppClient::messageReceived);
+ connect(&m_callManager, &QXmppCallManager::callReceived, this, &VocaXmppClient::callReceived);
+ connect(&m_callManager, &QXmppCallManager::callStarted, this, &VocaXmppClient::callStarted);
+}
+
+VocaXmppClient::~VocaXmppClient()
+{
+}
+
+void VocaXmppClient::messageReceived(const QXmppMessage &message)
+{
+ QString from = message.from();
+ QString msg = message.body();
+
+ // sendPacket(QXmppMessage("", from, "Your message: " + msg));
+}
+
+void VocaXmppClient::callConnected()
+{
+
+}
+
+int VocaXmppClient::setupPipe()
+{
+ GstElement* wavenc = gst_element_factory_make("wavenc", "wavenc");
+ GstElement* sink = gst_element_factory_make("filesink", "sink");
+
+ if (!wavenc || !sink)
+ {
+ gst_printerr("Not all elements could be created\n");
+ }
+ GstElement* pipe = m_call->pipeline();
+ gst_bin_add_many(GST_BIN(pipe), wavenc, sink, NULL);
+ if (!gst_element_link_many(wavenc, sink, NULL))
+ {
+ gst_printerr("Elements could not be linked\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+void VocaXmppClient::callReceived(QXmppCall *call)
+{
+ m_call = call;
+ connect(m_call, &QXmppCall::connected, this, &VocaXmppClient::callConnected);
+ connect(m_call, &QXmppCall::finished, this, &VocaXmppClient::callFinished);
+ //connect(m_call, &QXmppCall::audioModeChanged, this, &VocaXmppClient::audioModeChanged);
+ m_call->accept();
+
+ setupPipe();
+}
+
+void VocaXmppClient::callStarted(QXmppCall *call)
+{
+ m_call = call;
+}
+
+void VocaXmppClient::callFinished()
+{
+ disconnect(m_call, &QXmppCall::connected, this, &VocaXmppClient::callConnected);
+ disconnect(m_call, &QXmppCall::finished, this, &VocaXmppClient::callFinished);
+ //disconnect(m_call, &QXmppCall::audioModeChanged, this, &VocaXmppClient::audioModeChanged);
+ m_call = nullptr;
+}
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+
+ VocaXmppClient client;
+ client.logger()->setLoggingType(QXmppLogger::StdoutLogging);
+ client.connectToServer(VOCASTI_XMPP_EMAIL, VOCASTI_XMPP_PASSWD);
+
+ return app.exec();
+}
diff --git a/main.h b/main.h
new file mode 100644
index 0000000..755a149
--- /dev/null
+++ b/main.h
@@ -0,0 +1,33 @@
+#ifndef VOCASTI_MAIN_H_
+#define VOCASTI_MAIN_H_
+
+#include
+#include
+#include
+#include
+
+class VocaXmppClient : public QXmppClient
+{
+ Q_OBJECT
+
+public:
+ VocaXmppClient(QObject *parent = nullptr);
+ ~VocaXmppClient() override;
+
+private slots:
+ void messageReceived(const QXmppMessage &);
+ void callConnected();
+ void callReceived(QXmppCall *call);
+ void callStarted(QXmppCall *call);
+ void callFinished();
+
+protected:
+ int setupPipe();
+
+ QXmppCall *m_call;
+ QXmppCallManager m_callManager;
+ QTimer m_timer;
+
+};
+
+#endif // VOCASTI_MAIN_H_
diff --git a/miku.webp b/miku.webp
new file mode 100755
index 0000000000000000000000000000000000000000..50f0f950cc1bfed064977249c56e2993652db789
GIT binary patch
literal 9350
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
A4*&oF
literal 0
HcmV?d00001
diff --git a/qxmpp b/qxmpp
new file mode 160000
index 0000000..7c189b0
--- /dev/null
+++ b/qxmpp
@@ -0,0 +1 @@
+Subproject commit 7c189b0cad72ad90134075586d7742f0fd4e7e1d