Remove old code (#59)
* Removed code * Updated readme
@@ -1,90 +0,0 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
maven { url "https://jitpack.io" }
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
defaultConfig {
|
||||
applicationId "com.example.mear"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DANDROID_STL=c++_shared", "-DANDROID=true"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
applicationIdSuffix = kotlin_version
|
||||
versionNameSuffix = kotlin_version
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "src/main/cpp/CMakeLists.txt"
|
||||
version "3.10.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def work_version = "2.2.0"
|
||||
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
// Kotlin + coroutines
|
||||
implementation "androidx.work:work-runtime-ktx:$work_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.0.0'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'com.ealva:ealvatag:0.4.3'
|
||||
implementation 'com.ealva:ealvalog:0.5.0'
|
||||
implementation 'com.ealva:ealvalog-core:0.5.0'
|
||||
implementation 'com.ealva:ealvalog-android:0.5.0'
|
||||
implementation 'com.github.XuDeveloper:XPopupWindow:1.0.1'
|
||||
// implementation 'com.google.guava:guava:27.0'
|
||||
implementation 'com.google.guava:guava:27.0.1-android'
|
||||
implementation 'com.squareup.okio:okio:2.4.0'
|
||||
implementation 'com.squareup.picasso:picasso:2.71828'
|
||||
implementation "org.jetbrains.anko:anko:0.10.8"
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61'
|
||||
|
||||
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
def requested = details.requested
|
||||
if (requested.group == 'com.android.support') {
|
||||
if (!requested.name.startsWith("multidex")) {
|
||||
details.useVersion '27.0.0'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.example.mear
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getTargetContext()
|
||||
assertEquals("com.example.mear", appContext.packageName)
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.example.mear">
|
||||
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".activities.IcarusSongActivity"></activity>
|
||||
<activity
|
||||
android:name=".activities.LoginActivity"
|
||||
android:label="@string/title_activity_main"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.SettingsActivity"
|
||||
android:label="@string/title_activity_settings"
|
||||
android:parentActivityName=".activities.MainActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="com.example.mear.activities.MainActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.MainActivity"
|
||||
android:label="@string/title_activity_main"
|
||||
android:parentActivityName=".activities.LoginActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="com.example.mear.activities.LoginActivity" />
|
||||
<!--
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
-->
|
||||
</activity>
|
||||
|
||||
<service android:name=".playback.service.MusicService" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,34 +0,0 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
###########################################################################
|
||||
pkginclude_HEADERS = \
|
||||
curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \
|
||||
typecheck-gcc.h system.h
|
||||
|
||||
pkgincludedir= $(includedir)/curl
|
||||
|
||||
checksrc:
|
||||
@@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS)
|
||||
|
||||
if CURLDEBUG
|
||||
# for debug builds, we scan the sources on all regular make invokes
|
||||
all-local: checksrc
|
||||
endif
|
||||
@@ -1,693 +0,0 @@
|
||||
# Makefile.in generated by automake 1.16.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = include/curl
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \
|
||||
$(top_srcdir)/m4/curl-compilers.m4 \
|
||||
$(top_srcdir)/m4/curl-confopts.m4 \
|
||||
$(top_srcdir)/m4/curl-functions.m4 \
|
||||
$(top_srcdir)/m4/curl-openssl.m4 \
|
||||
$(top_srcdir)/m4/curl-override.m4 \
|
||||
$(top_srcdir)/m4/curl-reentrant.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||
$(top_srcdir)/m4/xc-am-iface.m4 \
|
||||
$(top_srcdir)/m4/xc-cc-check.m4 \
|
||||
$(top_srcdir)/m4/xc-lt-iface.m4 \
|
||||
$(top_srcdir)/m4/xc-translit.m4 \
|
||||
$(top_srcdir)/m4/xc-val-flgs.m4 \
|
||||
$(top_srcdir)/m4/zz40-xc-ovr.m4 \
|
||||
$(top_srcdir)/m4/zz50-xc-ovr.m4 \
|
||||
$(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(pkginclude_HEADERS) \
|
||||
$(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/lib/curl_config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
am__installdirs = "$(DESTDIR)$(pkgincludedir)"
|
||||
HEADERS = $(pkginclude_HEADERS)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
pkgincludedir = $(includedir)/curl
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AS = @AS@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BLANK_AT_MAKETIME = @BLANK_AT_MAKETIME@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@
|
||||
CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
|
||||
CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@
|
||||
CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@
|
||||
CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
|
||||
CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
|
||||
CODE_COVERAGE_LIBS = @CODE_COVERAGE_LIBS@
|
||||
CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CPPFLAG_CURL_STATICLIB = @CPPFLAG_CURL_STATICLIB@
|
||||
CURLVERSION = @CURLVERSION@
|
||||
CURL_CA_BUNDLE = @CURL_CA_BUNDLE@
|
||||
CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@
|
||||
CURL_DISABLE_DICT = @CURL_DISABLE_DICT@
|
||||
CURL_DISABLE_FILE = @CURL_DISABLE_FILE@
|
||||
CURL_DISABLE_FTP = @CURL_DISABLE_FTP@
|
||||
CURL_DISABLE_GOPHER = @CURL_DISABLE_GOPHER@
|
||||
CURL_DISABLE_HTTP = @CURL_DISABLE_HTTP@
|
||||
CURL_DISABLE_IMAP = @CURL_DISABLE_IMAP@
|
||||
CURL_DISABLE_LDAP = @CURL_DISABLE_LDAP@
|
||||
CURL_DISABLE_LDAPS = @CURL_DISABLE_LDAPS@
|
||||
CURL_DISABLE_POP3 = @CURL_DISABLE_POP3@
|
||||
CURL_DISABLE_PROXY = @CURL_DISABLE_PROXY@
|
||||
CURL_DISABLE_RTSP = @CURL_DISABLE_RTSP@
|
||||
CURL_DISABLE_SMB = @CURL_DISABLE_SMB@
|
||||
CURL_DISABLE_SMTP = @CURL_DISABLE_SMTP@
|
||||
CURL_DISABLE_TELNET = @CURL_DISABLE_TELNET@
|
||||
CURL_DISABLE_TFTP = @CURL_DISABLE_TFTP@
|
||||
CURL_LT_SHLIB_VERSIONED_FLAVOUR = @CURL_LT_SHLIB_VERSIONED_FLAVOUR@
|
||||
CURL_NETWORK_AND_TIME_LIBS = @CURL_NETWORK_AND_TIME_LIBS@
|
||||
CURL_NETWORK_LIBS = @CURL_NETWORK_LIBS@
|
||||
CURL_WITH_MULTI_SSL = @CURL_WITH_MULTI_SSL@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFAULT_SSL_BACKEND = @DEFAULT_SSL_BACKEND@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ENABLE_SHARED = @ENABLE_SHARED@
|
||||
ENABLE_STATIC = @ENABLE_STATIC@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GCOV = @GCOV@
|
||||
GENHTML = @GENHTML@
|
||||
GREP = @GREP@
|
||||
HAVE_BROTLI = @HAVE_BROTLI@
|
||||
HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@
|
||||
HAVE_LDAP_SSL = @HAVE_LDAP_SSL@
|
||||
HAVE_LIBZ = @HAVE_LIBZ@
|
||||
HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@
|
||||
IDN_ENABLED = @IDN_ENABLED@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
IPV6_ENABLED = @IPV6_ENABLED@
|
||||
LCOV = @LCOV@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBCURL_LIBS = @LIBCURL_LIBS@
|
||||
LIBMETALINK_CPPFLAGS = @LIBMETALINK_CPPFLAGS@
|
||||
LIBMETALINK_LDFLAGS = @LIBMETALINK_LDFLAGS@
|
||||
LIBMETALINK_LIBS = @LIBMETALINK_LIBS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MANOPT = @MANOPT@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
NROFF = @NROFF@
|
||||
NSS_LIBS = @NSS_LIBS@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PERL = @PERL@
|
||||
PKGADD_NAME = @PKGADD_NAME@
|
||||
PKGADD_PKG = @PKGADD_PKG@
|
||||
PKGADD_VENDOR = @PKGADD_VENDOR@
|
||||
PKGCONFIG = @PKGCONFIG@
|
||||
RANDOM_FILE = @RANDOM_FILE@
|
||||
RANLIB = @RANLIB@
|
||||
REQUIRE_LIB_DEPS = @REQUIRE_LIB_DEPS@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL_BACKENDS = @SSL_BACKENDS@
|
||||
SSL_ENABLED = @SSL_ENABLED@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STRIP = @STRIP@
|
||||
SUPPORT_FEATURES = @SUPPORT_FEATURES@
|
||||
SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@
|
||||
USE_ARES = @USE_ARES@
|
||||
USE_AXTLS = @USE_AXTLS@
|
||||
USE_CYASSL = @USE_CYASSL@
|
||||
USE_DARWINSSL = @USE_DARWINSSL@
|
||||
USE_GNUTLS = @USE_GNUTLS@
|
||||
USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@
|
||||
USE_LIBRTMP = @USE_LIBRTMP@
|
||||
USE_LIBSSH = @USE_LIBSSH@
|
||||
USE_LIBSSH2 = @USE_LIBSSH2@
|
||||
USE_MBEDTLS = @USE_MBEDTLS@
|
||||
USE_NGHTTP2 = @USE_NGHTTP2@
|
||||
USE_NSS = @USE_NSS@
|
||||
USE_OPENLDAP = @USE_OPENLDAP@
|
||||
USE_POLARSSL = @USE_POLARSSL@
|
||||
USE_SCHANNEL = @USE_SCHANNEL@
|
||||
USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@
|
||||
USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@
|
||||
VERSION = @VERSION@
|
||||
VERSIONNUM = @VERSIONNUM@
|
||||
ZLIB_LIBS = @ZLIB_LIBS@
|
||||
ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
libext = @libext@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
subdirs = @subdirs@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
###########################################################################
|
||||
pkginclude_HEADERS = \
|
||||
curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \
|
||||
typecheck-gcc.h system.h
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/curl/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu include/curl/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
install-pkgincludeHEADERS: $(pkginclude_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \
|
||||
$(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \
|
||||
done
|
||||
|
||||
uninstall-pkgincludeHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
|
||||
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
|
||||
dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir)
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-am
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-am
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscopelist: cscopelist-am
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
distdir-am: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
@CURLDEBUG_FALSE@all-local:
|
||||
all-am: Makefile $(HEADERS) all-local
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(pkgincludedir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-pkgincludeHEADERS
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-pkgincludeHEADERS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \
|
||||
clean-generic clean-libtool cscopelist-am ctags ctags-am \
|
||||
distclean distclean-generic distclean-libtool distclean-tags \
|
||||
distdir dvi dvi-am html html-am info info-am install \
|
||||
install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-pkgincludeHEADERS \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||
uninstall-am uninstall-pkgincludeHEADERS
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
checksrc:
|
||||
@@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS)
|
||||
|
||||
# for debug builds, we scan the sources on all regular make invokes
|
||||
@CURLDEBUG_TRUE@all-local: checksrc
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
@@ -1,77 +0,0 @@
|
||||
#ifndef __CURL_CURLVER_H
|
||||
#define __CURL_CURLVER_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* This header file contains nothing but libcurl version info, generated by
|
||||
a script at release-time. This was made its own header file in 7.11.2 */
|
||||
|
||||
/* This is the global package copyright */
|
||||
#define LIBCURL_COPYRIGHT "1996 - 2018 Daniel Stenberg, <daniel@haxx.se>."
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.60.0-DEV"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 60
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
||||
always follow this syntax:
|
||||
|
||||
0xXXYYZZ
|
||||
|
||||
Where XX, YY and ZZ are the main version, release and patch numbers in
|
||||
hexadecimal (using 8 bits each). All three numbers are always represented
|
||||
using two digits. 1.2 would appear as "0x010200" while version 9.11.7
|
||||
appears as "0x090b07".
|
||||
|
||||
This 6-digit (24 bits) hexadecimal number does not show pre-release number,
|
||||
and it is always a greater number in a more recent release. It makes
|
||||
comparisons with greater than and less than work.
|
||||
|
||||
Note: This define is the full hex number and _does not_ use the
|
||||
CURL_VERSION_BITS() macro since curl's own configure script greps for it
|
||||
and needs it to contain the full number.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x073C00
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
* timestamp is not stored in git, as the timestamp is properly set in the
|
||||
* tarballs by the maketgz script.
|
||||
*
|
||||
* The format of the date follows this template:
|
||||
*
|
||||
* "2007-11-23"
|
||||
*/
|
||||
#define LIBCURL_TIMESTAMP "[unreleased]"
|
||||
|
||||
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
|
||||
#define CURL_AT_LEAST_VERSION(x,y,z) \
|
||||
(LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
|
||||
|
||||
#endif /* __CURL_CURLVER_H */
|
||||
@@ -1,102 +0,0 @@
|
||||
#ifndef __CURL_EASY_H
|
||||
#define __CURL_EASY_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
CURL_EXTERN CURL *curl_easy_init(void);
|
||||
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
|
||||
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
|
||||
CURL_EXTERN void curl_easy_cleanup(CURL *curl);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_getinfo()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Request internal information from the curl session with this function. The
|
||||
* third argument MUST be a pointer to a long, a pointer to a char * or a
|
||||
* pointer to a double (as the documentation describes elsewhere). The data
|
||||
* pointed to will be filled in accordingly and can be relied upon only if the
|
||||
* function returns CURLE_OK. This function is intended to get used *AFTER* a
|
||||
* performed transfer, all results from this function are undefined until the
|
||||
* transfer is completed.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
|
||||
|
||||
|
||||
/*
|
||||
* NAME curl_easy_duphandle()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Creates a new curl session handle with the same options set for the handle
|
||||
* passed in. Duplicating a handle could only be a matter of cloning data and
|
||||
* options, internal state info and things like persistent connections cannot
|
||||
* be transferred. It is useful in multithreaded applications when you can run
|
||||
* curl_easy_duphandle() for each new thread to avoid a series of identical
|
||||
* curl_easy_setopt() invokes in every thread.
|
||||
*/
|
||||
CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_reset()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Re-initializes a CURL handle to the default values. This puts back the
|
||||
* handle to the same state as it was in when it was just created.
|
||||
*
|
||||
* It does keep: live connections, the Session ID cache, the DNS cache and the
|
||||
* cookies.
|
||||
*/
|
||||
CURL_EXTERN void curl_easy_reset(CURL *curl);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_recv()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Receives data from the connected socket. Use after successful
|
||||
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
|
||||
size_t *n);
|
||||
|
||||
/*
|
||||
* NAME curl_easy_send()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Sends data over the connected socket. Use after successful
|
||||
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
|
||||
size_t buflen, size_t *n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,50 +0,0 @@
|
||||
#ifndef __CURL_MPRINTF_H
|
||||
#define __CURL_MPRINTF_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h> /* needed for FILE */
|
||||
#include "curl.h" /* for CURL_EXTERN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
CURL_EXTERN int curl_mprintf(const char *format, ...);
|
||||
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
|
||||
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
|
||||
CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
|
||||
const char *format, ...);
|
||||
CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
|
||||
CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
|
||||
CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
|
||||
CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
|
||||
const char *format, va_list args);
|
||||
CURL_EXTERN char *curl_maprintf(const char *format, ...);
|
||||
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CURL_MPRINTF_H */
|
||||
@@ -1,441 +0,0 @@
|
||||
#ifndef __CURL_MULTI_H
|
||||
#define __CURL_MULTI_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
/*
|
||||
This is an "external" header file. Don't give away any internals here!
|
||||
|
||||
GOALS
|
||||
|
||||
o Enable a "pull" interface. The application that uses libcurl decides where
|
||||
and when to ask libcurl to get/send data.
|
||||
|
||||
o Enable multiple simultaneous transfers in the same thread without making it
|
||||
complicated for the application.
|
||||
|
||||
o Enable the application to select() on its own file descriptors and curl's
|
||||
file descriptors simultaneous easily.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* This header file should not really need to include "curl.h" since curl.h
|
||||
* itself includes this file and we expect user applications to do #include
|
||||
* <curl/curl.h> without the need for especially including multi.h.
|
||||
*
|
||||
* For some reason we added this include here at one point, and rather than to
|
||||
* break existing (wrongly written) libcurl applications, we leave it as-is
|
||||
* but with this warning attached.
|
||||
*/
|
||||
#include "curl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
|
||||
typedef struct Curl_multi CURLM;
|
||||
#else
|
||||
typedef void CURLM;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
|
||||
curl_multi_socket*() soon */
|
||||
CURLM_OK,
|
||||
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
|
||||
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
|
||||
CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
|
||||
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
|
||||
CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
|
||||
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
|
||||
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
|
||||
attempted to get added - again */
|
||||
CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
|
||||
callback */
|
||||
CURLM_LAST
|
||||
} CURLMcode;
|
||||
|
||||
/* just to make code nicer when using curl_multi_socket() you can now check
|
||||
for CURLM_CALL_MULTI_SOCKET too in the same style it works for
|
||||
curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
|
||||
#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
|
||||
|
||||
/* bitmask bits for CURLMOPT_PIPELINING */
|
||||
#define CURLPIPE_NOTHING 0L
|
||||
#define CURLPIPE_HTTP1 1L
|
||||
#define CURLPIPE_MULTIPLEX 2L
|
||||
|
||||
typedef enum {
|
||||
CURLMSG_NONE, /* first, not used */
|
||||
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
|
||||
the CURLcode of the transfer */
|
||||
CURLMSG_LAST /* last, not used */
|
||||
} CURLMSG;
|
||||
|
||||
struct CURLMsg {
|
||||
CURLMSG msg; /* what this message means */
|
||||
CURL *easy_handle; /* the handle it concerns */
|
||||
union {
|
||||
void *whatever; /* message-specific data */
|
||||
CURLcode result; /* return code for transfer */
|
||||
} data;
|
||||
};
|
||||
typedef struct CURLMsg CURLMsg;
|
||||
|
||||
/* Based on poll(2) structure and values.
|
||||
* We don't use pollfd and POLL* constants explicitly
|
||||
* to cover platforms without poll(). */
|
||||
#define CURL_WAIT_POLLIN 0x0001
|
||||
#define CURL_WAIT_POLLPRI 0x0002
|
||||
#define CURL_WAIT_POLLOUT 0x0004
|
||||
|
||||
struct curl_waitfd {
|
||||
curl_socket_t fd;
|
||||
short events;
|
||||
short revents; /* not supported yet */
|
||||
};
|
||||
|
||||
/*
|
||||
* Name: curl_multi_init()
|
||||
*
|
||||
* Desc: inititalize multi-style curl usage
|
||||
*
|
||||
* Returns: a new CURLM handle to use in all 'curl_multi' functions.
|
||||
*/
|
||||
CURL_EXTERN CURLM *curl_multi_init(void);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_add_handle()
|
||||
*
|
||||
* Desc: add a standard curl handle to the multi stack
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
|
||||
CURL *curl_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_remove_handle()
|
||||
*
|
||||
* Desc: removes a curl handle from the multi stack again
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
CURL *curl_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_fdset()
|
||||
*
|
||||
* Desc: Ask curl for its fd_set sets. The app can use these to select() or
|
||||
* poll() on. We want curl_multi_perform() called as soon as one of
|
||||
* them are ready.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *exc_fd_set,
|
||||
int *max_fd);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_wait()
|
||||
*
|
||||
* Desc: Poll on all fds within a CURLM set as well as any
|
||||
* additional fds passed to the function.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
|
||||
struct curl_waitfd extra_fds[],
|
||||
unsigned int extra_nfds,
|
||||
int timeout_ms,
|
||||
int *ret);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_perform()
|
||||
*
|
||||
* Desc: When the app thinks there's data available for curl it calls this
|
||||
* function to read/write whatever there is right now. This returns
|
||||
* as soon as the reads and writes are done. This function does not
|
||||
* require that there actually is data available for reading or that
|
||||
* data can be written, it can be called just in case. It returns
|
||||
* the number of handles that still transfer data in the second
|
||||
* argument's integer-pointer.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
|
||||
* returns errors etc regarding the whole multi stack. There might
|
||||
* still have occurred problems on individual transfers even when
|
||||
* this returns OK.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
|
||||
int *running_handles);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_cleanup()
|
||||
*
|
||||
* Desc: Cleans up and removes a whole multi stack. It does not free or
|
||||
* touch any individual easy handles in any way. We need to define
|
||||
* in what state those handles will be if this function is called
|
||||
* in the middle of a transfer.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_info_read()
|
||||
*
|
||||
* Desc: Ask the multi handle if there's any messages/informationals from
|
||||
* the individual transfers. Messages include informationals such as
|
||||
* error code from the transfer or just the fact that a transfer is
|
||||
* completed. More details on these should be written down as well.
|
||||
*
|
||||
* Repeated calls to this function will return a new struct each
|
||||
* time, until a special "end of msgs" struct is returned as a signal
|
||||
* that there is no more to get at this point.
|
||||
*
|
||||
* The data the returned pointer points to will not survive calling
|
||||
* curl_multi_cleanup().
|
||||
*
|
||||
* The 'CURLMsg' struct is meant to be very simple and only contain
|
||||
* very basic information. If more involved information is wanted,
|
||||
* we will provide the particular "transfer handle" in that struct
|
||||
* and that should/could/would be used in subsequent
|
||||
* curl_easy_getinfo() calls (or similar). The point being that we
|
||||
* must never expose complex structs to applications, as then we'll
|
||||
* undoubtably get backwards compatibility problems in the future.
|
||||
*
|
||||
* Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
|
||||
* of structs. It also writes the number of messages left in the
|
||||
* queue (after this read) in the integer the second argument points
|
||||
* to.
|
||||
*/
|
||||
CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
|
||||
int *msgs_in_queue);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_strerror()
|
||||
*
|
||||
* Desc: The curl_multi_strerror function may be used to turn a CURLMcode
|
||||
* value into the equivalent human readable error string. This is
|
||||
* useful for printing meaningful error messages.
|
||||
*
|
||||
* Returns: A pointer to a zero-terminated error message.
|
||||
*/
|
||||
CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_socket() and
|
||||
* curl_multi_socket_all()
|
||||
*
|
||||
* Desc: An alternative version of curl_multi_perform() that allows the
|
||||
* application to pass in one of the file descriptors that have been
|
||||
* detected to have "action" on them and let libcurl perform.
|
||||
* See man page for details.
|
||||
*/
|
||||
#define CURL_POLL_NONE 0
|
||||
#define CURL_POLL_IN 1
|
||||
#define CURL_POLL_OUT 2
|
||||
#define CURL_POLL_INOUT 3
|
||||
#define CURL_POLL_REMOVE 4
|
||||
|
||||
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
|
||||
|
||||
#define CURL_CSELECT_IN 0x01
|
||||
#define CURL_CSELECT_OUT 0x02
|
||||
#define CURL_CSELECT_ERR 0x04
|
||||
|
||||
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
|
||||
curl_socket_t s, /* socket */
|
||||
int what, /* see above */
|
||||
void *userp, /* private callback
|
||||
pointer */
|
||||
void *socketp); /* private socket
|
||||
pointer */
|
||||
/*
|
||||
* Name: curl_multi_timer_callback
|
||||
*
|
||||
* Desc: Called by libcurl whenever the library detects a change in the
|
||||
* maximum number of milliseconds the app is allowed to wait before
|
||||
* curl_multi_socket() or curl_multi_perform() must be called
|
||||
* (to allow libcurl's timed events to take place).
|
||||
*
|
||||
* Returns: The callback should return zero.
|
||||
*/
|
||||
typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
|
||||
long timeout_ms, /* see above */
|
||||
void *userp); /* private callback
|
||||
pointer */
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
|
||||
int *running_handles);
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
|
||||
curl_socket_t s,
|
||||
int ev_bitmask,
|
||||
int *running_handles);
|
||||
|
||||
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
|
||||
int *running_handles);
|
||||
|
||||
#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
|
||||
/* This macro below was added in 7.16.3 to push users who recompile to use
|
||||
the new curl_multi_socket_action() instead of the old curl_multi_socket()
|
||||
*/
|
||||
#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Name: curl_multi_timeout()
|
||||
*
|
||||
* Desc: Returns the maximum number of milliseconds the app is allowed to
|
||||
* wait before curl_multi_socket() or curl_multi_perform() must be
|
||||
* called (to allow libcurl's timed events to take place).
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
|
||||
long *milliseconds);
|
||||
|
||||
#undef CINIT /* re-using the same name as in curl.h */
|
||||
|
||||
#ifdef CURL_ISOCPP
|
||||
#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
|
||||
#else
|
||||
/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
|
||||
#define LONG CURLOPTTYPE_LONG
|
||||
#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
|
||||
#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
|
||||
#define OFF_T CURLOPTTYPE_OFF_T
|
||||
#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
/* This is the socket callback function pointer */
|
||||
CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
|
||||
|
||||
/* This is the argument passed to the socket callback */
|
||||
CINIT(SOCKETDATA, OBJECTPOINT, 2),
|
||||
|
||||
/* set to 1 to enable pipelining for this multi handle */
|
||||
CINIT(PIPELINING, LONG, 3),
|
||||
|
||||
/* This is the timer callback function pointer */
|
||||
CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
|
||||
|
||||
/* This is the argument passed to the timer callback */
|
||||
CINIT(TIMERDATA, OBJECTPOINT, 5),
|
||||
|
||||
/* maximum number of entries in the connection cache */
|
||||
CINIT(MAXCONNECTS, LONG, 6),
|
||||
|
||||
/* maximum number of (pipelining) connections to one host */
|
||||
CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
|
||||
|
||||
/* maximum number of requests in a pipeline */
|
||||
CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
|
||||
|
||||
/* a connection with a content-length longer than this
|
||||
will not be considered for pipelining */
|
||||
CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
|
||||
|
||||
/* a connection with a chunk length longer than this
|
||||
will not be considered for pipelining */
|
||||
CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
|
||||
|
||||
/* a list of site names(+port) that are blacklisted from
|
||||
pipelining */
|
||||
CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
|
||||
|
||||
/* a list of server types that are blacklisted from
|
||||
pipelining */
|
||||
CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
|
||||
|
||||
/* maximum number of open connections in total */
|
||||
CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
|
||||
|
||||
/* This is the server push callback function pointer */
|
||||
CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14),
|
||||
|
||||
/* This is the argument passed to the server push callback */
|
||||
CINIT(PUSHDATA, OBJECTPOINT, 15),
|
||||
|
||||
CURLMOPT_LASTENTRY /* the last unused */
|
||||
} CURLMoption;
|
||||
|
||||
|
||||
/*
|
||||
* Name: curl_multi_setopt()
|
||||
*
|
||||
* Desc: Sets options for the multi handle.
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
|
||||
CURLMoption option, ...);
|
||||
|
||||
|
||||
/*
|
||||
* Name: curl_multi_assign()
|
||||
*
|
||||
* Desc: This function sets an association in the multi handle between the
|
||||
* given socket and a private pointer of the application. This is
|
||||
* (only) useful for curl_multi_socket uses.
|
||||
*
|
||||
* Returns: CURLM error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
|
||||
curl_socket_t sockfd, void *sockp);
|
||||
|
||||
|
||||
/*
|
||||
* Name: curl_push_callback
|
||||
*
|
||||
* Desc: This callback gets called when a new stream is being pushed by the
|
||||
* server. It approves or denies the new stream.
|
||||
*
|
||||
* Returns: CURL_PUSH_OK or CURL_PUSH_DENY.
|
||||
*/
|
||||
#define CURL_PUSH_OK 0
|
||||
#define CURL_PUSH_DENY 1
|
||||
|
||||
struct curl_pushheaders; /* forward declaration only */
|
||||
|
||||
CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h,
|
||||
size_t num);
|
||||
CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h,
|
||||
const char *name);
|
||||
|
||||
typedef int (*curl_push_callback)(CURL *parent,
|
||||
CURL *easy,
|
||||
size_t num_headers,
|
||||
struct curl_pushheaders *headers,
|
||||
void *userp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,33 +0,0 @@
|
||||
#ifndef __STDC_HEADERS_H
|
||||
#define __STDC_HEADERS_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
size_t fread(void *, size_t, size_t, FILE *);
|
||||
size_t fwrite(const void *, size_t, size_t, FILE *);
|
||||
|
||||
int strcasecmp(const char *, const char *);
|
||||
int strncasecmp(const char *, const char *, size_t);
|
||||
|
||||
#endif /* __STDC_HEADERS_H */
|
||||
@@ -1,475 +0,0 @@
|
||||
#ifndef __CURL_SYSTEM_H
|
||||
#define __CURL_SYSTEM_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Try to keep one section per platform, compiler and architecture, otherwise,
|
||||
* if an existing section is reused for a different one and later on the
|
||||
* original is adjusted, probably the piggybacking one can be adversely
|
||||
* changed.
|
||||
*
|
||||
* In order to differentiate between platforms/compilers/architectures use
|
||||
* only compiler built in predefined preprocessor symbols.
|
||||
*
|
||||
* curl_off_t
|
||||
* ----------
|
||||
*
|
||||
* For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit
|
||||
* wide signed integral data type. The width of this data type must remain
|
||||
* constant and independent of any possible large file support settings.
|
||||
*
|
||||
* As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit
|
||||
* wide signed integral data type if there is no 64-bit type.
|
||||
*
|
||||
* As a general rule, curl_off_t shall not be mapped to off_t. This rule shall
|
||||
* only be violated if off_t is the only 64-bit data type available and the
|
||||
* size of off_t is independent of large file support settings. Keep your
|
||||
* build on the safe side avoiding an off_t gating. If you have a 64-bit
|
||||
* off_t then take for sure that another 64-bit data type exists, dig deeper
|
||||
* and you will find it.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(__DJGPP__) || defined(__GO32__)
|
||||
# if defined(__DJGPP__) && (__DJGPP__ > 1)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__SALFORDC__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__BORLANDC__)
|
||||
# if (__BORLANDC__ < 0x520)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__TURBOC__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__WATCOMC__)
|
||||
# if defined(__386__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__POCC__)
|
||||
# if (__POCC__ < 280)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# elif defined(_MSC_VER)
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__LCC__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__SYMBIAN32__)
|
||||
# if defined(__EABI__) /* Treat all ARM compilers equally */
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(__CW32__)
|
||||
# pragma longlong on
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(__VC32__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
|
||||
|
||||
#elif defined(__MWERKS__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(_WIN32_WCE)
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__MINGW32__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_WS2TCPIP_H 1
|
||||
|
||||
#elif defined(__VMS)
|
||||
# if defined(__VAX)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
|
||||
|
||||
#elif defined(__OS400__)
|
||||
# if defined(__ILEC400__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
# endif
|
||||
|
||||
#elif defined(__MVS__)
|
||||
# if defined(__IBMC__) || defined(__IBMCPP__)
|
||||
# if defined(_ILP32)
|
||||
# elif defined(_LP64)
|
||||
# endif
|
||||
# if defined(_LONG_LONG)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(_LP64)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
# endif
|
||||
|
||||
#elif defined(__370__)
|
||||
# if defined(__IBMC__) || defined(__IBMCPP__)
|
||||
# if defined(_ILP32)
|
||||
# elif defined(_LP64)
|
||||
# endif
|
||||
# if defined(_LONG_LONG)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(_LP64)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
# endif
|
||||
|
||||
#elif defined(TPF)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__TINYC__) /* also known as tcc */
|
||||
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
#elif defined(__SUNPRO_C) /* Oracle Solaris Studio */
|
||||
# if !defined(__LP64) && (defined(__ILP32) || \
|
||||
defined(__i386) || \
|
||||
defined(__sparcv8) || \
|
||||
defined(__sparcv8plus))
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(__LP64) || \
|
||||
defined(__amd64) || defined(__sparcv9)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
/* ===================================== */
|
||||
/* KEEP MSVC THE PENULTIMATE ENTRY */
|
||||
/* ===================================== */
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
|
||||
# define CURL_TYPEOF_CURL_OFF_T __int64
|
||||
# define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
# define CURL_SUFFIX_CURL_OFF_T i64
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ui64
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
/* ===================================== */
|
||||
/* KEEP GENERIC GCC THE LAST ENTRY */
|
||||
/* ===================================== */
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
# if !defined(__LP64__) && \
|
||||
(defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \
|
||||
defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \
|
||||
defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
|
||||
defined(__XTENSA__) || \
|
||||
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \
|
||||
(defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L))
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(__LP64__) || \
|
||||
defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
|
||||
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
|
||||
(defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
#else
|
||||
/* generic "safe guess" on old 32 bit style */
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
#endif
|
||||
|
||||
#ifdef _AIX
|
||||
/* AIX needs <sys/poll.h> */
|
||||
#define CURL_PULL_SYS_POLL_H
|
||||
#endif
|
||||
|
||||
|
||||
/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */
|
||||
/* ws2tcpip.h is required here to properly make type definitions below. */
|
||||
#ifdef CURL_PULL_WS2TCPIP_H
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
# include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */
|
||||
/* sys/types.h is required here to properly make type definitions below. */
|
||||
#ifdef CURL_PULL_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */
|
||||
/* sys/socket.h is required here to properly make type definitions below. */
|
||||
#ifdef CURL_PULL_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */
|
||||
/* sys/poll.h is required here to properly make type definitions below. */
|
||||
#ifdef CURL_PULL_SYS_POLL_H
|
||||
# include <sys/poll.h>
|
||||
#endif
|
||||
|
||||
/* Data type definition of curl_socklen_t. */
|
||||
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
|
||||
typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
|
||||
#endif
|
||||
|
||||
/* Data type definition of curl_off_t. */
|
||||
|
||||
#ifdef CURL_TYPEOF_CURL_OFF_T
|
||||
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
|
||||
* these to be visible and exported by the external libcurl interface API,
|
||||
* while also making them visible to the library internals, simply including
|
||||
* curl_setup.h, without actually needing to include curl.h internally.
|
||||
* If some day this section would grow big enough, all this should be moved
|
||||
* to its own header file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Figure out if we can use the ## preprocessor operator, which is supported
|
||||
* by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
|
||||
* or __cplusplus so we need to carefully check for them too.
|
||||
*/
|
||||
|
||||
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
|
||||
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
|
||||
defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
|
||||
defined(__ILEC400__)
|
||||
/* This compiler is believed to have an ISO compatible preprocessor */
|
||||
#define CURL_ISOCPP
|
||||
#else
|
||||
/* This compiler is believed NOT to have an ISO compatible preprocessor */
|
||||
#undef CURL_ISOCPP
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros for minimum-width signed and unsigned curl_off_t integer constants.
|
||||
*/
|
||||
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
|
||||
# define __CURL_OFF_T_C_HLPR2(x) x
|
||||
# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
|
||||
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
|
||||
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
|
||||
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
|
||||
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
|
||||
#else
|
||||
# ifdef CURL_ISOCPP
|
||||
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
|
||||
# else
|
||||
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
|
||||
# endif
|
||||
# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
|
||||
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
|
||||
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
|
||||
#endif
|
||||
|
||||
#endif /* __CURL_SYSTEM_H */
|
||||
@@ -1,696 +0,0 @@
|
||||
#ifndef __CURL_TYPECHECK_GCC_H
|
||||
#define __CURL_TYPECHECK_GCC_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* wraps curl_easy_setopt() with typechecking */
|
||||
|
||||
/* To add a new kind of warning, add an
|
||||
* if(_curl_is_sometype_option(_curl_opt))
|
||||
* if(!_curl_is_sometype(value))
|
||||
* _curl_easy_setopt_err_sometype();
|
||||
* block and define _curl_is_sometype_option, _curl_is_sometype and
|
||||
* _curl_easy_setopt_err_sometype below
|
||||
*
|
||||
* NOTE: We use two nested 'if' statements here instead of the && operator, in
|
||||
* order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x
|
||||
* when compiling with -Wlogical-op.
|
||||
*
|
||||
* To add an option that uses the same type as an existing option, you'll just
|
||||
* need to extend the appropriate _curl_*_option macro
|
||||
*/
|
||||
#define curl_easy_setopt(handle, option, value) \
|
||||
__extension__ ({ \
|
||||
__typeof__(option) _curl_opt = option; \
|
||||
if(__builtin_constant_p(_curl_opt)) { \
|
||||
if(_curl_is_long_option(_curl_opt)) \
|
||||
if(!_curl_is_long(value)) \
|
||||
_curl_easy_setopt_err_long(); \
|
||||
if(_curl_is_off_t_option(_curl_opt)) \
|
||||
if(!_curl_is_off_t(value)) \
|
||||
_curl_easy_setopt_err_curl_off_t(); \
|
||||
if(_curl_is_string_option(_curl_opt)) \
|
||||
if(!_curl_is_string(value)) \
|
||||
_curl_easy_setopt_err_string(); \
|
||||
if(_curl_is_write_cb_option(_curl_opt)) \
|
||||
if(!_curl_is_write_cb(value)) \
|
||||
_curl_easy_setopt_err_write_callback(); \
|
||||
if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
|
||||
if(!_curl_is_resolver_start_callback(value)) \
|
||||
_curl_easy_setopt_err_resolver_start_callback(); \
|
||||
if((_curl_opt) == CURLOPT_READFUNCTION) \
|
||||
if(!_curl_is_read_cb(value)) \
|
||||
_curl_easy_setopt_err_read_cb(); \
|
||||
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
|
||||
if(!_curl_is_ioctl_cb(value)) \
|
||||
_curl_easy_setopt_err_ioctl_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
|
||||
if(!_curl_is_sockopt_cb(value)) \
|
||||
_curl_easy_setopt_err_sockopt_cb(); \
|
||||
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
|
||||
if(!_curl_is_opensocket_cb(value)) \
|
||||
_curl_easy_setopt_err_opensocket_cb(); \
|
||||
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
|
||||
if(!_curl_is_progress_cb(value)) \
|
||||
_curl_easy_setopt_err_progress_cb(); \
|
||||
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
|
||||
if(!_curl_is_debug_cb(value)) \
|
||||
_curl_easy_setopt_err_debug_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
|
||||
if(!_curl_is_ssl_ctx_cb(value)) \
|
||||
_curl_easy_setopt_err_ssl_ctx_cb(); \
|
||||
if(_curl_is_conv_cb_option(_curl_opt)) \
|
||||
if(!_curl_is_conv_cb(value)) \
|
||||
_curl_easy_setopt_err_conv_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
|
||||
if(!_curl_is_seek_cb(value)) \
|
||||
_curl_easy_setopt_err_seek_cb(); \
|
||||
if(_curl_is_cb_data_option(_curl_opt)) \
|
||||
if(!_curl_is_cb_data(value)) \
|
||||
_curl_easy_setopt_err_cb_data(); \
|
||||
if((_curl_opt) == CURLOPT_ERRORBUFFER) \
|
||||
if(!_curl_is_error_buffer(value)) \
|
||||
_curl_easy_setopt_err_error_buffer(); \
|
||||
if((_curl_opt) == CURLOPT_STDERR) \
|
||||
if(!_curl_is_FILE(value)) \
|
||||
_curl_easy_setopt_err_FILE(); \
|
||||
if(_curl_is_postfields_option(_curl_opt)) \
|
||||
if(!_curl_is_postfields(value)) \
|
||||
_curl_easy_setopt_err_postfields(); \
|
||||
if((_curl_opt) == CURLOPT_HTTPPOST) \
|
||||
if(!_curl_is_arr((value), struct curl_httppost)) \
|
||||
_curl_easy_setopt_err_curl_httpost(); \
|
||||
if((_curl_opt) == CURLOPT_MIMEPOST) \
|
||||
if(!_curl_is_ptr((value), curl_mime)) \
|
||||
_curl_easy_setopt_err_curl_mimepost(); \
|
||||
if(_curl_is_slist_option(_curl_opt)) \
|
||||
if(!_curl_is_arr((value), struct curl_slist)) \
|
||||
_curl_easy_setopt_err_curl_slist(); \
|
||||
if((_curl_opt) == CURLOPT_SHARE) \
|
||||
if(!_curl_is_ptr((value), CURLSH)) \
|
||||
_curl_easy_setopt_err_CURLSH(); \
|
||||
} \
|
||||
curl_easy_setopt(handle, _curl_opt, value); \
|
||||
})
|
||||
|
||||
/* wraps curl_easy_getinfo() with typechecking */
|
||||
/* FIXME: don't allow const pointers */
|
||||
#define curl_easy_getinfo(handle, info, arg) \
|
||||
__extension__ ({ \
|
||||
__typeof__(info) _curl_info = info; \
|
||||
if(__builtin_constant_p(_curl_info)) { \
|
||||
if(_curl_is_string_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), char *)) \
|
||||
_curl_easy_getinfo_err_string(); \
|
||||
if(_curl_is_long_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), long)) \
|
||||
_curl_easy_getinfo_err_long(); \
|
||||
if(_curl_is_double_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), double)) \
|
||||
_curl_easy_getinfo_err_double(); \
|
||||
if(_curl_is_slist_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_slist *)) \
|
||||
_curl_easy_getinfo_err_curl_slist(); \
|
||||
if(_curl_is_tlssessioninfo_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \
|
||||
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
|
||||
if(_curl_is_certinfo_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_certinfo *)) \
|
||||
_curl_easy_getinfo_err_curl_certinfo(); \
|
||||
if(_curl_is_socket_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), curl_socket_t)) \
|
||||
_curl_easy_getinfo_err_curl_socket(); \
|
||||
if(_curl_is_off_t_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), curl_off_t)) \
|
||||
_curl_easy_getinfo_err_curl_off_t(); \
|
||||
} \
|
||||
curl_easy_getinfo(handle, _curl_info, arg); \
|
||||
})
|
||||
|
||||
/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
|
||||
* for now just make sure that the functions are called with three
|
||||
* arguments
|
||||
*/
|
||||
#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
|
||||
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
|
||||
|
||||
|
||||
/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
|
||||
* functions */
|
||||
|
||||
/* To define a new warning, use _CURL_WARNING(identifier, "message") */
|
||||
#define _CURL_WARNING(id, message) \
|
||||
static void __attribute__((__warning__(message))) \
|
||||
__attribute__((__unused__)) __attribute__((__noinline__)) \
|
||||
id(void) { __asm__(""); }
|
||||
|
||||
_CURL_WARNING(_curl_easy_setopt_err_long,
|
||||
"curl_easy_setopt expects a long argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
|
||||
"curl_easy_setopt expects a curl_off_t argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_string,
|
||||
"curl_easy_setopt expects a "
|
||||
"string ('char *' or char[]) argument for this option"
|
||||
)
|
||||
_CURL_WARNING(_curl_easy_setopt_err_write_callback,
|
||||
"curl_easy_setopt expects a curl_write_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_resolver_start_callback,
|
||||
"curl_easy_setopt expects a "
|
||||
"curl_resolver_start_callback argument for this option"
|
||||
)
|
||||
_CURL_WARNING(_curl_easy_setopt_err_read_cb,
|
||||
"curl_easy_setopt expects a curl_read_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
|
||||
"curl_easy_setopt expects a curl_ioctl_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
|
||||
"curl_easy_setopt expects a curl_sockopt_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
|
||||
"curl_easy_setopt expects a "
|
||||
"curl_opensocket_callback argument for this option"
|
||||
)
|
||||
_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
|
||||
"curl_easy_setopt expects a curl_progress_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
|
||||
"curl_easy_setopt expects a curl_debug_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
|
||||
"curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
|
||||
"curl_easy_setopt expects a curl_conv_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
|
||||
"curl_easy_setopt expects a curl_seek_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_cb_data,
|
||||
"curl_easy_setopt expects a "
|
||||
"private data pointer as argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
|
||||
"curl_easy_setopt expects a "
|
||||
"char buffer of CURL_ERROR_SIZE as argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_FILE,
|
||||
"curl_easy_setopt expects a 'FILE *' argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_postfields,
|
||||
"curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
|
||||
"curl_easy_setopt expects a 'struct curl_httppost *' "
|
||||
"argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_mimepost,
|
||||
"curl_easy_setopt expects a 'curl_mime *' "
|
||||
"argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
|
||||
"curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
|
||||
"curl_easy_setopt expects a CURLSH* argument for this option")
|
||||
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_string,
|
||||
"curl_easy_getinfo expects a pointer to 'char *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_long,
|
||||
"curl_easy_getinfo expects a pointer to long for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_double,
|
||||
"curl_easy_getinfo expects a pointer to double for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
"curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
|
||||
"curl_easy_getinfo expects a pointer to "
|
||||
"'struct curl_tlssessioninfo *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo,
|
||||
"curl_easy_getinfo expects a pointer to "
|
||||
"'struct curl_certinfo *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_socket,
|
||||
"curl_easy_getinfo expects a pointer to curl_socket_t for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
"curl_easy_getinfo expects a pointer to curl_off_t for this info")
|
||||
|
||||
/* groups of curl_easy_setops options that take the same type of argument */
|
||||
|
||||
/* To add a new option to one of the groups, just add
|
||||
* (option) == CURLOPT_SOMETHING
|
||||
* to the or-expression. If the option takes a long or curl_off_t, you don't
|
||||
* have to do anything
|
||||
*/
|
||||
|
||||
/* evaluates to true if option takes a long argument */
|
||||
#define _curl_is_long_option(option) \
|
||||
(0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
|
||||
|
||||
#define _curl_is_off_t_option(option) \
|
||||
((option) > CURLOPTTYPE_OFF_T)
|
||||
|
||||
/* evaluates to true if option takes a char* argument */
|
||||
#define _curl_is_string_option(option) \
|
||||
((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \
|
||||
(option) == CURLOPT_ACCEPT_ENCODING || \
|
||||
(option) == CURLOPT_CAINFO || \
|
||||
(option) == CURLOPT_CAPATH || \
|
||||
(option) == CURLOPT_COOKIE || \
|
||||
(option) == CURLOPT_COOKIEFILE || \
|
||||
(option) == CURLOPT_COOKIEJAR || \
|
||||
(option) == CURLOPT_COOKIELIST || \
|
||||
(option) == CURLOPT_CRLFILE || \
|
||||
(option) == CURLOPT_CUSTOMREQUEST || \
|
||||
(option) == CURLOPT_DEFAULT_PROTOCOL || \
|
||||
(option) == CURLOPT_DNS_INTERFACE || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP4 || \
|
||||
(option) == CURLOPT_DNS_LOCAL_IP6 || \
|
||||
(option) == CURLOPT_DNS_SERVERS || \
|
||||
(option) == CURLOPT_EGDSOCKET || \
|
||||
(option) == CURLOPT_FTPPORT || \
|
||||
(option) == CURLOPT_FTP_ACCOUNT || \
|
||||
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
|
||||
(option) == CURLOPT_INTERFACE || \
|
||||
(option) == CURLOPT_ISSUERCERT || \
|
||||
(option) == CURLOPT_KEYPASSWD || \
|
||||
(option) == CURLOPT_KRBLEVEL || \
|
||||
(option) == CURLOPT_LOGIN_OPTIONS || \
|
||||
(option) == CURLOPT_MAIL_AUTH || \
|
||||
(option) == CURLOPT_MAIL_FROM || \
|
||||
(option) == CURLOPT_NETRC_FILE || \
|
||||
(option) == CURLOPT_NOPROXY || \
|
||||
(option) == CURLOPT_PASSWORD || \
|
||||
(option) == CURLOPT_PINNEDPUBLICKEY || \
|
||||
(option) == CURLOPT_PRE_PROXY || \
|
||||
(option) == CURLOPT_PROXY || \
|
||||
(option) == CURLOPT_PROXYPASSWORD || \
|
||||
(option) == CURLOPT_PROXYUSERNAME || \
|
||||
(option) == CURLOPT_PROXYUSERPWD || \
|
||||
(option) == CURLOPT_PROXY_CAINFO || \
|
||||
(option) == CURLOPT_PROXY_CAPATH || \
|
||||
(option) == CURLOPT_PROXY_CRLFILE || \
|
||||
(option) == CURLOPT_PROXY_KEYPASSWD || \
|
||||
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
|
||||
(option) == CURLOPT_PROXY_SERVICE_NAME || \
|
||||
(option) == CURLOPT_PROXY_SSLCERT || \
|
||||
(option) == CURLOPT_PROXY_SSLCERTTYPE || \
|
||||
(option) == CURLOPT_PROXY_SSLKEY || \
|
||||
(option) == CURLOPT_PROXY_SSLKEYTYPE || \
|
||||
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
|
||||
(option) == CURLOPT_RANDOM_FILE || \
|
||||
(option) == CURLOPT_RANGE || \
|
||||
(option) == CURLOPT_REFERER || \
|
||||
(option) == CURLOPT_RTSP_SESSION_ID || \
|
||||
(option) == CURLOPT_RTSP_STREAM_URI || \
|
||||
(option) == CURLOPT_RTSP_TRANSPORT || \
|
||||
(option) == CURLOPT_SERVICE_NAME || \
|
||||
(option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
|
||||
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
|
||||
(option) == CURLOPT_SSH_KNOWNHOSTS || \
|
||||
(option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
|
||||
(option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
|
||||
(option) == CURLOPT_SSLCERT || \
|
||||
(option) == CURLOPT_SSLCERTTYPE || \
|
||||
(option) == CURLOPT_SSLENGINE || \
|
||||
(option) == CURLOPT_SSLKEY || \
|
||||
(option) == CURLOPT_SSLKEYTYPE || \
|
||||
(option) == CURLOPT_SSL_CIPHER_LIST || \
|
||||
(option) == CURLOPT_TLSAUTH_PASSWORD || \
|
||||
(option) == CURLOPT_TLSAUTH_TYPE || \
|
||||
(option) == CURLOPT_TLSAUTH_USERNAME || \
|
||||
(option) == CURLOPT_UNIX_SOCKET_PATH || \
|
||||
(option) == CURLOPT_URL || \
|
||||
(option) == CURLOPT_USERAGENT || \
|
||||
(option) == CURLOPT_USERNAME || \
|
||||
(option) == CURLOPT_USERPWD || \
|
||||
(option) == CURLOPT_XOAUTH2_BEARER || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a curl_write_callback argument */
|
||||
#define _curl_is_write_cb_option(option) \
|
||||
((option) == CURLOPT_HEADERFUNCTION || \
|
||||
(option) == CURLOPT_WRITEFUNCTION)
|
||||
|
||||
/* evaluates to true if option takes a curl_conv_callback argument */
|
||||
#define _curl_is_conv_cb_option(option) \
|
||||
((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
|
||||
(option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
|
||||
(option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
|
||||
|
||||
/* evaluates to true if option takes a data argument to pass to a callback */
|
||||
#define _curl_is_cb_data_option(option) \
|
||||
((option) == CURLOPT_CHUNK_DATA || \
|
||||
(option) == CURLOPT_CLOSESOCKETDATA || \
|
||||
(option) == CURLOPT_DEBUGDATA || \
|
||||
(option) == CURLOPT_FNMATCH_DATA || \
|
||||
(option) == CURLOPT_HEADERDATA || \
|
||||
(option) == CURLOPT_INTERLEAVEDATA || \
|
||||
(option) == CURLOPT_IOCTLDATA || \
|
||||
(option) == CURLOPT_OPENSOCKETDATA || \
|
||||
(option) == CURLOPT_PRIVATE || \
|
||||
(option) == CURLOPT_PROGRESSDATA || \
|
||||
(option) == CURLOPT_READDATA || \
|
||||
(option) == CURLOPT_SEEKDATA || \
|
||||
(option) == CURLOPT_SOCKOPTDATA || \
|
||||
(option) == CURLOPT_SSH_KEYDATA || \
|
||||
(option) == CURLOPT_SSL_CTX_DATA || \
|
||||
(option) == CURLOPT_WRITEDATA || \
|
||||
(option) == CURLOPT_RESOLVER_START_DATA || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a POST data argument (void* or char*) */
|
||||
#define _curl_is_postfields_option(option) \
|
||||
((option) == CURLOPT_POSTFIELDS || \
|
||||
(option) == CURLOPT_COPYPOSTFIELDS || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a struct curl_slist * argument */
|
||||
#define _curl_is_slist_option(option) \
|
||||
((option) == CURLOPT_HTTP200ALIASES || \
|
||||
(option) == CURLOPT_HTTPHEADER || \
|
||||
(option) == CURLOPT_MAIL_RCPT || \
|
||||
(option) == CURLOPT_POSTQUOTE || \
|
||||
(option) == CURLOPT_PREQUOTE || \
|
||||
(option) == CURLOPT_PROXYHEADER || \
|
||||
(option) == CURLOPT_QUOTE || \
|
||||
(option) == CURLOPT_RESOLVE || \
|
||||
(option) == CURLOPT_TELNETOPTIONS || \
|
||||
0)
|
||||
|
||||
/* groups of curl_easy_getinfo infos that take the same type of argument */
|
||||
|
||||
/* evaluates to true if info expects a pointer to char * argument */
|
||||
#define _curl_is_string_info(info) \
|
||||
(CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
|
||||
|
||||
/* evaluates to true if info expects a pointer to long argument */
|
||||
#define _curl_is_long_info(info) \
|
||||
(CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
|
||||
|
||||
/* evaluates to true if info expects a pointer to double argument */
|
||||
#define _curl_is_double_info(info) \
|
||||
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
|
||||
|
||||
/* true if info expects a pointer to struct curl_slist * argument */
|
||||
#define _curl_is_slist_info(info) \
|
||||
(((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
|
||||
|
||||
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
|
||||
#define _curl_is_tlssessioninfo_info(info) \
|
||||
(((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
|
||||
|
||||
/* true if info expects a pointer to struct curl_certinfo * argument */
|
||||
#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
|
||||
|
||||
/* true if info expects a pointer to struct curl_socket_t argument */
|
||||
#define _curl_is_socket_info(info) \
|
||||
(CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
|
||||
|
||||
/* true if info expects a pointer to curl_off_t argument */
|
||||
#define _curl_is_off_t_info(info) \
|
||||
(CURLINFO_OFF_T < (info))
|
||||
|
||||
|
||||
/* typecheck helpers -- check whether given expression has requested type*/
|
||||
|
||||
/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
|
||||
* otherwise define a new macro. Search for __builtin_types_compatible_p
|
||||
* in the GCC manual.
|
||||
* NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
|
||||
* the actual expression passed to the curl_easy_setopt macro. This
|
||||
* means that you can only apply the sizeof and __typeof__ operators, no
|
||||
* == or whatsoever.
|
||||
*/
|
||||
|
||||
/* XXX: should evaluate to true iff expr is a pointer */
|
||||
#define _curl_is_any_ptr(expr) \
|
||||
(sizeof(expr) == sizeof(void *))
|
||||
|
||||
/* evaluates to true if expr is NULL */
|
||||
/* XXX: must not evaluate expr, so this check is not accurate */
|
||||
#define _curl_is_NULL(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
|
||||
|
||||
/* evaluates to true if expr is type*, const type* or NULL */
|
||||
#define _curl_is_ptr(expr, type) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), type *) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), const type *))
|
||||
|
||||
/* evaluates to true if expr is one of type[], type*, NULL or const type* */
|
||||
#define _curl_is_arr(expr, type) \
|
||||
(_curl_is_ptr((expr), type) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), type []))
|
||||
|
||||
/* evaluates to true if expr is a string */
|
||||
#define _curl_is_string(expr) \
|
||||
(_curl_is_arr((expr), char) || \
|
||||
_curl_is_arr((expr), signed char) || \
|
||||
_curl_is_arr((expr), unsigned char))
|
||||
|
||||
/* evaluates to true if expr is a long (no matter the signedness)
|
||||
* XXX: for now, int is also accepted (and therefore short and char, which
|
||||
* are promoted to int when passed to a variadic function) */
|
||||
#define _curl_is_long(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), int) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed int) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned int) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), short) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed short) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned short) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed char) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned char))
|
||||
|
||||
/* evaluates to true if expr is of type curl_off_t */
|
||||
#define _curl_is_off_t(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
|
||||
|
||||
/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
|
||||
/* XXX: also check size of an char[] array? */
|
||||
#define _curl_is_error_buffer(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char[]))
|
||||
|
||||
/* evaluates to true if expr is of type (const) void* or (const) FILE* */
|
||||
#if 0
|
||||
#define _curl_is_cb_data(expr) \
|
||||
(_curl_is_ptr((expr), void) || \
|
||||
_curl_is_ptr((expr), FILE))
|
||||
#else /* be less strict */
|
||||
#define _curl_is_cb_data(expr) \
|
||||
_curl_is_any_ptr(expr)
|
||||
#endif
|
||||
|
||||
/* evaluates to true if expr is of type FILE* */
|
||||
#define _curl_is_FILE(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), FILE *)))
|
||||
|
||||
/* evaluates to true if expr can be passed as POST data (void* or char*) */
|
||||
#define _curl_is_postfields(expr) \
|
||||
(_curl_is_ptr((expr), void) || \
|
||||
_curl_is_arr((expr), char))
|
||||
|
||||
/* FIXME: the whole callback checking is messy...
|
||||
* The idea is to tolerate char vs. void and const vs. not const
|
||||
* pointers in arguments at least
|
||||
*/
|
||||
/* helper: __builtin_types_compatible_p distinguishes between functions and
|
||||
* function pointers, hide it */
|
||||
#define _curl_callback_compatible(func, type) \
|
||||
(__builtin_types_compatible_p(__typeof__(func), type) || \
|
||||
__builtin_types_compatible_p(__typeof__(func) *, type))
|
||||
|
||||
/* evaluates to true if expr is of type curl_resolver_start_callback */
|
||||
#define _curl_is_resolver_start_callback(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_resolver_start_callback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_read_callback or "similar" */
|
||||
#define _curl_is_read_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), __typeof__(fread) *) || \
|
||||
_curl_callback_compatible((expr), curl_read_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback6))
|
||||
typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
|
||||
typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
|
||||
typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
|
||||
typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_write_callback or "similar" */
|
||||
#define _curl_is_write_cb(expr) \
|
||||
(_curl_is_read_cb(expr) || \
|
||||
_curl_callback_compatible((expr), __typeof__(fwrite) *) || \
|
||||
_curl_callback_compatible((expr), curl_write_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback6))
|
||||
typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
|
||||
const void *);
|
||||
typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *);
|
||||
typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
|
||||
const void *);
|
||||
typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
|
||||
#define _curl_is_ioctl_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_ioctl_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback4))
|
||||
typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
|
||||
#define _curl_is_sockopt_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_sockopt_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_sockopt_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_sockopt_callback2))
|
||||
typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
|
||||
typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
|
||||
curlsocktype);
|
||||
|
||||
/* evaluates to true if expr is of type curl_opensocket_callback or
|
||||
"similar" */
|
||||
#define _curl_is_opensocket_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_opensocket_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback4))
|
||||
typedef curl_socket_t (*_curl_opensocket_callback1)
|
||||
(void *, curlsocktype, struct curl_sockaddr *);
|
||||
typedef curl_socket_t (*_curl_opensocket_callback2)
|
||||
(void *, curlsocktype, const struct curl_sockaddr *);
|
||||
typedef curl_socket_t (*_curl_opensocket_callback3)
|
||||
(const void *, curlsocktype, struct curl_sockaddr *);
|
||||
typedef curl_socket_t (*_curl_opensocket_callback4)
|
||||
(const void *, curlsocktype, const struct curl_sockaddr *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_progress_callback or "similar" */
|
||||
#define _curl_is_progress_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_progress_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_progress_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_progress_callback2))
|
||||
typedef int (*_curl_progress_callback1)(void *,
|
||||
double, double, double, double);
|
||||
typedef int (*_curl_progress_callback2)(const void *,
|
||||
double, double, double, double);
|
||||
|
||||
/* evaluates to true if expr is of type curl_debug_callback or "similar" */
|
||||
#define _curl_is_debug_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_debug_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback6) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback7) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback8))
|
||||
typedef int (*_curl_debug_callback1) (CURL *,
|
||||
curl_infotype, char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback2) (CURL *,
|
||||
curl_infotype, char *, size_t, const void *);
|
||||
typedef int (*_curl_debug_callback3) (CURL *,
|
||||
curl_infotype, const char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback4) (CURL *,
|
||||
curl_infotype, const char *, size_t, const void *);
|
||||
typedef int (*_curl_debug_callback5) (CURL *,
|
||||
curl_infotype, unsigned char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback6) (CURL *,
|
||||
curl_infotype, unsigned char *, size_t, const void *);
|
||||
typedef int (*_curl_debug_callback7) (CURL *,
|
||||
curl_infotype, const unsigned char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback8) (CURL *,
|
||||
curl_infotype, const unsigned char *, size_t, const void *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
|
||||
/* this is getting even messier... */
|
||||
#define _curl_is_ssl_ctx_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_ssl_ctx_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
|
||||
const void *);
|
||||
#ifdef HEADER_SSL_H
|
||||
/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
|
||||
* this will of course break if we're included before OpenSSL headers...
|
||||
*/
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
|
||||
const void *);
|
||||
#else
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
|
||||
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
|
||||
#endif
|
||||
|
||||
/* evaluates to true if expr is of type curl_conv_callback or "similar" */
|
||||
#define _curl_is_conv_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_conv_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback4))
|
||||
typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
|
||||
|
||||
/* evaluates to true if expr is of type curl_seek_callback or "similar" */
|
||||
#define _curl_is_seek_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_seek_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_seek_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_seek_callback2))
|
||||
typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
|
||||
typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
|
||||
|
||||
|
||||
#endif /* __CURL_TYPECHECK_GCC_H */
|
||||
@@ -1,89 +0,0 @@
|
||||
# For more information about using CMake with Android Studio, read the
|
||||
# documentation: https://d.android.com/studio/projects/add-native-code.html
|
||||
|
||||
# Sets the minimum version of CMake required to build the native library.
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# Creates and names a library, sets it as either STATIC
|
||||
# or SHARED, and provides the relative paths to its source code.
|
||||
# You can define multiple libraries, and CMake builds them for you.
|
||||
# Gradle automatically packages shared libraries with your APK.
|
||||
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
set (HEADERS
|
||||
Demo.hpp
|
||||
manager/DirectoryManager.h
|
||||
manager/Tok.h
|
||||
model/APIInfo.h
|
||||
model/CoverArt.h
|
||||
model/Song.h
|
||||
model/Token.h
|
||||
model/User.h
|
||||
repository/APIRepository.h
|
||||
repository/BaseRepository.h
|
||||
repository/CoverArtRepository.h
|
||||
repository/RepeatRepository.h
|
||||
repository/ShuffleRepository.h
|
||||
repository/SongRepository.h
|
||||
repository/TokenRepository.h
|
||||
repository/UserRepository.h
|
||||
types/ConnType.h
|
||||
types/RepeatTypes.h
|
||||
types/ShuffleTypes.h
|
||||
utility/GeneralUtility.h
|
||||
utility/JNIObjectConversion.h
|
||||
)
|
||||
|
||||
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
||||
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/json)
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/3rdparty/SQLiteCpp)
|
||||
|
||||
|
||||
add_library(native-lib SHARED
|
||||
Demo.cpp
|
||||
${HEADERS}
|
||||
)
|
||||
|
||||
|
||||
find_library(log-lib
|
||||
log
|
||||
)
|
||||
|
||||
|
||||
set (CURL_LIBRARY
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/android/${ANDROID_ABI}
|
||||
)
|
||||
|
||||
|
||||
set (CURL_INCLUDE_DIR
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/android/include/curl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/android/include
|
||||
)
|
||||
|
||||
set(SQLITECPP_INCLUDE
|
||||
${CMAKE_CURRENT_LIST_DIR}/3rdparty/SQLiteCpp/include
|
||||
)
|
||||
|
||||
add_library(boo STATIC IMPORTED)
|
||||
|
||||
set_target_properties(boo PROPERTIES IMPORTED_LOCATION
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/android/${ANDROID_ABI}/libcurl.a"
|
||||
)
|
||||
|
||||
include_directories(${CURL_INCLUDE_DIR} ${SQLITECPP_INCLUDE} ${HEADERS})
|
||||
|
||||
target_link_libraries(native-lib PRIVATE
|
||||
nlohmann_json::nlohmann_json
|
||||
boo
|
||||
SQLiteCpp
|
||||
sqlite3
|
||||
dl
|
||||
${log-lib}
|
||||
z
|
||||
)
|
||||
@@ -1,4 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 9/26/19.
|
||||
//
|
||||
#include "Demo.hpp"
|
||||
@@ -1,764 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/12/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_DEMO_H
|
||||
#define MEAR_DEMO_H
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include <android/asset_manager_jni.h>
|
||||
#include <android/log.h>
|
||||
#include <android/sharedmem.h>
|
||||
#include <fcntl.h>
|
||||
#include <jni.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "manager/Tok.h"
|
||||
#include "manager/DirectoryManager.h"
|
||||
#include "model/APIInfo.h"
|
||||
#include "model/CoverArt.h"
|
||||
#include "model/Song.h"
|
||||
#include "model/Token.h"
|
||||
#include "model/User.h"
|
||||
#include "repository/APIRepository.h"
|
||||
#include "repository/CoverArtRepository.h"
|
||||
#include "repository/RepeatRepository.h"
|
||||
#include "repository/ShuffleRepository.h"
|
||||
#include "repository/SongRepository.h"
|
||||
#include "repository/TokenRepository.h"
|
||||
#include "repository/UserRepository.h"
|
||||
#include "utility/JNIObjectConversion.h"
|
||||
|
||||
|
||||
template<class Song = model::Song>
|
||||
std::vector<Song> retrieveSongs(const model::Token& token, const std::string& baseUri) {
|
||||
std::vector<model::Song> songs;
|
||||
repository::SongRepository songRepo;
|
||||
|
||||
return songRepo.fetchSongs(token, baseUri);
|
||||
}
|
||||
|
||||
template<typename Str = std::string>
|
||||
Str jstringToString(JNIEnv *env, jstring& val) {
|
||||
auto myVal = env->GetStringUTFChars(val, nullptr);
|
||||
return myVal;
|
||||
}
|
||||
|
||||
template<class APIInfo = model::APIInfo>
|
||||
APIInfo retrieveAPIInfo(const std::string& path) {
|
||||
repository::local::APIRepository apiRepo;
|
||||
|
||||
return apiRepo.retrieveAPIInfo(path);
|
||||
}
|
||||
|
||||
template<typename SongObj, typename JE, class Song = model::Song>
|
||||
Song ObjToSong(JE *env, SongObj obj) {
|
||||
jclass songClass = env->GetObjectClass(obj);
|
||||
|
||||
auto songId = env->GetFieldID( songClass, "id", "I" );
|
||||
auto songTitle = env->GetFieldID( songClass, "title", "Ljava/lang/String;" );
|
||||
auto songAlbum = env->GetFieldID( songClass, "album", "Ljava/lang/String;" );
|
||||
auto songAlbumArtist = env->GetFieldID(songClass, "albumArtist", "Ljava/lang/String;");
|
||||
auto songArtist = env->GetFieldID( songClass, "artist", "Ljava/lang/String;" );
|
||||
auto songGenre = env->GetFieldID( songClass, "genre", "Ljava/lang/String;" );
|
||||
auto songDuration = env->GetFieldID( songClass, "duration", "I" );
|
||||
auto songTrack = env->GetFieldID(songClass, "track", "I");
|
||||
auto songDisc = env->GetFieldID(songClass, "disc", "I");
|
||||
auto songYear = env->GetFieldID( songClass, "year", "I" );
|
||||
auto songCoverArtId = env->GetFieldID(songClass, "coverArtId", "I");
|
||||
auto songPathId = env->GetFieldID(songClass, "path", "Ljava/lang/String;");
|
||||
auto songFilenameId = env->GetFieldID(songClass, "filename", "Ljava/lang/String;");
|
||||
auto songDownloadedId = env->GetFieldID(songClass, "downloaded", "Z");
|
||||
|
||||
auto songIdVal = env->GetIntField(obj, songId);
|
||||
auto titleVal = (jstring)env->GetObjectField(obj, songTitle);
|
||||
auto albumVal = (jstring)env->GetObjectField(obj, songAlbum);
|
||||
auto albumArtistVal = (jstring)env->GetObjectField(obj, songAlbumArtist);
|
||||
auto songArtistVal = (jstring)env->GetObjectField(obj, songArtist);
|
||||
auto songGenreVal = (jstring)env->GetObjectField(obj, songGenre);
|
||||
auto songDurationVal = env->GetIntField(obj, songDuration);
|
||||
auto songTrackVal = env->GetIntField(obj, songTrack);
|
||||
auto songDiscVal = env->GetIntField(obj, songDisc);
|
||||
auto songYearVal = env->GetIntField(obj, songYear);
|
||||
auto songCoverArtIdVal = env->GetIntField(obj, songCoverArtId);
|
||||
auto songPathVal = (jstring)env->GetObjectField(obj, songPathId);
|
||||
auto songFilenameVal = (jstring)env->GetObjectField(obj, songFilenameId);
|
||||
|
||||
|
||||
Song song;
|
||||
song.id = songIdVal;
|
||||
song.title = env->GetStringUTFChars(titleVal, nullptr);
|
||||
song.artist = env->GetStringUTFChars(songArtistVal, nullptr);
|
||||
song.album = env->GetStringUTFChars(albumVal, nullptr);
|
||||
song.albumArtist = env->GetStringUTFChars(albumArtistVal, nullptr);
|
||||
song.genre = env->GetStringUTFChars(songGenreVal, nullptr);
|
||||
song.duration = songDurationVal;
|
||||
song.track = songTrackVal;
|
||||
song.disc = songDiscVal;
|
||||
song.year = songYearVal;
|
||||
song.coverArtId = songCoverArtIdVal;
|
||||
song.path = (songPathVal == nullptr) ? "" : env->GetStringUTFChars(songPathVal, nullptr);
|
||||
song.filename = (songFilenameVal == nullptr) ? "" : env->GetStringUTFChars(songFilenameVal, nullptr);
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
template<class Song = model::Song>
|
||||
Song retrieveSong(const model::Token& token, const Song& song,
|
||||
const std::string& baseUri) {
|
||||
repository::SongRepository songRepo;
|
||||
|
||||
return songRepo.retrieveSong(token, song, baseUri);
|
||||
}
|
||||
|
||||
template<class Token = model::Token>
|
||||
Token fetchToken(const model::User& user, const std::string& apiUri) {
|
||||
manager::Tok tokMgr;
|
||||
auto token = tokMgr.fetchTokenTrans(user, apiUri);
|
||||
|
||||
return token;
|
||||
}
|
||||
template<class Token = model::Token>
|
||||
Token retrieveSavedToken(const std::string& path) {
|
||||
repository::local::TokenRepository tokenRepo;
|
||||
if (!tokenRepo.databaseExist(path)) {
|
||||
tokenRepo.initializedDatabase(path);
|
||||
}
|
||||
auto token = tokenRepo.retrieveToken(path);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
template<class User = model::User>
|
||||
User retrieveCredentials(const std::string& dataPath) {
|
||||
repository::local::UserRepository userRepo;
|
||||
if (!userRepo.databaseExist(dataPath)) {
|
||||
userRepo.initializedDatabase(dataPath);
|
||||
}
|
||||
auto user = userRepo.retrieveUserCredentials(dataPath);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
int retrieveRepeatMode(const std::string& path) {
|
||||
repository::local::RepeatRepository repeatRepo;
|
||||
if (!repeatRepo.databaseExist(path)) {
|
||||
repeatRepo.initializedDatabase(path);
|
||||
}
|
||||
if (!repeatRepo.doesTableExist(path)) {
|
||||
repeatRepo.createRepeatTable(path);
|
||||
}
|
||||
|
||||
auto repeatMode = repeatRepo.retrieveRepeatMode(path);
|
||||
|
||||
return static_cast<int>(repeatMode);
|
||||
}
|
||||
|
||||
int retrieveShuffleMode(const std::string& path) {
|
||||
repository::local::ShuffleRepository shuffleRepo;
|
||||
if (!shuffleRepo.databaseExist(path)) {
|
||||
shuffleRepo.initializedDatabase(path);
|
||||
}
|
||||
if (!shuffleRepo.doesTableExist(path)) {
|
||||
shuffleRepo.createShuffleTable(path);
|
||||
}
|
||||
|
||||
auto shuffleMode = shuffleRepo.retrieveShuffleMode(path);
|
||||
|
||||
return static_cast<int>(shuffleMode);
|
||||
}
|
||||
|
||||
|
||||
template<class Song = model::Song, typename Str = std::string, typename B = bool>
|
||||
B deleteSong(Song& song, const Str& path) {
|
||||
manager::DirectoryManager dirMgr;
|
||||
if (!dirMgr.doesSongExist(song, path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto result = dirMgr.deleteSong(song, path);
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
repository::local::SongRepository songRepo(path);
|
||||
songRepo.deleteSongFromTable(song, path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool doesDatabaseExist(const std::string& dataPath) {
|
||||
repository::local::UserRepository userRepo;
|
||||
const auto result = userRepo.databaseExist(dataPath);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool apiInformationExist(const std::string& dataPath) {
|
||||
repository::local::APIRepository apiRepo;
|
||||
|
||||
return apiRepo.isTableEmpty(dataPath);
|
||||
}
|
||||
|
||||
bool doesTokenExist(const std::string& dataPath) {
|
||||
repository::local::TokenRepository tokenRepo;
|
||||
|
||||
return tokenRepo.isTableEmpty(dataPath);
|
||||
}
|
||||
|
||||
bool userCredentialExist(const std::string& dataPath) {
|
||||
repository::local::UserRepository userRepo;
|
||||
|
||||
return userRepo.isTableEmpty(dataPath);
|
||||
}
|
||||
|
||||
|
||||
void saveAPIInfo(const model::APIInfo& apiInfo, const std::string& path) {
|
||||
repository::local::APIRepository apiRepo;
|
||||
if (!apiRepo.databaseExist(path)) {
|
||||
apiRepo.initializedDatabase(path);
|
||||
}
|
||||
if (!apiRepo.doesTableExist(path)) {
|
||||
apiRepo.createAPiInfoTable(path);
|
||||
}
|
||||
if (!apiRepo.isTableEmpty(path)) {
|
||||
apiRepo.deleteAPIInfo(apiInfo, path);
|
||||
}
|
||||
|
||||
apiRepo.saveAPIInfo(apiInfo, path);
|
||||
}
|
||||
|
||||
void saveCredentials(const model::User& user, const std::string& appDirectory) {
|
||||
repository::local::UserRepository userRepo;
|
||||
|
||||
if (!userRepo.databaseExist(appDirectory)) {
|
||||
userRepo.initializedDatabase(appDirectory);
|
||||
}
|
||||
if (!userRepo.doesTableExist(appDirectory)) {
|
||||
userRepo.createUserTable(appDirectory);
|
||||
}
|
||||
|
||||
if (!userRepo.isTableEmpty(appDirectory)) {
|
||||
userRepo.deleteUserTable(appDirectory);
|
||||
}
|
||||
|
||||
userRepo.saveUserCred(user, appDirectory);
|
||||
}
|
||||
|
||||
void saveToken(const model::Token& token, const std::string& path) {
|
||||
repository::local::TokenRepository tokenRepo;
|
||||
if (!tokenRepo.databaseExist(path)) {
|
||||
tokenRepo.initializedDatabase(path);
|
||||
}
|
||||
if (!tokenRepo.doesTableExist(path)) {
|
||||
tokenRepo.createTokenTable(path);
|
||||
}
|
||||
if (!tokenRepo.isTableEmpty(path)) {
|
||||
tokenRepo.deleteRecord(path);
|
||||
}
|
||||
|
||||
tokenRepo.saveToken(token, path);
|
||||
}
|
||||
|
||||
void updateRepeatMode(const std::string& path) {
|
||||
repository::local::RepeatRepository repeatRepo;
|
||||
if (!repeatRepo.databaseExist(path)) {
|
||||
repeatRepo.initializedDatabase(path);
|
||||
}
|
||||
repeatRepo.updateRepeat(path);
|
||||
}
|
||||
|
||||
void updateShuffleMode(const std::string& path) {
|
||||
repository::local::ShuffleRepository shuffleRepo;
|
||||
if (!shuffleRepo.databaseExist(path)) {
|
||||
shuffleRepo.initializedDatabase(path);
|
||||
}
|
||||
shuffleRepo.updateShuffle(path);
|
||||
}
|
||||
|
||||
template<class Song = model::Song, class Token = model::Token, typename Str = std::string>
|
||||
void downloadSong(Song& song, const Token& token, const Str& path) {
|
||||
song.filename = "track";
|
||||
song.path = path;
|
||||
repository::local::APIRepository apiRepo;
|
||||
auto apiInfo = apiRepo.retrieveAPIInfo(path);
|
||||
repository::SongRepository songRepo;
|
||||
manager::DirectoryManager dirMgr;
|
||||
if (dirMgr.doesSongExist(song, path)) {
|
||||
std::cout << "song already exists\n";
|
||||
return;
|
||||
}
|
||||
|
||||
auto downloadedSong = songRepo.downloadSong(token, song, apiInfo);
|
||||
|
||||
dirMgr.createSongDirectory(song, path);
|
||||
downloadedSong.path = dirMgr.fullSongPath(song, path);
|
||||
std::fstream saveSong(downloadedSong.path, std::ios::out | std::ios::binary);
|
||||
saveSong.write((char*)&downloadedSong.data[0], downloadedSong.data.size());
|
||||
saveSong.close();
|
||||
|
||||
song.path = downloadedSong.path;
|
||||
song.downloaded = true;
|
||||
repository::local::SongRepository localSongRepo(path);
|
||||
localSongRepo.saveSong(downloadedSong, path);
|
||||
}
|
||||
|
||||
|
||||
template<class Song = model::Song>
|
||||
jobject songToObj(JNIEnv *env, const Song& song) {
|
||||
jclass songClass = env->FindClass( "com/example/mear/models/Song");
|
||||
jmethodID jconstructor = env->GetMethodID( songClass, "<init>", "()V" );
|
||||
jobject songObj = env->NewObject( songClass, jconstructor );
|
||||
|
||||
auto songId = env->GetFieldID( songClass, "id", "I" );
|
||||
auto songTitle = env->GetFieldID( songClass, "title", "Ljava/lang/String;" );
|
||||
auto songAlbum = env->GetFieldID( songClass, "album", "Ljava/lang/String;" );
|
||||
auto songAlbumArtist = env->GetFieldID(songClass, "albumArtist", "Ljava/lang/String;");
|
||||
auto songArtist = env->GetFieldID( songClass, "artist", "Ljava/lang/String;" );
|
||||
auto songGenre = env->GetFieldID( songClass, "genre", "Ljava/lang/String;" );
|
||||
auto songYear = env->GetFieldID( songClass, "year", "I" );
|
||||
auto songDuration = env->GetFieldID( songClass, "duration", "I" );
|
||||
auto songTrack = env->GetFieldID(songClass, "track", "I");
|
||||
auto songDisc = env->GetFieldID(songClass, "disc", "I");
|
||||
auto songCoverArtId = env->GetFieldID(songClass, "coverArtId", "I");
|
||||
auto songDownloadedId = env->GetFieldID(songClass, "downloaded", "Z");
|
||||
auto songPathId = env->GetFieldID(songClass, "path", "Ljava/lang/String;");
|
||||
auto songFilenameId = env->GetFieldID(songClass, "filename", "Ljava/lang/String;");
|
||||
|
||||
auto songPath = (song.path.empty()) ? nullptr : env->NewStringUTF(song.path.c_str());
|
||||
auto songFilename = (song.filename.empty()) ? nullptr : env->NewStringUTF(song.filename.c_str());
|
||||
|
||||
env->SetIntField(songObj, songId, song.id);
|
||||
env->SetObjectField(songObj, songTitle, env->NewStringUTF(song.title.c_str()));
|
||||
env->SetObjectField(songObj, songAlbum, env->NewStringUTF(song.album.c_str()));
|
||||
env->SetObjectField(songObj, songAlbumArtist, env->NewStringUTF(song.albumArtist.c_str()));
|
||||
env->SetObjectField(songObj, songArtist, env->NewStringUTF(song.artist.c_str()));
|
||||
env->SetObjectField(songObj, songGenre, env->NewStringUTF(song.genre.c_str()));
|
||||
env->SetIntField(songObj, songYear, song.year);
|
||||
env->SetIntField(songObj, songDuration, song.duration);
|
||||
env->SetIntField(songObj, songTrack, song.track);
|
||||
env->SetIntField(songObj, songDisc, song.disc);
|
||||
env->SetIntField(songObj, songCoverArtId, song.coverArtId);
|
||||
env->SetBooleanField(songObj, songDownloadedId, song.downloaded);
|
||||
env->SetObjectField(songObj, songPathId, songPath);
|
||||
env->SetObjectField(songObj, songFilenameId, songFilename);
|
||||
|
||||
env->DeleteLocalRef(songPath);
|
||||
env->DeleteLocalRef(songFilename);
|
||||
|
||||
return songObj;
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobjectArray
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_TrackRepository_retrieveSongs(
|
||||
JNIEnv *env,
|
||||
jobject thisOnj,
|
||||
jobject token,
|
||||
jstring baseUri
|
||||
) {
|
||||
jclass songClass = env->FindClass( "com/example/mear/models/Song");
|
||||
|
||||
auto tk = utility::JNIObjectConversion<model::Token>::ObjToToken(env, token);
|
||||
|
||||
const std::string uri = env->GetStringUTFChars(baseUri, nullptr);
|
||||
env->DeleteLocalRef(baseUri);
|
||||
|
||||
auto allSongs = retrieveSongs(tk, uri);
|
||||
jobjectArray songs = env->NewObjectArray(allSongs.size(), songClass, nullptr);
|
||||
auto i = 0;
|
||||
for (auto& sng: allSongs) {
|
||||
try {
|
||||
auto song = songToObj<model::Song>(env, sng);
|
||||
env->SetObjectArrayElement(songs, i++, song);
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobjectArray
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_TrackRepository_retrieveSongsIncludingDownloaded(
|
||||
JNIEnv *env,
|
||||
jobject thisOnj,
|
||||
jobject token,
|
||||
jstring baseUri,
|
||||
jstring appPathStr
|
||||
) {
|
||||
jclass songClass = env->FindClass( "com/example/mear/models/Song");
|
||||
|
||||
std::string appPath = env->GetStringUTFChars((jstring)appPathStr, nullptr);
|
||||
auto tk = utility::JNIObjectConversion<model::Token>::ObjToToken(env, token);
|
||||
|
||||
const std::string uri = env->GetStringUTFChars(baseUri, nullptr);
|
||||
env->DeleteLocalRef(baseUri);
|
||||
|
||||
auto allSongs = retrieveSongs(tk, uri);
|
||||
jobjectArray songs = env->NewObjectArray(allSongs.size(), songClass, nullptr);
|
||||
auto i = 0;
|
||||
|
||||
repository::local::SongRepository localSongRepo(appPath);
|
||||
auto localSongs = (!localSongRepo.isTableEmpty(appPath)) ?
|
||||
localSongRepo.retrieveAllSongs(appPath) : std::vector<model::Song>();
|
||||
|
||||
for (auto& sng: allSongs) {
|
||||
try {
|
||||
if (localSongs.size() > 0) {
|
||||
auto result = std::any_of(localSongs.begin(), localSongs.end(),
|
||||
[&](model::Song s) {
|
||||
auto result = s.artist.compare(sng.artist) == 0 &&
|
||||
s.title.compare(sng.title) == 0 &&
|
||||
s.album.compare(sng.album) == 0 &&
|
||||
s.albumArtist.compare(sng.albumArtist) == 0;
|
||||
|
||||
if (result) {
|
||||
auto song = songToObj<model::Song>(env, s);
|
||||
env->SetObjectArrayElement(songs, i++, song);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
if (result) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto song = songToObj<model::Song>(env, sng);
|
||||
env->SetObjectArrayElement(songs, i++, song);
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_CoverArtRepository_retrieveCoverArtImage(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jobject tokenObj,
|
||||
jobject coverArt,
|
||||
jstring apiUri
|
||||
) {
|
||||
auto token = utility::JNIObjectConversion<model::Token>::ObjToToken(env, tokenObj);
|
||||
|
||||
auto cover = utility::JNIObjectConversion<model::CoverArt>::
|
||||
ObjToCoverArt(env, coverArt);
|
||||
|
||||
repository::CoverArtRepository<model::CoverArt> coverArtRepo;
|
||||
auto data = coverArtRepo.retrieveCoverArtData(token, cover, env->GetStringUTFChars(apiUri, nullptr));
|
||||
|
||||
jbyteArray image = env->NewByteArray(data.size());
|
||||
env->SetByteArrayRegion(image, 0, data.size(), (jbyte*) data.data());
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_APIRepository_retrieveAPIInfoRecord(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jstring pathStr ) {
|
||||
const auto path = env->GetStringUTFChars(pathStr, nullptr);
|
||||
|
||||
auto apiInfo = retrieveAPIInfo(path);
|
||||
|
||||
auto apiInfoObj = utility::JNIObjectConversion<model::APIInfo>::
|
||||
APIInfoToObj(env, apiInfo);
|
||||
|
||||
return apiInfoObj;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_TokenRepository_retrieveTokenRecord(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jstring pathStr
|
||||
) {
|
||||
const auto path = env->GetStringUTFChars(pathStr, nullptr);
|
||||
auto token = retrieveSavedToken(path);
|
||||
|
||||
auto tokenObj = utility::JNIObjectConversion<model::Token>::TokenToObj(env, token);
|
||||
|
||||
return tokenObj;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_TrackRepository_downloadSong(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jobject tokenObj,
|
||||
jobject songObj,
|
||||
jstring pathStr
|
||||
) {
|
||||
auto token = utility::JNIObjectConversion<model::Token>::ObjToToken(env, tokenObj);
|
||||
|
||||
auto song = ObjToSong<jobject, JNIEnv>(env, songObj);
|
||||
auto path = env->GetStringUTFChars(pathStr, nullptr);
|
||||
downloadSong(song, token, path);
|
||||
|
||||
return songToObj(env, song);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_TrackRepository_retrieveSong(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jobject tokenObj,
|
||||
jobject songObj,
|
||||
jstring uriStr
|
||||
) {
|
||||
auto songClass = env->GetObjectClass(songObj);
|
||||
|
||||
auto idField = env->GetFieldID(songClass, "id", "I");
|
||||
|
||||
auto idInt = env->GetIntField(songObj, idField);
|
||||
|
||||
auto uri = env->GetStringUTFChars(uriStr, nullptr);
|
||||
auto token = utility::JNIObjectConversion<model::Token>::ObjToToken(env, tokenObj);
|
||||
|
||||
model::Song song(idInt);
|
||||
|
||||
song = retrieveSong(token, song, uri);
|
||||
auto fetchedSongObj = songToObj(env, song);
|
||||
|
||||
return fetchedSongObj;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_UserRepository_retrieveUserCredentials(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jstring dataPath
|
||||
) {
|
||||
const std::string dataPathStr = env->GetStringUTFChars(dataPath, nullptr);
|
||||
auto user = retrieveCredentials(dataPathStr);
|
||||
|
||||
auto userObj = utility::JNIObjectConversion<model::User>::UserToObj<JNIEnv>(env, user);
|
||||
|
||||
return userObj;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_UserRepository_logUser(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jobject user,
|
||||
jstring apiUri ) {
|
||||
const std::string api = env->GetStringUTFChars(apiUri, nullptr);
|
||||
|
||||
auto us = utility::JNIObjectConversion<model::User>::ObjToUser(env, user);
|
||||
|
||||
auto token = fetchToken(us, api);
|
||||
|
||||
auto tokenObj = utility::JNIObjectConversion<model::Token>::TokenToObj(env, token);
|
||||
|
||||
return tokenObj;
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_RepeatRepository_retrieveRepeatMode(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jstring pathStr
|
||||
) {
|
||||
const auto dataPath = jstringToString(env, pathStr);
|
||||
auto repeatMode = retrieveRepeatMode(dataPath);
|
||||
|
||||
return repeatMode;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_ShuffleRepository_retrieveShuffleMode(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jstring pathStr
|
||||
) {
|
||||
const auto dataPath = jstringToString(env, pathStr);
|
||||
auto shuffleMode = retrieveShuffleMode(dataPath);
|
||||
|
||||
return shuffleMode;
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_APIRepository_isAPIInfoTableEmpty(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jstring pathStr
|
||||
) {
|
||||
const auto dataPath = env->GetStringUTFChars(pathStr, nullptr);
|
||||
|
||||
return apiInformationExist(dataPath);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_BaseRepository_doesDatabaseExist(
|
||||
JNIEnv *env,
|
||||
jobject thidObj,
|
||||
jstring dataPath
|
||||
) {
|
||||
const std::string dataPathStr = env->GetStringUTFChars(dataPath, nullptr);
|
||||
jboolean result = doesDatabaseExist(dataPathStr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_TokenRepository_isTokenTableEmpty(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jstring pathStr
|
||||
) {
|
||||
const auto dataPath = env->GetStringUTFChars(pathStr, nullptr);
|
||||
|
||||
return doesTokenExist(dataPath);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_TrackRepository_deleteSong(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jobject songObj,
|
||||
jstring pathStr
|
||||
) {
|
||||
auto songClass = env->GetObjectClass(songObj);
|
||||
auto path = env->GetStringUTFChars(pathStr, nullptr);
|
||||
auto song = ObjToSong(env, songObj);
|
||||
|
||||
const auto result = deleteSong(song, path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_UserRepository_isUserTableEmpty(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jstring dataPath
|
||||
) {
|
||||
const std::string dataPathStr = env->GetStringUTFChars(dataPath, nullptr);
|
||||
|
||||
return userCredentialExist(dataPathStr);
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_APIRepository_saveAPIInfoRecord(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jobject apiInfoObj,
|
||||
jstring pathStr
|
||||
) {
|
||||
auto apiInfo = utility::JNIObjectConversion<model::APIInfo>::
|
||||
ObjToAPIInfo(env, apiInfoObj);
|
||||
auto path = env->GetStringUTFChars(pathStr, nullptr);
|
||||
|
||||
saveAPIInfo(apiInfo, path);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_RepeatRepository_updateRepeatMode(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jstring pathStr
|
||||
) {
|
||||
const auto dataPath = jstringToString(env, pathStr);
|
||||
updateRepeatMode(dataPath);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_ShuffleRepository_updateShuffle(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jstring pathStr
|
||||
) {
|
||||
const auto dataPath = jstringToString(env, pathStr);
|
||||
updateShuffleMode(dataPath);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_TokenRepository_saveTokenRecord(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jobject tokenObj,
|
||||
jstring pathStr
|
||||
) {
|
||||
auto token = utility::JNIObjectConversion<model::Token>::ObjToToken(env, tokenObj);
|
||||
auto path = env->GetStringUTFChars(pathStr, nullptr);
|
||||
|
||||
saveToken(token, path);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void
|
||||
JNICALL
|
||||
Java_com_example_mear_repositories_UserRepository_saveUserCredentials(
|
||||
JNIEnv *env,
|
||||
jobject thisObj,
|
||||
jobject user,
|
||||
jstring appDirectory
|
||||
) {
|
||||
const std::string appDirectoryStr = env->GetStringUTFChars(appDirectory, nullptr);
|
||||
|
||||
auto usr = utility::JNIObjectConversion<model::User>::ObjToUser<JNIEnv>(env, user);
|
||||
|
||||
saveCredentials(usr, appDirectoryStr);
|
||||
}
|
||||
|
||||
|
||||
#endif //MEAR_DEMO_H
|
||||
@@ -1,205 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 11/29/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_DIRECTORYMANAGER_H
|
||||
#define MEAR_DIRECTORYMANAGER_H
|
||||
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../model/Song.h"
|
||||
#include "../utility/GeneralUtility.h"
|
||||
|
||||
namespace manager {
|
||||
template<class Song = model::Song>
|
||||
class DirectoryManager {
|
||||
public:
|
||||
template<typename Str = std::string>
|
||||
std::string fullSongPath(const Song& song, const Str& path) {
|
||||
std::string s = rootMusicDirectory(path);
|
||||
s.append(song.albumArtist);
|
||||
s.append("/");
|
||||
s.append(song.album);
|
||||
s.append("/");
|
||||
|
||||
if (song.disc == 0) {
|
||||
s.append("disc1");
|
||||
} else {
|
||||
s.append("disc");
|
||||
s.append(std::to_string(song.disc));
|
||||
}
|
||||
|
||||
s.append("/");
|
||||
s.append("track");
|
||||
if (song.track < 10) {
|
||||
s.append("0");
|
||||
s.append(std::to_string(song.track));
|
||||
} else {
|
||||
s.append(std::to_string(song.track));
|
||||
}
|
||||
|
||||
s.append(".mp3");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename Str = std::string>
|
||||
Str albumPath(const Song& song, const Str& path) {
|
||||
auto s = rootMusicDirectory<std::string>(path);
|
||||
s.append(song.albumArtist);
|
||||
s.append("/");
|
||||
s.append(song.album);
|
||||
|
||||
auto ss = s;
|
||||
|
||||
return ss.c_str();
|
||||
}
|
||||
|
||||
template<typename Str = std::string>
|
||||
Str albumDiscPath(const Song& song, const Str& path) {
|
||||
std::string songPath = albumPath(song, path);
|
||||
songPath.append("/disc");
|
||||
if (song.disc == 0) {
|
||||
songPath.append("1");
|
||||
} else {
|
||||
songPath.append(std::to_string(song.disc));
|
||||
}
|
||||
|
||||
return songPath.c_str();
|
||||
}
|
||||
|
||||
template<typename Str = std::string>
|
||||
Str artistPath(const Song& song, const Str& path) {
|
||||
Str s = rootMusicDirectory(path);
|
||||
s.append(song.albumArtist);
|
||||
|
||||
return s.c_str();
|
||||
}
|
||||
|
||||
|
||||
template<typename Str = std::string, typename B = bool>
|
||||
B doesSongExist(const Song& song, const Str& path) {
|
||||
std::string s = fullSongPath(song, path);
|
||||
|
||||
struct stat buffer;
|
||||
return (stat (s.c_str(), &buffer) == 0);
|
||||
}
|
||||
|
||||
template<typename Str = std::string, typename B = bool>
|
||||
B deleteSong(const Song& song, const Str& path) {
|
||||
const auto s = fullSongPath(song, path);
|
||||
|
||||
return (remove(s.c_str()) == 0) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
template<typename Str = std::string>
|
||||
void createSongDirectory(const Song& song, const Str& path) {
|
||||
if (!rootMusicDirectoryExists<std::string>(path)) {
|
||||
const std::string p(rootMusicDirectory<std::string>(path));
|
||||
auto status = mkdir(p.c_str(), 0777);
|
||||
}
|
||||
if (!artistDirectoryExists(song, path)) {
|
||||
auto status = mkdir(artistPath<std::string>(song, path).c_str(), 0777);
|
||||
}
|
||||
if (!albumDirectoryExists(song, path)) {
|
||||
auto status = mkdir(albumPath(song, path), 0777);
|
||||
}
|
||||
if (!albumDiscDirectoryExists(song, path)) {
|
||||
auto status = mkdir(albumDiscPath(song, path), 0777);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename Str = std::string>
|
||||
static auto rootMusicDirectory(const Str& path) {
|
||||
auto rootPath = utility::GeneralUtility::appendForwardSlashToUri<std::string>(path);
|
||||
rootPath.append("music/");
|
||||
|
||||
return rootPath;
|
||||
}
|
||||
|
||||
|
||||
template<typename Str = std::string, typename B = bool>
|
||||
B albumDirectoryExists(const Song song, const Str& path) {
|
||||
// auto albumPath = utility::GeneralUtility::appendForwardSlashToUri<std::string>(path);
|
||||
auto albumPath = rootMusicDirectory<std::string>(path);
|
||||
albumPath.append(song.albumArtist);
|
||||
albumPath.append("/");
|
||||
albumPath.append(song.album);
|
||||
|
||||
DIR* dir = opendir(albumPath.c_str());
|
||||
|
||||
if (dir) {
|
||||
closedir(dir);
|
||||
return true;
|
||||
} else if (ENOENT == errno) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Str = std::string, typename B = bool>
|
||||
B albumDiscDirectoryExists(const Song& song, const Str& path) {
|
||||
std::string albumDistPath = albumPath(song, path);
|
||||
albumDistPath.append("/disc");
|
||||
if (song.disc == 0) {
|
||||
albumDistPath.append("1");
|
||||
} else {
|
||||
albumDistPath.append(std::to_string(song.disc));
|
||||
}
|
||||
|
||||
DIR *dir = opendir(albumDistPath.c_str());
|
||||
|
||||
if (dir) {
|
||||
closedir(dir);
|
||||
return true;
|
||||
} else if (ENOENT == errno) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Str = std::string, typename B = bool>
|
||||
B artistDirectoryExists(const Song& song, const Str& path) {
|
||||
// auto artistPath = utility::GeneralUtility::appendForwardSlashToUri<std::string>(path);
|
||||
auto artistPath = rootMusicDirectory<std::string>(path);
|
||||
artistPath.append(song.albumArtist);
|
||||
DIR* dir = opendir(artistPath.c_str());
|
||||
|
||||
if (dir) {
|
||||
closedir(dir);
|
||||
return true;
|
||||
} else if (ENOENT == errno) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Str = std::string, typename B = bool>
|
||||
B rootMusicDirectoryExists(const Str& path) {
|
||||
auto rootPath = rootMusicDirectory<std::string>(path);
|
||||
DIR *dir = opendir(rootPath.c_str());
|
||||
|
||||
if (dir) {
|
||||
closedir(dir);
|
||||
return true;
|
||||
} else if (ENOENT == errno) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MEAR_DIRECTORYMANAGER_H
|
||||
@@ -1,109 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/1/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_TOK_H
|
||||
#define MEAR_TOK_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "../model/Token.h"
|
||||
#include "../model/User.h"
|
||||
|
||||
namespace manager {
|
||||
template<class Token = model::Token>
|
||||
class Tok {
|
||||
public:
|
||||
template<class User = model::User>
|
||||
Token fetchTokenTrans(const User& user, const std::string& uri) {
|
||||
CURL *curl;
|
||||
struct curl_slist *chunk = nullptr;
|
||||
CURLcode res;
|
||||
|
||||
curl = curl_easy_init();
|
||||
|
||||
if (!curl) {
|
||||
return model::Token("none");
|
||||
}
|
||||
|
||||
std::string resp;
|
||||
const auto loginUri = fetchLoginUri(uri);
|
||||
const auto obj = userJsonString(user);
|
||||
|
||||
constexpr auto contentType = "Content-type: Keep-alive";
|
||||
chunk = curl_slist_append(chunk, contentType);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, loginUri.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, obj.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeOut<long>());
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (res == CURLE_OK) {
|
||||
long respCode;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &respCode);
|
||||
|
||||
if (respCode != 200) {
|
||||
return Token(std::move("failure"));
|
||||
}
|
||||
|
||||
auto s = nlohmann::json::parse(resp);
|
||||
const auto tokenStr = std::move(s["token"].get<std::string>());
|
||||
|
||||
return Token(std::move(tokenStr));
|
||||
}
|
||||
|
||||
return Token("failure");
|
||||
}
|
||||
private:
|
||||
std::string fetchLoginUri(const std::string& uriBase) noexcept {
|
||||
std::string uri(uriBase);
|
||||
if (uri.at(uri.size() - 1) != '/') {
|
||||
uri.append("/");
|
||||
}
|
||||
uri.append(loginEndpoint());
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
std::string userJsonString(const model::User& user) {
|
||||
nlohmann::json usr;
|
||||
usr["username"] = user.username;
|
||||
usr["password"] = user.password;
|
||||
|
||||
return usr.dump();
|
||||
}
|
||||
|
||||
|
||||
template<typename L>
|
||||
constexpr L timeOut() noexcept {
|
||||
return 15L;
|
||||
}
|
||||
|
||||
|
||||
constexpr auto loginEndpoint() noexcept {
|
||||
return "api/v1/login";
|
||||
}
|
||||
|
||||
|
||||
static size_t respBodyRetriever(void* ptr, size_t size, size_t nmemb, char* e) {
|
||||
((std::string*)e)->append((char*)ptr, size * nmemb);
|
||||
|
||||
return size * nmemb;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //MEAR_TOK_H
|
||||
@@ -1,30 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/12/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_APIINFO_H
|
||||
#define MEAR_APIINFO_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace model {
|
||||
class APIInfo
|
||||
{
|
||||
public:
|
||||
APIInfo() = default;
|
||||
APIInfo(const std::string& uri) :
|
||||
uri(uri) { }
|
||||
APIInfo(const std::string& uri, const int version) :
|
||||
uri(uri), version(version) { }
|
||||
APIInfo(const std::string&& uri, const int version) :
|
||||
uri(uri), version(version) { }
|
||||
APIInfo(const std::string& uri, const std::string& endpoint, const int version) :
|
||||
uri(uri), endpoint(endpoint), version(version) { }
|
||||
|
||||
std::string uri;
|
||||
std::string endpoint;
|
||||
int version;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MEAR_APIINFO_H
|
||||
@@ -1,24 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 11/8/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_COVERART_H
|
||||
#define MEAR_COVERART_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace model {
|
||||
class CoverArt {
|
||||
public:
|
||||
CoverArt() = default;
|
||||
CoverArt(const int id, const std::string& title) :
|
||||
id(id), title(title) { }
|
||||
CoverArt(const int id, const std::string&& title) :
|
||||
id(id), title(title) { }
|
||||
|
||||
int id;
|
||||
std::string title;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MEAR_COVERART_H
|
||||
@@ -1,46 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 9/26/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_SONG_H
|
||||
#define MEAR_SONG_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace model {
|
||||
class Song {
|
||||
public:
|
||||
Song() = default;
|
||||
Song(const int id) : id(id) { }
|
||||
Song(const int id, const std::string& title, const std::string& artist,
|
||||
const std::string& album, const std::string& genre,
|
||||
const int duration, const int year) :
|
||||
id(id), title(title), artist(artist), album(album),
|
||||
genre(genre), duration(duration), year(year) { }
|
||||
Song(const int id, const std::string& title, const std::string& artist,
|
||||
const std::string& album, const std::string& albumArtist, const std::string& genre,
|
||||
const int duration, const int year, const int coverArtId) :
|
||||
id(id), title(title), artist(artist), album(album), albumArtist(albumArtist),
|
||||
genre(genre), duration(duration), year(year), coverArtId(coverArtId) { }
|
||||
|
||||
int id;
|
||||
std::string title;
|
||||
std::string artist;
|
||||
std::string album;
|
||||
std::string albumArtist;
|
||||
std::string genre;
|
||||
int duration;
|
||||
int track;
|
||||
int disc;
|
||||
int year;
|
||||
int coverArtId;
|
||||
std::vector<char> data;
|
||||
bool downloaded;
|
||||
std::string path;
|
||||
std::string filename;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MEAR_SONG_H
|
||||
@@ -1,23 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/6/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_TOKEN_H
|
||||
#define MEAR_TOKEN_H
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace model {
|
||||
class Token
|
||||
{
|
||||
public:
|
||||
Token() = default;
|
||||
Token(const std::string& accessToken) : accessToken(accessToken) { }
|
||||
Token(const std::string&& accessToken) : accessToken(accessToken) { }
|
||||
|
||||
std::string accessToken;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MEAR_TOKEN_H
|
||||
@@ -1,26 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 9/26/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_USER_H
|
||||
#define MEAR_USER_H
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace model {
|
||||
class User
|
||||
{
|
||||
public:
|
||||
User() = default;
|
||||
User(const std::string& user, const std::string& pass) :
|
||||
username(user), password(pass) { }
|
||||
User(const std::string&& user, const std::string&& pass) :
|
||||
username(user), password(pass) {}
|
||||
|
||||
std::string username;
|
||||
std::string password;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MEAR_USER_H
|
||||
@@ -1,112 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/12/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_APIREPOSITORY_H
|
||||
#define MEAR_APIREPOSITORY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "BaseRepository.h"
|
||||
#include "../model/APIInfo.h"
|
||||
|
||||
namespace repository { namespace local {
|
||||
class APIRepository: public BaseRepository {
|
||||
public:
|
||||
APIRepository() {
|
||||
m_tableName = apiInfoTable();
|
||||
}
|
||||
|
||||
|
||||
model::APIInfo retrieveAPIInfo(const std::string& path) {
|
||||
model::APIInfo apiInfo;
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(path);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READONLY);
|
||||
|
||||
std::string queryString("SELECT * FROM ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" LIMIT 1");
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
|
||||
auto result = query.executeStep();
|
||||
apiInfo.uri = query.getColumn(1).getString();
|
||||
apiInfo.version = query.getColumn(2).getInt();
|
||||
|
||||
return apiInfo;
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
|
||||
return apiInfo;
|
||||
}
|
||||
|
||||
|
||||
[[deprecated("use the base class function")]]
|
||||
bool doesAPIInfoTableExist(const std::string& path) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(path);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READONLY);
|
||||
|
||||
return db.tableExists(m_tableName);
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void createAPiInfoTable(const std::string& path) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(path);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READWRITE);
|
||||
|
||||
std::string queryString("CREATE TABLE ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (Id INTEGER PRIMARY KEY, Uri TEXT, Version INT)");
|
||||
db.exec(queryString);
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
void deleteAPIInfo(const model::APIInfo& apiInfo, const std::string& path) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(path);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READWRITE);
|
||||
|
||||
std::string queryString("DELETE FROM ");
|
||||
queryString.append(m_tableName);
|
||||
|
||||
db.exec(queryString);
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
void saveAPIInfo(const model::APIInfo& apiInfo, const std::string& path) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(path);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READWRITE);
|
||||
std::string queryString("INSERT INTO ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (Uri, Version) VALUES (?, ?)");
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
query.bind(1, apiInfo.uri);
|
||||
query.bind(2, apiInfo.version);
|
||||
|
||||
query.exec();
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::string apiInfoTable() noexcept { return "APIInfo"; }
|
||||
};
|
||||
}}
|
||||
|
||||
|
||||
#endif //MEAR_APIREPOSITORY_H
|
||||
@@ -1,127 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/6/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_BASEREPOSITORY_H
|
||||
#define MEAR_BASEREPOSITORY_H
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include <SQLiteCpp/Database.h>
|
||||
|
||||
#include "../types/ConnType.h"
|
||||
|
||||
namespace repository { namespace local {
|
||||
using type::ConnType;
|
||||
|
||||
class BaseRepository {
|
||||
public:
|
||||
bool databaseExist(const std::string& appPath) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READONLY);
|
||||
return true;
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool doesTableExist(const std::string& appPath) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READONLY);
|
||||
|
||||
auto result = db.tableExists(m_tableName);
|
||||
return result;
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isTableEmpty(const std::string& appPath) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READONLY);
|
||||
std::string queryStr("SELECT * FROM ");
|
||||
queryStr.append(m_tableName);
|
||||
|
||||
SQLite::Statement query(db, queryStr);
|
||||
|
||||
auto r = query.executeStep();
|
||||
|
||||
const auto result = query.hasRow();
|
||||
|
||||
return !result;
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void initializedDatabase(const std::string& appPath) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_CREATE | SQLite::OPEN_READWRITE);
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
void deleteRecord(const std::string& appPath) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_CREATE | SQLite::OPEN_READWRITE);
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
protected:
|
||||
std::string pathOfDatabase(const std::string& appPath) {
|
||||
std::string dbPath(appPath);
|
||||
auto lastChar = dbPath.at(dbPath.size()-1);
|
||||
if (lastChar != '/') {
|
||||
dbPath.append("/");
|
||||
}
|
||||
|
||||
dbPath.append(databaseName());
|
||||
|
||||
return dbPath;
|
||||
}
|
||||
|
||||
template<typename Str = std::string>
|
||||
const Str databaseName() noexcept { return "mear.db3"; }
|
||||
|
||||
|
||||
SQLite::Database getDbConn(const std::string& path, ConnType dbType) {
|
||||
auto dbPath = pathOfDatabase(path);
|
||||
switch (dbType) {
|
||||
case ConnType::ReadOnly:
|
||||
return SQLite::Database(dbPath, SQLite::OPEN_READONLY);
|
||||
case ConnType::ReadWrite:
|
||||
return SQLite::Database(dbPath, SQLite::OPEN_READWRITE);
|
||||
case ConnType::Create:
|
||||
return SQLite::Database(dbPath, SQLite::OPEN_CREATE);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return SQLite::Database(dbPath);
|
||||
}
|
||||
|
||||
std::string m_tableName;
|
||||
private:
|
||||
};
|
||||
} }
|
||||
|
||||
|
||||
#endif //MEAR_BASEREPOSITORY_H
|
||||
@@ -1,97 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 11/8/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_COVERARTREPOSITORY_H
|
||||
#define MEAR_COVERARTREPOSITORY_H
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include "../3rdparty/android/include/curl/curl.h"
|
||||
|
||||
#include "../model/CoverArt.h"
|
||||
#include "../model/Token.h"
|
||||
|
||||
using data = char;
|
||||
|
||||
namespace repository {
|
||||
template<typename C>
|
||||
class CoverArtRepository {
|
||||
public:
|
||||
// TODO: implement this
|
||||
std::vector<C> retrieveCoverArtRecords(const model::Token& token, const std::string& uri) {
|
||||
std::vector<std::string> vals;
|
||||
|
||||
return vals;
|
||||
}
|
||||
|
||||
std::vector<data> retrieveCoverArtData(const model::Token& token, const C& cover,
|
||||
const std::string& uri) {
|
||||
std::string fullUri(uri);
|
||||
if (fullUri.at(fullUri.size() - 1) != '/') {
|
||||
fullUri.append("/");
|
||||
}
|
||||
fullUri.append(downloadEndpoint());
|
||||
fullUri.append(std::to_string(cover.id));
|
||||
|
||||
CURL *curl;
|
||||
struct curl_slist *chunk = nullptr;
|
||||
curl = curl_easy_init();
|
||||
|
||||
if (!curl) {
|
||||
return std::vector<data>();
|
||||
}
|
||||
|
||||
std::string data;
|
||||
std::string authHeader("Authorization: Bearer ");
|
||||
authHeader.append(token.accessToken);
|
||||
constexpr auto keepAliveHeader = "Content-type: Keep-alive";
|
||||
chunk = curl_slist_append(chunk, authHeader.c_str());
|
||||
chunk = curl_slist_append(chunk, keepAliveHeader);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, fullUri.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
|
||||
auto res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
std::vector<char> vals(data.begin(), data.end());
|
||||
|
||||
return vals;
|
||||
}
|
||||
|
||||
// TODO: implement this
|
||||
C retrieveCoverArtRecord(const model::Token& token, const C& cover,
|
||||
const std::string& uri) {
|
||||
C cov;
|
||||
|
||||
return cov;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
constexpr auto downloadEndpoint() noexcept {
|
||||
return "api/v1/coverart/download/";
|
||||
}
|
||||
|
||||
constexpr auto recordsEndpoint() noexcept {
|
||||
return "api/v1/coverart/";
|
||||
}
|
||||
|
||||
static size_t respBodyRetriever(void *ptr, size_t size,
|
||||
size_t nmemb, char *e) {
|
||||
((std::string*)e)->append((char*)ptr, size * nmemb);
|
||||
|
||||
return size * nmemb;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //MEAR_COVERARTREPOSITORY_H
|
||||
@@ -1,105 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/21/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_REPEATREPOSITORY_H
|
||||
#define MEAR_REPEATREPOSITORY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "BaseRepository.h"
|
||||
#include "../types/RepeatTypes.h"
|
||||
|
||||
namespace repository { namespace local {
|
||||
class RepeatRepository : public BaseRepository {
|
||||
public:
|
||||
RepeatRepository() {
|
||||
m_tableName = repeatTable();
|
||||
}
|
||||
|
||||
|
||||
RepeatTypes retrieveRepeatMode(const std::string& path) {
|
||||
try {
|
||||
auto db = getDbConn(path, ConnType::ReadOnly);
|
||||
std::string queryString("SELECT * FROM ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" LIMIT 1");
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
|
||||
const auto result = query.executeStep();
|
||||
|
||||
auto repeatType = query.getColumn(1).getInt();
|
||||
auto val = static_cast<RepeatTypes>(repeatType);
|
||||
return val;
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
|
||||
return RepeatTypes::RepeatOff;
|
||||
}
|
||||
|
||||
|
||||
void createRepeatTable(const std::string& path) {
|
||||
try {
|
||||
auto db = getDbConn(path, ConnType::ReadWrite);
|
||||
std::string queryString("CREATE TABLE ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (Id INTEGER PRIMARY KEY, RepeatMode INT)");
|
||||
|
||||
db.exec(queryString);
|
||||
|
||||
queryString = "INSERT INTO " + m_tableName + " (RepeatMode) VALUES(?)";
|
||||
SQLite::Statement query(db, queryString);
|
||||
query.bind(1, static_cast<int>(RepeatTypes::RepeatOff));
|
||||
query.exec();
|
||||
|
||||
} catch (std::exception &ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
void updateRepeat(const std::string& path) {
|
||||
try {
|
||||
auto db = getDbConn(path, ConnType::ReadWrite);
|
||||
|
||||
if (isTableEmpty(path)) {
|
||||
std::string queryString("INSERT INTO ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (RepeatMode) VALUES (?)");
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
query.bind(1, static_cast<int>(RepeatTypes::RepeatOff));
|
||||
query.exec();
|
||||
} else {
|
||||
std::string queryString("UPDATE ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" SET RepeatMode = ?");
|
||||
|
||||
auto repeatMode = retrieveRepeatMode(path);
|
||||
SQLite::Statement query(db, queryString);
|
||||
|
||||
switch (repeatMode) {
|
||||
case RepeatTypes::RepeatOff:
|
||||
query.bind(1, static_cast<int>(RepeatTypes::RepeatSong));
|
||||
break;
|
||||
case RepeatTypes::RepeatSong:
|
||||
query.bind(1, static_cast<int>(RepeatTypes::RepeatOff));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
query.exec();
|
||||
}
|
||||
} catch (std::exception &ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::string repeatTable() noexcept { return "Repeat"; }
|
||||
};
|
||||
}}
|
||||
|
||||
|
||||
#endif //MEAR_REPEATREPOSITORY_H
|
||||
@@ -1,109 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/21/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_SHUFFLEREPOSITORY_H
|
||||
#define MEAR_SHUFFLEREPOSITORY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "BaseRepository.h"
|
||||
#include "../types/ShuffleTypes.h"
|
||||
|
||||
namespace repository { namespace local {
|
||||
class ShuffleRepository : public BaseRepository {
|
||||
public:
|
||||
ShuffleRepository() {
|
||||
m_tableName = shuffleTable();
|
||||
}
|
||||
|
||||
|
||||
ShuffleTypes retrieveShuffleMode(const std::string& path) {
|
||||
try {
|
||||
auto db = getDbConn(path, ConnType::ReadOnly);
|
||||
std::string queryString("SELECT * FROM ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" LIMIT 1");
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
|
||||
const auto result = query.executeStep();
|
||||
auto shuffleType = query.getColumn(1).getInt();
|
||||
auto val = static_cast<ShuffleTypes>(shuffleType);
|
||||
|
||||
return val;
|
||||
|
||||
} catch (std::exception &ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
|
||||
return ShuffleTypes::ShuffleOff;
|
||||
}
|
||||
|
||||
|
||||
void createShuffleTable(const std::string& path) {
|
||||
try {
|
||||
auto db = getDbConn(path, ConnType::ReadWrite);
|
||||
std::string queryString("CREATE TABLE ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (Id INTEGER PRIMARY KEY, ShuffleMode INT)");
|
||||
|
||||
db.exec(queryString);
|
||||
|
||||
queryString = "INSERT INTO ";
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (ShuffleMode) VALUES(?)");
|
||||
SQLite::Statement query(db, queryString);
|
||||
query.bind(1, static_cast<int>(ShuffleTypes::ShuffleOff));
|
||||
query.exec();
|
||||
} catch (std::exception &ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
void updateShuffle(const std::string& path) {
|
||||
try {
|
||||
auto db = getDbConn(path, ConnType::ReadWrite);
|
||||
|
||||
if (!doesTableExist(path)) {
|
||||
createShuffleTable(path);
|
||||
}
|
||||
|
||||
if (isTableEmpty(path)) {
|
||||
constexpr auto queryString = "INSERT INTO ? (ShuffleMode) VALUES(?)";
|
||||
SQLite::Statement query(db, queryString);
|
||||
query.bind(1, m_tableName);
|
||||
query.bind(2, static_cast<int>(ShuffleTypes::ShuffleOff));
|
||||
query.exec();
|
||||
} else {
|
||||
std::string queryString("UPDATE ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" SET ShuffleMode = ?");
|
||||
|
||||
auto shuffleMode = retrieveShuffleMode(path);
|
||||
SQLite::Statement query(db, queryString);
|
||||
|
||||
switch (shuffleMode) {
|
||||
case ShuffleTypes::ShuffleOff:
|
||||
query.bind(1, static_cast<int>(ShuffleTypes::ShuffleOn));
|
||||
break;
|
||||
case ShuffleTypes::ShuffleOn:
|
||||
query.bind(1, static_cast<int>(ShuffleTypes::ShuffleOff));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
query.exec();
|
||||
}
|
||||
} catch (std::exception &ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::string shuffleTable() noexcept { return "Shuffle"; }
|
||||
};
|
||||
}}
|
||||
|
||||
|
||||
#endif //MEAR_SHUFFLEREPOSITORY_H
|
||||
@@ -1,338 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/3/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_SONGREPOSITORY_H
|
||||
#define MEAR_SONGREPOSITORY_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../3rdparty/android/include/curl/curl.h"
|
||||
#include "../3rdparty/json/single_include/nlohmann/json.hpp"
|
||||
|
||||
#include "../model/Song.h"
|
||||
#include "../model/Token.h"
|
||||
#include "BaseRepository.h"
|
||||
#include "../utility/GeneralUtility.h"
|
||||
|
||||
namespace repository {
|
||||
|
||||
template<class Song = model::Song>
|
||||
class SongRepository {
|
||||
public:
|
||||
template<typename Token = model::Token>
|
||||
std::vector<Song> fetchSongs(const Token& token, const std::string& uri) {
|
||||
auto fullUri = utility::GeneralUtility::appendForwardSlashToUri<std::string>(uri);
|
||||
fullUri.append(songRecordEndpoint());
|
||||
std::vector<Song> songs;
|
||||
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
struct curl_slist *chunk = nullptr;
|
||||
curl = curl_easy_init();
|
||||
|
||||
if (!curl) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
std::string resp;
|
||||
|
||||
std::string authInfo("Authorization: Bearer ");
|
||||
authInfo.append(token.accessToken);
|
||||
constexpr auto contentType = "Content-type: Keep-alive";
|
||||
chunk = curl_slist_append(chunk, authInfo.c_str());
|
||||
chunk = curl_slist_append(chunk, contentType);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, fullUri.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (res == CURLE_OK) {
|
||||
auto songsJson = nlohmann::json::parse(resp.c_str());
|
||||
for (auto& songJson: songsJson) {
|
||||
Song song(songJson["id"].get<int>(), songJson["title"].get<std::string>(),
|
||||
songJson["artist"].get<std::string>(),
|
||||
songJson["album"].get<std::string>(),
|
||||
songJson["album_artist"].get<std::string>(),
|
||||
songJson["genre"].get<std::string>(), songJson["duration"].get<int>(),
|
||||
songJson["year"].get<int>(), songJson["coverart_id"].get<int>());
|
||||
song.filename = "";
|
||||
song.path = "";
|
||||
song.track = songJson["track"].get<int>();
|
||||
song.disc = songJson["disc"].get<int>();
|
||||
song.downloaded = false;
|
||||
|
||||
songs.push_back(song);
|
||||
}
|
||||
}
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
template<typename Token = model::Token>
|
||||
Song retrieveSong(const Token& token, const Song& sng,
|
||||
const std::string& baseUri) {
|
||||
auto uri = utility::GeneralUtility::appendForwardSlashToUri(baseUri);
|
||||
uri.append(songRecordEndpoint());
|
||||
uri.append(std::to_string(sng.id));
|
||||
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
struct curl_slist *chunk = nullptr;
|
||||
curl = curl_easy_init();
|
||||
|
||||
if (!curl) {
|
||||
return sng;
|
||||
}
|
||||
|
||||
std::string resp;
|
||||
|
||||
std::string authInfo("Authorization: Bearer ");
|
||||
authInfo.append(token.accessToken);
|
||||
constexpr auto contentType = "Content-type: Keep-alive";
|
||||
chunk = curl_slist_append(chunk, authInfo.c_str());
|
||||
chunk = curl_slist_append(chunk, contentType);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, uri.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (res == CURLE_OK) {
|
||||
auto s = nlohmann::json::parse(resp.c_str());
|
||||
Song song(s["id"].get<int>(), s["title"].get<std::string>(),
|
||||
s["artist"].get<std::string>(), s["album"].get<std::string>(),
|
||||
s["album_artist"].get<std::string>(), s["genre"].get<std::string>(),
|
||||
s["duration"].get<int>(), s["year"].get<int>(),
|
||||
s["coverart_id"].get<int>());
|
||||
song.track = s["track"].get<int>();
|
||||
song.disc = s["disc"].get<int>();
|
||||
song.filename = "";
|
||||
song.path = "";
|
||||
song.downloaded = false;
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
return sng;
|
||||
}
|
||||
|
||||
template<typename Token = model::Token, typename API = model::APIInfo>
|
||||
Song downloadSong(const Token &token, const Song& song, const API& uri) {
|
||||
auto fullUri = utility::GeneralUtility::appendForwardSlashToUri(uri.uri);
|
||||
fullUri.append(songDownloadEndpoint());
|
||||
fullUri.append(std::to_string(song.id));
|
||||
Song downloadedSong = song;
|
||||
|
||||
CURL *curl = curl_easy_init();
|
||||
struct curl_slist *chunk = nullptr;
|
||||
|
||||
std::string data;
|
||||
const auto authHeader = utility::GeneralUtility::authHeader(token);
|
||||
chunk = curl_slist_append(chunk, authHeader.c_str());
|
||||
chunk = curl_slist_append(chunk, "Content-type: Keep-alive");
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, fullUri.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, respBodyRetriever);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
|
||||
auto res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
downloadedSong.data = std::move(std::vector<char>(data.begin(), data.end()));
|
||||
|
||||
return downloadedSong;
|
||||
}
|
||||
private:
|
||||
static size_t respBodyRetriever(void *ptr, size_t size, size_t nmemb, char *e) {
|
||||
((std::string*)e)->append((char*)ptr, size * nmemb);
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
constexpr auto songRecordEndpoint() noexcept { return "api/v1/song/"; }
|
||||
|
||||
constexpr auto songDownloadEndpoint() noexcept { return "api/v1/song/data/"; }
|
||||
};
|
||||
|
||||
namespace local {
|
||||
template<class Song = model::Song>
|
||||
class SongRepository : public BaseRepository {
|
||||
public:
|
||||
SongRepository() {
|
||||
m_tableName = songTable();
|
||||
}
|
||||
|
||||
template<typename Str = std::string>
|
||||
SongRepository(const Str& val) {
|
||||
m_tableName = songTable();
|
||||
if (!databaseExist(val)) {
|
||||
initializedDatabase(val);
|
||||
}
|
||||
if (!doesTableExist(val)) {
|
||||
createSongTable(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<Song> retrieveAllSongs(const std::string& appPath) {
|
||||
std::vector<Song> downloadedSongs;
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READONLY);
|
||||
|
||||
std::string queryString("SELECT * FROM ");
|
||||
queryString.append(m_tableName);
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
|
||||
while (query.executeStep()) {
|
||||
Song song;
|
||||
song.id = query.getColumn(0).getInt();
|
||||
song.title = query.getColumn(1).getString();
|
||||
song.artist = query.getColumn(2).getString();
|
||||
song.album = query.getColumn(3).getString();
|
||||
song.albumArtist = query.getColumn(4).getString();
|
||||
song.genre = query.getColumn(5).getString();
|
||||
song.year = query.getColumn(6).getInt();
|
||||
song.duration = query.getColumn(7).getInt();
|
||||
song.track = query.getColumn(8).getInt();
|
||||
song.disc = query.getColumn(9).getInt();
|
||||
song.filename = query.getColumn(10).getString();
|
||||
song.path = query.getColumn(11).getString();
|
||||
song.coverArtId = query.getColumn(12).getInt();
|
||||
song.downloaded = true;
|
||||
|
||||
downloadedSongs.push_back(song);
|
||||
}
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
|
||||
return downloadedSongs;
|
||||
}
|
||||
|
||||
|
||||
Song retrieveSong(const Song& song, const std::string& appPath) {
|
||||
Song retrievedSong;
|
||||
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READONLY);
|
||||
|
||||
std::string queryString("SELECT * FROM ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" WHERE Id = ?");
|
||||
queryString.append(" LIMIT 1");
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
query.bind(1, song.id);
|
||||
auto result = query.executeStep();
|
||||
|
||||
retrievedSong.id = query.getColumn(0).getInt();
|
||||
retrievedSong.title = query.getColumn(1).getString();
|
||||
retrievedSong.artist = query.getColumn(2).getString();
|
||||
retrievedSong.album = query.getColumn(3).getString();
|
||||
retrievedSong.albumArtist = query.getColumn(4).getString();
|
||||
retrievedSong.genre = query.getColumn(5).getString();
|
||||
retrievedSong.year = query.getColumn(6).getInt();
|
||||
retrievedSong.duration = query.getColumn(7).getInt();
|
||||
retrievedSong.track = query.getColumn(8).getInt();
|
||||
retrievedSong.disc = query.getColumn(9).getInt();
|
||||
retrievedSong.filename = query.getColumn(10).getString();
|
||||
retrievedSong.path = query.getColumn(11).getString();
|
||||
retrievedSong.coverArtId = query.getColumn(12).getInt();
|
||||
retrievedSong.downloaded = true;
|
||||
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
|
||||
return retrievedSong;
|
||||
}
|
||||
|
||||
|
||||
void createSongTable(const std::string& appPath) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READWRITE);
|
||||
|
||||
std::string queryString("CREATE TABLE ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (Id INTEGER, Title TEXT, Artist TEXT, Album TEXT, ");
|
||||
queryString.append("AlbumArtist TEXT, Genre TEXT, Year INTEGER, ");
|
||||
queryString.append("Duration INTEGER, Track INTEGER, Disc INTEGER, ");
|
||||
queryString.append("Filename TEXT, Path TEXT, CoverArtId INTEGER)");
|
||||
|
||||
db.exec(queryString);
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
void deleteSongFromTable(const Song& song, const std::string& appPath) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READWRITE);
|
||||
|
||||
std::string queryString("DELETE FROM ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" WHERE Id = ?");
|
||||
SQLite::Statement query(db, queryString);
|
||||
query.bind(1, song.id);
|
||||
|
||||
query.exec();
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
void saveSong(const Song& song, const std::string& appPath) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READWRITE);
|
||||
|
||||
std::string queryString("INSERT INTO ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (Id, Title, Artist, Album, AlbumArtist, Genre, Year, ");
|
||||
queryString.append("Duration, Track, Disc, Filename, Path, CoverArtId) ");
|
||||
queryString.append("VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
query.bind(1, song.id);
|
||||
query.bind(2, song.title);
|
||||
query.bind(3, song.artist);
|
||||
query.bind(4, song.album);
|
||||
query.bind(5, song.albumArtist);
|
||||
query.bind(6, song.genre);
|
||||
query.bind(7, song.year);
|
||||
query.bind(8, song.duration);
|
||||
query.bind(9, song.track);
|
||||
query.bind(10, song.disc);
|
||||
query.bind(11, song.filename);
|
||||
query.bind(12, song.path);
|
||||
query.bind(13, song.coverArtId);
|
||||
|
||||
auto result = query.exec();
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
private:
|
||||
constexpr auto songTable() noexcept { return "Song"; }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //MEAR_SONGREPOSITORY_H
|
||||
@@ -1,81 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/6/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_TOKENREPOSITORY_H
|
||||
#define MEAR_TOKENREPOSITORY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../model/Token.h"
|
||||
#include "BaseRepository.h"
|
||||
|
||||
namespace repository { namespace local {
|
||||
template<class Token = model::Token>
|
||||
class TokenRepository: public BaseRepository {
|
||||
public:
|
||||
TokenRepository() {
|
||||
m_tableName = tokenTable();
|
||||
}
|
||||
|
||||
|
||||
Token retrieveToken(const std::string& path) {
|
||||
Token token;
|
||||
|
||||
try {
|
||||
auto db = getDbConn(path, ConnType::ReadOnly);
|
||||
std::string queryString("SELECT * FROM ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" LIMIT 1");
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
|
||||
auto result = query.executeStep();
|
||||
token.accessToken = std::move(query.getColumn(1).getString());
|
||||
|
||||
return token;
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
|
||||
void createTokenTable(const std::string& path) {
|
||||
try {
|
||||
auto db = getDbConn(path, ConnType::ReadWrite);
|
||||
|
||||
std::string queryString("CREATE TABLE ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (Id INTEGER PRIMARY KEY, AccessToken TEXT)");
|
||||
|
||||
db.exec(queryString);
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
void saveToken(const Token& token, const std::string& path) {
|
||||
try {
|
||||
auto db = getDbConn(path, ConnType::ReadWrite);
|
||||
|
||||
std::string queryString("INSERT INTO ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (AccessToken) VALUES (?)");
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
query.bind(1, token.accessToken);
|
||||
|
||||
query.exec();
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::string tokenTable() noexcept { return "Token"; }
|
||||
};
|
||||
}}
|
||||
|
||||
|
||||
#endif //MEAR_TOKENREPOSITORY_H
|
||||
@@ -1,101 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/6/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_USERREPOSITORY_H
|
||||
#define MEAR_USERREPOSITORY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "BaseRepository.h"
|
||||
#include "../model/User.h"
|
||||
|
||||
|
||||
namespace repository { namespace local {
|
||||
template<class User = model::User>
|
||||
class UserRepository : public BaseRepository {
|
||||
public:
|
||||
UserRepository() {
|
||||
m_tableName = userTable();
|
||||
}
|
||||
|
||||
|
||||
User retrieveUserCredentials(const std::string& appPath) {
|
||||
User user;
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READONLY);
|
||||
|
||||
std::string queryString("SELECT * FROM ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" LIMIT 1");
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
|
||||
auto result = query.executeStep();
|
||||
|
||||
user.username = std::move(query.getColumn(1).getString());
|
||||
user.password = std::move(query.getColumn(2).getString());
|
||||
|
||||
return user;
|
||||
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
void createUserTable(const std::string& appPath) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READWRITE);
|
||||
|
||||
std::string queryString("CREATE TABLE ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (Id INTEGER PRIMARY KEY, Username TEXT, Password TEXT)");
|
||||
db.exec(queryString);
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
void deleteUserTable(const std::string& appPath) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READWRITE);
|
||||
|
||||
std::string queryStr("DELETE FROM ");
|
||||
queryStr.append(m_tableName);
|
||||
|
||||
db.exec(queryStr);
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
void saveUserCred(const User& user, const std::string& appPath) {
|
||||
try {
|
||||
const auto dbPath = pathOfDatabase(appPath);
|
||||
SQLite::Database db(dbPath, SQLite::OPEN_READWRITE);
|
||||
std::string queryString("INSERT INTO ");
|
||||
queryString.append(m_tableName);
|
||||
queryString.append(" (Username, Password) VALUES (?, ?)");
|
||||
|
||||
SQLite::Statement query(db, queryString);
|
||||
query.bind(1, user.username);
|
||||
query.bind(2, user.password);
|
||||
|
||||
query.exec();
|
||||
} catch (std::exception& ex) {
|
||||
auto msg = ex.what();
|
||||
}
|
||||
}
|
||||
private:
|
||||
const std::string userTable() noexcept { return "User"; }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif //MEAR_USERREPOSITORY_H
|
||||
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 11/29/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_CONNTYPE_H
|
||||
#define MEAR_CONNTYPE_H
|
||||
|
||||
namespace type {
|
||||
enum class ConnType {
|
||||
ReadOnly = 0,
|
||||
ReadWrite = 1,
|
||||
Create = 2
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MEAR_CONNTYPE_H
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/21/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_REPEATTYPES_H
|
||||
#define MEAR_REPEATTYPES_H
|
||||
|
||||
|
||||
enum class RepeatTypes {
|
||||
RepeatSong = 0,
|
||||
RepeatOff = 1
|
||||
};
|
||||
|
||||
|
||||
#endif //MEAR_REPEATTYPES_H
|
||||
@@ -1,13 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 10/21/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_SHUFFLETYPES_H
|
||||
#define MEAR_SHUFFLETYPES_H
|
||||
|
||||
enum class ShuffleTypes {
|
||||
ShuffleOn = 0,
|
||||
ShuffleOff = 1
|
||||
};
|
||||
|
||||
#endif //MEAR_SHUFFLETYPES_H
|
||||
@@ -1,35 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 11/25/19.
|
||||
//
|
||||
|
||||
#ifndef MEAR_GENERALUTILITY_H
|
||||
#define MEAR_GENERALUTILITY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../model/Token.h"
|
||||
|
||||
namespace utility {
|
||||
class GeneralUtility {
|
||||
public:
|
||||
template<typename S = std::string>
|
||||
static S appendForwardSlashToUri(const S& uri) {
|
||||
std::string fullUri(uri);
|
||||
if (fullUri.at(fullUri.size() - 1) != '/') {
|
||||
fullUri.append("/");
|
||||
}
|
||||
|
||||
return fullUri;
|
||||
}
|
||||
template<typename S = std::string, class Token = model::Token>
|
||||
static S authHeader(const Token& token) {
|
||||
std::string header("Authorization: Bearer ");
|
||||
header.append(token.accessToken);
|
||||
|
||||
return header;
|
||||
}
|
||||
private:
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MEAR_GENERALUTILITY_H
|
||||
@@ -1,139 +0,0 @@
|
||||
//
|
||||
// Created by brahmix on 1/13/20.
|
||||
//
|
||||
|
||||
#ifndef MEAR_JNIOBJECTCONVERSION_H
|
||||
#define MEAR_JNIOBJECTCONVERSION_H
|
||||
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "../model/Token.h"
|
||||
#include "../model/User.h"
|
||||
|
||||
namespace utility {
|
||||
template<typename SomeClass, typename Obj = jobject>
|
||||
class JNIObjectConversion {
|
||||
public:
|
||||
// jobject to classes
|
||||
template<typename JE = JNIEnv>
|
||||
static SomeClass ObjToToken(JE *env, Obj tokenObj) {
|
||||
auto tokenClass = env->GetObjectClass(tokenObj);
|
||||
|
||||
auto accessTokenId = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;");
|
||||
|
||||
auto accessTokenVal = static_cast<jstring>(
|
||||
env->GetObjectField(tokenObj, accessTokenId));
|
||||
|
||||
SomeClass token(std::move(env->GetStringUTFChars(accessTokenVal, nullptr)));
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
template<typename JE = JNIEnv>
|
||||
static SomeClass ObjToUser(JE *env, Obj userObj) {
|
||||
auto userClass = env->GetObjectClass(userObj);
|
||||
|
||||
auto usernameId = env->GetFieldID(userClass, "username", "Ljava/lang/String;");
|
||||
auto passwordId = env->GetFieldID(userClass, "password", "Ljava/lang/String;");
|
||||
|
||||
auto usernameVal = static_cast<jstring>(env->GetObjectField(userObj, usernameId));
|
||||
auto passwordVal = static_cast<jstring>(env->GetObjectField(userObj, passwordId));
|
||||
|
||||
SomeClass user(std::move(env->GetStringUTFChars(usernameVal, nullptr)),
|
||||
std::move(env->GetStringUTFChars(passwordVal, nullptr)));
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
template<typename JE = JNIEnv>
|
||||
static SomeClass ObjToAPIInfo(JE *env, Obj apiObj) {
|
||||
auto apiClass = env->GetObjectClass(apiObj);
|
||||
|
||||
auto uriId = env->GetFieldID(apiClass, "uri", "Ljava/lang/String;");
|
||||
auto versionId = env->GetFieldID(apiClass, "version", "I");
|
||||
|
||||
auto uriVal = static_cast<jstring>(env->GetObjectField(apiObj, uriId));
|
||||
auto versionVal = env->GetIntField(apiObj, versionId);
|
||||
|
||||
SomeClass apiInfo(std::move(env->GetStringUTFChars(uriVal, nullptr)), versionVal);
|
||||
|
||||
return apiInfo;
|
||||
}
|
||||
|
||||
template<typename JE = JNIEnv>
|
||||
static SomeClass ObjToCoverArt(JE *env, Obj covObj) {
|
||||
auto coverClass = env->GetObjectClass(covObj);
|
||||
|
||||
auto idField = env->GetFieldID(coverClass, "id", "I");
|
||||
auto titleField = env->GetFieldID(coverClass, "title", "Ljava/lang/String;");
|
||||
|
||||
auto id = env->GetIntField(covObj, idField);
|
||||
auto title = static_cast<jstring>(env->GetObjectField(covObj, titleField));
|
||||
|
||||
SomeClass cover(id, std::move(env->GetStringUTFChars(title, nullptr)));
|
||||
|
||||
return cover;
|
||||
}
|
||||
|
||||
|
||||
// classes to jobject
|
||||
template<typename JE = JNIEnv>
|
||||
static Obj TokenToObj(JE *env, const SomeClass& token) {
|
||||
auto tokenClass = env->FindClass(classBasePath<std::string>("models/Token").c_str());
|
||||
auto tokenConstructor = env->GetMethodID(tokenClass, "<init>", "()V");
|
||||
auto tokenObj = env->NewObject(tokenClass, tokenConstructor);
|
||||
|
||||
auto accessTokenId = env->GetFieldID(tokenClass, "accessToken", "Ljava/lang/String;");
|
||||
|
||||
env->SetObjectField(tokenObj,
|
||||
accessTokenId, env->NewStringUTF(token.accessToken.c_str()));
|
||||
|
||||
return tokenObj;
|
||||
}
|
||||
|
||||
template<typename JE = JNIEnv>
|
||||
static Obj UserToObj(JE *env, const SomeClass& user) {
|
||||
auto userClass = env->FindClass(classBasePath<std::string>("models/User").c_str());
|
||||
auto classConstructor = env->GetMethodID(userClass, "<init>", "()V");
|
||||
auto userObj = env->NewObject(userClass, classConstructor);
|
||||
|
||||
auto usernameId = env->GetFieldID(userClass, "username", "Ljava/lang/String;");
|
||||
auto passwordId = env->GetFieldID(userClass, "password", "Ljava/lang/String;");
|
||||
|
||||
env->SetObjectField(userObj, usernameId, env->NewStringUTF(user.username.c_str()));
|
||||
env->SetObjectField(userObj, passwordId, env->NewStringUTF(user.password.c_str()));
|
||||
|
||||
return userObj;
|
||||
}
|
||||
|
||||
template<typename JE = JNIEnv>
|
||||
static Obj APIInfoToObj(JE *env, const SomeClass& apiInfo) {
|
||||
auto apiClass = env->FindClass(classBasePath<std::string>("models/APIInfo").c_str());
|
||||
auto apiConstructor = env->GetMethodID(apiClass, "<init>", "()V");
|
||||
auto apiObj = env->NewObject(apiClass, apiConstructor);
|
||||
|
||||
auto uriId = env->GetFieldID(apiClass, "uri", "Ljava/lang/String;");
|
||||
auto versionId = env->GetFieldID(apiClass, "version", "I");
|
||||
|
||||
env->SetObjectField(apiObj, uriId, env->NewStringUTF(apiInfo.uri.c_str()));
|
||||
env->SetIntField(apiObj, versionId, apiInfo.version);
|
||||
|
||||
return apiObj;
|
||||
}
|
||||
|
||||
|
||||
template<typename Str = std::string>
|
||||
static Str classBasePath(const Str& classPath = std::string()) noexcept {
|
||||
Str basePath("com/example/mear/");
|
||||
if (!classPath.empty()) {
|
||||
basePath.append(classPath);
|
||||
}
|
||||
|
||||
return basePath;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MEAR_JNIOBJECTCONVERSION_H
|
||||
@@ -1,90 +0,0 @@
|
||||
package com.example.mear
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceActivity
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.appcompat.app.ActionBar
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import android.view.MenuInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
/**
|
||||
* A [android.preference.PreferenceActivity] which implements and proxies the necessary calls
|
||||
* to be used with AppCompat.
|
||||
*/
|
||||
abstract class AppCompatPreferenceActivity : PreferenceActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
delegate.installViewFactory()
|
||||
delegate.onCreate(savedInstanceState)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onPostCreate(savedInstanceState: Bundle?) {
|
||||
super.onPostCreate(savedInstanceState)
|
||||
delegate.onPostCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
val supportActionBar: ActionBar?
|
||||
get() = delegate.supportActionBar
|
||||
|
||||
fun setSupportActionBar(toolbar: Toolbar?) {
|
||||
delegate.setSupportActionBar(toolbar)
|
||||
}
|
||||
|
||||
override fun getMenuInflater(): MenuInflater {
|
||||
return delegate.menuInflater
|
||||
}
|
||||
|
||||
override fun setContentView(@LayoutRes layoutResID: Int) {
|
||||
delegate.setContentView(layoutResID)
|
||||
}
|
||||
|
||||
override fun setContentView(view: View) {
|
||||
delegate.setContentView(view)
|
||||
}
|
||||
|
||||
override fun setContentView(view: View, params: ViewGroup.LayoutParams) {
|
||||
delegate.setContentView(view, params)
|
||||
}
|
||||
|
||||
override fun addContentView(view: View, params: ViewGroup.LayoutParams) {
|
||||
delegate.addContentView(view, params)
|
||||
}
|
||||
|
||||
override fun onPostResume() {
|
||||
super.onPostResume()
|
||||
delegate.onPostResume()
|
||||
}
|
||||
|
||||
override fun onTitleChanged(title: CharSequence, color: Int) {
|
||||
super.onTitleChanged(title, color)
|
||||
delegate.setTitle(title)
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
delegate.onConfigurationChanged(newConfig)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
delegate.onStop()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
delegate.onDestroy()
|
||||
}
|
||||
|
||||
override fun invalidateOptionsMenu() {
|
||||
delegate.invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
private val delegate: AppCompatDelegate by lazy {
|
||||
AppCompatDelegate.create(this, null)
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package com.example.mear.activities
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.Environment
|
||||
import android.os.IBinder
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.widget.Toast
|
||||
import com.example.mear.R
|
||||
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
import com.example.mear.playback.service.MusicService
|
||||
|
||||
open class BaseServiceActivity: AppCompatActivity() {
|
||||
protected var musicService: MusicService? = null
|
||||
|
||||
|
||||
protected open fun resetControls() {
|
||||
val d = "l"
|
||||
}
|
||||
protected open fun initializeChangeListeners() {
|
||||
val d = "l"
|
||||
}
|
||||
protected open fun updateTrackProgress() {
|
||||
val d = "l"
|
||||
}
|
||||
protected open fun configureTrackDisplay() {
|
||||
val d = "l"
|
||||
}
|
||||
|
||||
|
||||
protected fun appDirectory(): String {
|
||||
return Environment.getDataDirectory().toString() + "/data/" +
|
||||
resources.getString(R.string.app_relative_path)
|
||||
}
|
||||
|
||||
|
||||
protected fun isServiceRunning(serviceClass: Class<*>): Boolean {
|
||||
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||
|
||||
for (service in activityManager.getRunningServices(Integer.MAX_VALUE)) {
|
||||
if (serviceClass.name == service.service.className) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
protected val mConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||
resetControls()
|
||||
|
||||
runBlocking {
|
||||
val demo = launch {
|
||||
musicService = (service as MusicService.LocalBinder).service
|
||||
initializeChangeListeners()
|
||||
updateTrackProgress()
|
||||
}
|
||||
demo.start()
|
||||
}
|
||||
if (musicService != null) {
|
||||
if (musicService!!.isPlaying()) {
|
||||
configureTrackDisplay()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(className: ComponentName) {
|
||||
resetControls()
|
||||
Toast.makeText(
|
||||
this@BaseServiceActivity, "Music Service Stopped",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
protected fun doBindService() {
|
||||
val intent = Intent(this, MusicService::class.java)
|
||||
if (isServiceRunning(MusicService::class.java)) {
|
||||
val suc = "Service is already running"
|
||||
}
|
||||
else {
|
||||
intent.putExtra("appPath", appDirectory())
|
||||
startService(intent)
|
||||
}
|
||||
|
||||
val result = bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
package com.example.mear.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.appcompat.widget.SearchView
|
||||
|
||||
import kotlinx.android.synthetic.main.content_song_view.*
|
||||
|
||||
import com.example.mear.adapters.SongAdapter
|
||||
import com.example.mear.models.APIInfo
|
||||
import com.example.mear.models.Song
|
||||
import com.example.mear.models.Token
|
||||
import com.example.mear.R
|
||||
import com.example.mear.repositories.*
|
||||
|
||||
|
||||
class IcarusSongActivity : BaseServiceActivity() {
|
||||
|
||||
private lateinit var adapter: SongAdapter
|
||||
|
||||
private lateinit var linearLayoutManager: LinearLayoutManager
|
||||
|
||||
private var songs: ArrayList<Song>? = null
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
try {
|
||||
setContentView(R.layout.activity_icarus_song)
|
||||
//setSupportActionBar(toolbar)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
window.statusBarColor = resources.getColor(R.color.track_seek)
|
||||
doBindService()
|
||||
initializeAdapter()
|
||||
initializeSongSearchListener()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val msg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun playSong(song: Song, token: Token, apiInfo: APIInfo) {
|
||||
musicService!!.icarusPlaySong(token, song, apiInfo)
|
||||
}
|
||||
|
||||
|
||||
private fun initializeAdapter() {
|
||||
try {
|
||||
linearLayoutManager =
|
||||
LinearLayoutManager(this)
|
||||
trackList.layoutManager = linearLayoutManager
|
||||
|
||||
val pa = appDirectory()
|
||||
val trackRepo = TrackRepository()
|
||||
val tokenRepo = TokenRepository()
|
||||
val apiRepo = APIRepository()
|
||||
val token = tokenRepo.retrieveToken(pa)
|
||||
val apiInfo = apiRepo.retrieveRecord(pa)
|
||||
val fetchedSongs = trackRepo.fetchSongsIncludingDownloaded(token, apiInfo.uri, pa)
|
||||
.toCollection(ArrayList())
|
||||
songs = fetchedSongs
|
||||
|
||||
songs!!.sortedWith(compareBy{it.title})
|
||||
|
||||
adapter = SongAdapter({songItems: Song -> playSong(songItems, token, apiInfo)}, songs!!)
|
||||
|
||||
trackList.adapter = adapter
|
||||
trackList.setHasFixedSize(true)
|
||||
trackList.setItemViewCacheSize(20)
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val msg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
private fun initializeSongSearchListener() {
|
||||
songSearch.setOnQueryTextListener(object: SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(p0: String?): Boolean {
|
||||
try {
|
||||
adapter.filter.filter(p0)
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val msg = ex.message
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onQueryTextChange(p0: String?): Boolean {
|
||||
try {
|
||||
adapter.filter.filter(p0)
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val msg = ex.message
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package com.example.mear.activities
|
||||
|
||||
import kotlinx.android.synthetic.main.activity_login.*
|
||||
import kotlinx.android.synthetic.main.content_login.*
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import org.jetbrains.anko.toast
|
||||
|
||||
import com.example.mear.models.*
|
||||
import com.example.mear.R
|
||||
import com.example.mear.repositories.*
|
||||
|
||||
class LoginActivity : BaseServiceActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
window.statusBarColor = resources.getColor(R.color.track_seek)
|
||||
setContentView(R.layout.activity_login)
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
loadElements()
|
||||
|
||||
login.setOnClickListener {
|
||||
loginButton()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun loginButton() {
|
||||
if (!validFields()) {
|
||||
toast("Fields are invalid").show()
|
||||
return
|
||||
}
|
||||
|
||||
val saveCred = saveUserCred.isChecked
|
||||
val apiInfo = APIInfo(apiUri.text.toString(), 1)
|
||||
val usr = User(username.text.toString(), password.text.toString())
|
||||
|
||||
val usrRepo = UserRepository()
|
||||
val tokenRepo = TokenRepository()
|
||||
val myToken = usrRepo.fetchToken(usr, apiInfo.uri)
|
||||
if (myToken.accessToken == "failure") {
|
||||
Toast.makeText(this, "login failed, try again", Toast.LENGTH_SHORT).show()
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
val pa = appDirectory()
|
||||
|
||||
if (saveCred && usrRepo.isTableEmpty(pa)) {
|
||||
val api = APIRepository()
|
||||
if (api.isTableEmpty(pa)) {
|
||||
api.saveRecord(apiInfo, pa)
|
||||
}
|
||||
usrRepo.saveCredentials(usr, pa)
|
||||
}
|
||||
tokenRepo.saveToken(myToken, pa)
|
||||
startActivity(Intent(this, MainActivity::class.java))
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val msg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadElements() {
|
||||
val pa = appDirectory()
|
||||
val usrRepo = UserRepository()
|
||||
val apiRepo = APIRepository()
|
||||
if (!usrRepo.databaseExist(pa)) {
|
||||
return
|
||||
}
|
||||
if (!usrRepo.isTableEmpty(pa)) {
|
||||
val usr = usrRepo.retrieveCredentials(pa)
|
||||
username.setText(usr.username)
|
||||
password.setText(usr.password)
|
||||
}
|
||||
if (!apiRepo.isTableEmpty(pa)) {
|
||||
val api = apiRepo.retrieveRecord(pa)
|
||||
apiUri.setText(api.uri)
|
||||
}
|
||||
|
||||
doBindService()
|
||||
}
|
||||
|
||||
|
||||
private fun validFields(): Boolean {
|
||||
if (username.text.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
if (password.text.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
if (password.text.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,443 +0,0 @@
|
||||
package com.example.mear.activities
|
||||
|
||||
import java.lang.Exception
|
||||
import java.lang.Runnable
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.io.*
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.fragment_play_controls.*
|
||||
import kotlinx.android.synthetic.main.fragment_track_cover.*
|
||||
import kotlinx.android.synthetic.main.fragment_track_details.*
|
||||
import kotlinx.android.synthetic.main.fragment_track_elapsing.*
|
||||
import kotlinx.android.synthetic.main.fragment_track_flow.*
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.work.Data
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import org.jetbrains.anko.image
|
||||
import org.jetbrains.anko.imageBitmap
|
||||
|
||||
import com.example.mear.listeners.TrackElaspingChange
|
||||
import com.example.mear.R
|
||||
import com.example.mear.repositories.*
|
||||
import com.example.mear.repositories.RepeatRepository.RepeatTypes
|
||||
import com.example.mear.repositories.ShuffleRepository.ShuffleTypes
|
||||
import com.example.mear.util.ConvertByteArray
|
||||
import com.example.mear.workers.IcarusSyncManager
|
||||
|
||||
|
||||
class MainActivity : BaseServiceActivity() {
|
||||
|
||||
private var musicHandler: Handler? = Handler()
|
||||
private var playCountUpdated: Boolean? = false
|
||||
private var serviceBinded: Boolean? = false
|
||||
private var repeatOn: Boolean? = false
|
||||
private var shuffleOn: Boolean? = false
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
try {
|
||||
setContentView(R.layout.activity_main)
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
initialize()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val msg = ex.message
|
||||
}
|
||||
}
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
try {
|
||||
if (serviceBinded == null || serviceBinded!! == false) {
|
||||
unbindService(mConnection)
|
||||
serviceBinded = true
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
try {
|
||||
if (serviceBinded!!.equals(null) || serviceBinded!! == false ) {
|
||||
unbindService(mConnection)
|
||||
serviceBinded = true
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun initialize() {
|
||||
TrackElapsing.progress = 0
|
||||
TrackElapsing.max = 100
|
||||
|
||||
try {
|
||||
window.statusBarColor = resources.getColor(R.color.track_seek)
|
||||
initializeShuffle()
|
||||
initializeRepeat()
|
||||
initializeServices()
|
||||
initializeClickListeners()
|
||||
configurePlayControlsDisplay()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
override fun initializeChangeListeners() {
|
||||
val newListener = TrackElaspingChange(TrackElapsing)
|
||||
if (musicService != null) {
|
||||
newListener.musicService = musicService
|
||||
newListener.initialize()
|
||||
TrackElapsing.setOnSeekBarChangeListener(newListener)
|
||||
}
|
||||
}
|
||||
private fun initializeClickListeners() {
|
||||
PlayTrack.setOnClickListener {
|
||||
playSongTrack()
|
||||
}
|
||||
NextTrack.setOnClickListener {
|
||||
playNextSongTrack()
|
||||
}
|
||||
PreviousTrack.setOnClickListener {
|
||||
playPreviousSongTrack()
|
||||
}
|
||||
ShuffleTracks.setOnClickListener {
|
||||
toggleShuffle()
|
||||
}
|
||||
RepeatTrack.setOnClickListener {
|
||||
toggleRepeat()
|
||||
}
|
||||
val clickListener = View.OnClickListener { view ->
|
||||
when (view.id) {
|
||||
R.id.SettingsLink-> {
|
||||
showPopup(view)
|
||||
}
|
||||
}
|
||||
}
|
||||
SettingsLink.setOnClickListener (clickListener )
|
||||
}
|
||||
private fun initializeServices() {
|
||||
doBindService()
|
||||
}
|
||||
private fun initializeShuffle() {
|
||||
val shuffleRepo = ShuffleRepository(null)
|
||||
val shuffleMode = shuffleRepo.shuffleMode(appDirectory())
|
||||
when (shuffleMode) {
|
||||
ShuffleTypes.ShuffleOff -> {
|
||||
ShuffleTracks.setText(R.string.shuffle_off)
|
||||
}
|
||||
ShuffleTypes.ShuffleOn -> {
|
||||
ShuffleTracks.setText(R.string.shuffle_on)
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun initializeRepeat() {
|
||||
val repeatRepo = RepeatRepository(null)
|
||||
val repeatMode = repeatRepo.repeatMode(appDirectory())
|
||||
when (repeatMode) {
|
||||
RepeatTypes.RepeatSong -> {
|
||||
RepeatTrack.text = resources.getText(R.string.repeat_on)
|
||||
}
|
||||
RepeatTypes.RepeatOff -> {
|
||||
RepeatTrack.text = resources.getText(R.string.repeat_off)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleShuffle() {
|
||||
val shuffleRepo = ShuffleRepository(null)
|
||||
shuffleRepo.alterShuffleMode(appDirectory())
|
||||
val shuffleMode = shuffleRepo.shuffleMode(appDirectory())
|
||||
|
||||
when (shuffleMode) {
|
||||
ShuffleTypes.ShuffleOff -> {
|
||||
shuffleOn = false
|
||||
ShuffleTracks.text = getString(R.string.shuffle_off)
|
||||
}
|
||||
ShuffleTypes.ShuffleOn -> {
|
||||
shuffleOn = true
|
||||
ShuffleTracks.text = getString(R.string.shuffle_on)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleRepeat() {
|
||||
val repeatRepo = RepeatRepository(null)
|
||||
|
||||
val appPath = appDirectory()
|
||||
repeatRepo.alterRepeatMode(appPath)
|
||||
|
||||
when (repeatRepo.repeatMode(appPath)) {
|
||||
RepeatTypes.RepeatOff -> {
|
||||
repeatOn = false
|
||||
RepeatTrack.text = resources.getText(R.string.repeat_off)
|
||||
}
|
||||
RepeatTypes.RepeatSong -> {
|
||||
repeatOn = true
|
||||
RepeatTrack.text = resources.getText(R.string.repeat_on)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun playSongTrack() {
|
||||
PlayTrack.isEnabled = false
|
||||
try {
|
||||
if (!musicService!!.isPlaying()) {
|
||||
musicService!!.playSongTrack()
|
||||
} else {
|
||||
musicService!!.pauseSongTrack()
|
||||
}
|
||||
configureTrackDisplay()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
PlayTrack.isEnabled = true
|
||||
}
|
||||
private fun playNextSongTrack() {
|
||||
NextTrack.isEnabled = false
|
||||
try {
|
||||
musicService!!.playNextTrack()
|
||||
|
||||
configureTrackDisplay()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
print(exMsg)
|
||||
}
|
||||
NextTrack.isEnabled = true
|
||||
playCountUpdated = false
|
||||
}
|
||||
private fun playPreviousSongTrack() {
|
||||
PreviousTrack.isEnabled = false
|
||||
try {
|
||||
musicService!!.playPreviousTrack()
|
||||
|
||||
configureTrackDisplay()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
print(exMsg)
|
||||
}
|
||||
PreviousTrack.isEnabled = true
|
||||
playCountUpdated = false
|
||||
}
|
||||
|
||||
|
||||
override fun configureTrackDisplay() {
|
||||
try {
|
||||
runOnUiThread {
|
||||
playCountUpdated = false
|
||||
configurePlayControlsDisplay()
|
||||
val currSong= musicService!!.getCurrentSong()
|
||||
val dur = String.format(
|
||||
"%02d:%02d", TimeUnit.SECONDS.toMinutes(currSong.duration.toLong()),
|
||||
(currSong.duration % 60)
|
||||
)
|
||||
|
||||
val coverArtRepo = CoverArtRepository()
|
||||
val apiRepo = APIRepository()
|
||||
val tokenRepo = TokenRepository()
|
||||
val path = appDirectory()
|
||||
val apiUri = apiRepo.retrieveRecord(path)
|
||||
val myToken = tokenRepo.retrieveToken(path)
|
||||
val coverArt = CoverArtRepository.CoverArt(currSong.coverArtId, currSong.title)
|
||||
val imgData = coverArtRepo.fetchCoverArtImage(myToken, coverArt, apiUri.uri)
|
||||
val ImageConvByte = ConvertByteArray(imgData)
|
||||
val convertedImage = ImageConvByte.convertToBmp(imgData)
|
||||
|
||||
|
||||
resetControls()
|
||||
|
||||
TrackTitle.text = currSong.title
|
||||
ArtistTitle.text = currSong.artist
|
||||
AlbumTitle.text = currSong.album
|
||||
TrackDuration.text = dur
|
||||
TrackCover.imageBitmap = convertedImage
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val msg = ex.message
|
||||
}
|
||||
}
|
||||
override fun resetControls() {
|
||||
TrackTitle!!.text = null
|
||||
ArtistTitle!!.text = null
|
||||
AlbumTitle!!.text = null
|
||||
CurrentPosition!!.text = null
|
||||
TrackCover!!.imageBitmap = null
|
||||
}
|
||||
override fun updateTrackProgress() {
|
||||
musicHandler!!.postDelayed(musicTrackTimeUpdateTask, 100)
|
||||
}
|
||||
private fun configurePlayControlsDisplay() {
|
||||
PlayTrack.background = null
|
||||
PlayTrack.colorFilter = null
|
||||
|
||||
if ((musicService == null || !musicService!!.isPlaying())) {
|
||||
PlayTrack.setImageResource(android.R.drawable.ic_media_play)
|
||||
PlayTrack.setColorFilter(Color.GREEN)
|
||||
}
|
||||
else {
|
||||
PlayTrack.setImageResource(android.R.drawable.ic_media_pause)
|
||||
PlayTrack.setColorFilter(Color.RED)
|
||||
}
|
||||
}
|
||||
|
||||
private fun songMetadataLoaded(): Boolean {
|
||||
if (TrackTitle.text.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
if (ArtistTitle.text.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
if (AlbumTitle.text.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
if (TrackCover.image == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
val currSong = musicService!!.getCurrentSong()
|
||||
|
||||
if (!TrackTitle.text.equals(currSong.title)) {
|
||||
return false
|
||||
}
|
||||
if ((ArtistTitle.text != currSong.artist)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
private fun showPopup(view: View) {
|
||||
try {
|
||||
var popup = PopupMenu(this, view)
|
||||
if (musicService!!.getCurrentSong().downloaded) {
|
||||
popup.inflate(R.menu.popup_menu_song_downloaded)
|
||||
}
|
||||
else {
|
||||
popup.inflate(R.menu.popup_menu)
|
||||
}
|
||||
|
||||
popup.setOnMenuItemClickListener{ item: MenuItem? ->
|
||||
when (item!!.itemId) {
|
||||
R.id.action_settings-> {
|
||||
startActivity(Intent(this, SettingsActivity::class.java))
|
||||
}
|
||||
R.id.action_song_view -> {
|
||||
startActivity(Intent(this, IcarusSongActivity::class.java))
|
||||
}
|
||||
R.id.action_song_delete -> {
|
||||
val appPath = appDirectory()
|
||||
val trackRepo = TrackRepository()
|
||||
|
||||
var currSong = musicService!!.getCurrentSong()
|
||||
Toast.makeText(this, "Deleting song", Toast.LENGTH_SHORT).show()
|
||||
val result = trackRepo.delete(currSong, appPath)
|
||||
if (result) {
|
||||
musicService!!.removeSongDownloadStatus(currSong)
|
||||
}
|
||||
}
|
||||
R.id.action_song_download -> {
|
||||
val appPath = appDirectory()
|
||||
var song = musicService!!.getCurrentSong()
|
||||
|
||||
Toast.makeText(this, "Downloading song", Toast.LENGTH_SHORT).show()
|
||||
|
||||
val constraints = androidx.work.Constraints.Builder()
|
||||
.setRequiredNetworkType(NetworkType.CONNECTED).build()
|
||||
|
||||
val data = Data.Builder()
|
||||
data.putString("appPath", appPath)
|
||||
|
||||
data.putInt("songId", song.id)
|
||||
data.putString("songTitle", song.title)
|
||||
data.putString("songArtist", song.artist)
|
||||
data.putString("songAlbum", song.album)
|
||||
data.putString("songAlbumArtist", song.albumArtist)
|
||||
data.putString("songGenre", song.genre)
|
||||
data.putInt("songYear", song.year)
|
||||
data.putInt("songDuration", song.duration)
|
||||
data.putInt("songCoverArtId", song.coverArtId)
|
||||
data.putBoolean("songDownloaded", false)
|
||||
data.putInt("songDisc", song.disc)
|
||||
data.putInt("songTrack", song.track)
|
||||
|
||||
val task = OneTimeWorkRequest.Builder(IcarusSyncManager::class.java)
|
||||
.setInputData(data.build())
|
||||
.setConstraints(constraints)
|
||||
.build()
|
||||
WorkManager.getInstance().enqueue(task)
|
||||
|
||||
WorkManager.getInstance(this).getWorkInfoByIdLiveData(task.id)
|
||||
.observe(this, Observer { info ->
|
||||
if (info != null && info.state.isFinished) {
|
||||
song.path = info.outputData.getString("songPath")!!
|
||||
song.filename = info.outputData.getString("songFilename")!!
|
||||
song.downloaded = info.outputData.getBoolean("songDownloaded", true)!!
|
||||
musicService!!.changeSongDownloadStatus(song)
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
R.id.action_song_play_count-> {
|
||||
// TODO: not implemented
|
||||
val trk = musicService!!.getCurrentSong()
|
||||
Toast.makeText(this, "Song played $playCount times", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
*/
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
popup.show()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
private var musicTrackTimeUpdateTask = object: Runnable {
|
||||
override fun run() {
|
||||
try {
|
||||
if (!songMetadataLoaded()) {
|
||||
configureTrackDisplay()
|
||||
}
|
||||
val currentPosition = musicService!!.currentPositionOfTrack() / 1000
|
||||
val dur = String.format( "%02d:%02d", TimeUnit.SECONDS.toMinutes(currentPosition.toLong()),
|
||||
(currentPosition % 60) )
|
||||
|
||||
CurrentPosition.text = dur
|
||||
|
||||
musicHandler!!.postDelayed(this, 100)
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package com.example.mear.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
|
||||
import java.lang.Exception
|
||||
import kotlinx.android.synthetic.main.activity_settings.*
|
||||
import kotlinx.android.synthetic.main.content_settings.*
|
||||
|
||||
import com.example.mear.R
|
||||
import com.example.mear.ui.popups.AboutPopup
|
||||
import kotlinx.android.synthetic.main.popup_layout.*
|
||||
|
||||
|
||||
class SettingsActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_settings)
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
var aListener = AboutListener(aboutApp, this)
|
||||
About.setOnClickListener(aListener)
|
||||
|
||||
/**
|
||||
About.setOnClickListener {
|
||||
val i =0
|
||||
var j = i.plus(500)
|
||||
}
|
||||
*/
|
||||
|
||||
initialize()
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
|
||||
private fun initialize() {
|
||||
window.statusBarColor = resources.getColor(R.color.track_seek)
|
||||
}
|
||||
|
||||
|
||||
class AboutListener(var layout: LinearLayout?, val ctx: Context): View.OnClickListener {
|
||||
override fun onClick(v: View?) {
|
||||
val ss = 10
|
||||
var ob = ss.plus(500)
|
||||
try {
|
||||
val popup = AboutPopup(ctx)
|
||||
popup?.showPopupFromScreenCenter(R.layout.activity_settings)
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
Toast.makeText(ctx, "About Setting pressed", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
package com.example.mear.adapters
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Filter
|
||||
import android.widget.Filterable
|
||||
|
||||
import java.lang.Exception
|
||||
import kotlinx.android.synthetic.main.fragment_song_view.view.*
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
|
||||
import com.squareup.picasso.Picasso
|
||||
|
||||
import com.example.mear.constants.Filenames
|
||||
import com.example.mear.inflate
|
||||
import com.example.mear.models.TrackItems
|
||||
import com.example.mear.R
|
||||
import com.example.mear.util.ConvertByteArray
|
||||
import com.example.mear.util.ExtractCover
|
||||
import org.jetbrains.anko.imageBitmap
|
||||
|
||||
|
||||
class RecyclerAdapter(val mOnClickListenerI: (TrackItems) -> Unit,
|
||||
var trackItemsSourceInit: ArrayList<TrackItems>):
|
||||
RecyclerView.Adapter<RecyclerAdapter.TrackItemsHolder>(), Filterable {
|
||||
|
||||
var allTrackItems = trackItemsSourceInit
|
||||
val adp = this
|
||||
|
||||
override fun onBindViewHolder(holder: TrackItemsHolder, position: Int) {
|
||||
val itemPhoto = trackItemsSourceInit!![position]
|
||||
holder.bindTrackItems(itemPhoto, mOnClickListenerI)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, position: Int): TrackItemsHolder {
|
||||
val inflatedView = parent.inflate(R.layout.fragment_song_view, false)
|
||||
return TrackItemsHolder(inflatedView)
|
||||
}
|
||||
|
||||
override fun getFilter(): Filter {
|
||||
return object: Filter() {
|
||||
override fun performFiltering(constraint: CharSequence?): FilterResults {
|
||||
val fr = FilterResults()
|
||||
|
||||
val sortedList = mutableListOf<TrackItems>()
|
||||
|
||||
for (trackItm in allTrackItems) {
|
||||
if (trackItm.artistTitle.contains(constraint!!, true) ||
|
||||
trackItm.trackTitle.contains(constraint!!, true)) {
|
||||
sortedList.add(trackItm)
|
||||
}
|
||||
}
|
||||
|
||||
fr.count = sortedList.size
|
||||
fr.values = sortedList
|
||||
|
||||
return fr
|
||||
}
|
||||
|
||||
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
|
||||
try {
|
||||
val itms = results!!.values as ArrayList<TrackItems>
|
||||
|
||||
adp.trackItemsSourceInit = itms
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
|
||||
adp.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return trackItemsSourceInit!!.size
|
||||
}
|
||||
|
||||
|
||||
fun configureActivity(actvity: Activity) {
|
||||
}
|
||||
|
||||
class TrackItemsHolder(v: View) : RecyclerView.ViewHolder(v) {
|
||||
|
||||
private var view: View = v
|
||||
private var trackItem: TrackItems? = null
|
||||
private val imgWidth = 40
|
||||
private val imgHeight = 40
|
||||
private var mBound = false
|
||||
|
||||
fun bindTrackItems(trackItems: TrackItems, clickList: (TrackItems) -> Unit) {
|
||||
try {
|
||||
var context = view.context
|
||||
|
||||
this.trackItem = trackItems
|
||||
|
||||
view.trackTitle.text = trackItem!!.trackTitle
|
||||
view.trackArtist.text = trackItem!!.artistTitle
|
||||
|
||||
val id = trackItems.id
|
||||
|
||||
var trackCoverPath = "${context.filesDir}/${Filenames.TRACK_COVERS}"
|
||||
trackCoverPath = "${trackCoverPath}${id}.bmp"
|
||||
|
||||
|
||||
//val extractArt = ExtractCover(null)
|
||||
//val coverArt = extractArt.retrieveCover(trackItem!!.trackPath)
|
||||
|
||||
//val convertByte = ConvertByteArray(coverArt)
|
||||
//var coverArtBmp = convertByte.convertToBmptScales(imgWidth, imgHeight)
|
||||
|
||||
//view.trackCover.imageBitmap = coverArtBmp
|
||||
// TODO: Implement usage of Picasso
|
||||
//Picasso.get().load(trackCoverPath).into(view.trackCover)
|
||||
|
||||
view.setOnClickListener { clickList(trackItem!!) }
|
||||
}
|
||||
catch (ex:Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.example.mear.adapters
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
import com.example.mear.holders.SettingItemsHolder
|
||||
import com.example.mear.models.SettingItems
|
||||
|
||||
class SettingsAdapter(val settingItems: ArrayList<SettingItems>) : RecyclerView.Adapter<SettingItemsHolder>() {
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
TODO("not implemented")
|
||||
}
|
||||
override fun onBindViewHolder(holder: SettingItemsHolder, position: Int) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
override fun onCreateViewHolder(parent: ViewGroup, position: Int): SettingItemsHolder {
|
||||
TODO("not implemented")
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package com.example.mear.adapters
|
||||
|
||||
import java.lang.Exception
|
||||
import kotlinx.android.synthetic.main.fragment_song_view.view.*
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Filter
|
||||
import android.widget.Filterable
|
||||
|
||||
import com.example.mear.inflate
|
||||
import com.example.mear.models.Song
|
||||
import com.example.mear.R
|
||||
|
||||
|
||||
class SongAdapter(val mOnClickListener: (Song) -> Unit,
|
||||
var songItemSource: ArrayList<Song>) :
|
||||
RecyclerView.Adapter<SongAdapter.SongItemHolder>(), Filterable {
|
||||
|
||||
var allIcarusSongs = songItemSource
|
||||
val adp = this
|
||||
|
||||
|
||||
override fun onBindViewHolder(p0: SongItemHolder, p1: Int) {
|
||||
val ph = songItemSource!![p1]
|
||||
p0.bindSongItems(ph, mOnClickListener)
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): SongItemHolder {
|
||||
val inflatedView = p0.inflate(R.layout.fragment_song_view, false)
|
||||
return SongItemHolder(inflatedView)
|
||||
}
|
||||
|
||||
|
||||
override fun getFilter(): Filter {
|
||||
return object: Filter() {
|
||||
override fun performFiltering(constraint: CharSequence?): FilterResults {
|
||||
val fr = FilterResults()
|
||||
val sortedList = mutableListOf<Song>()
|
||||
|
||||
for (song in allIcarusSongs) {
|
||||
if (song.artist.contains(constraint!!, true) ||
|
||||
song.title.contains(constraint!!, true)) {
|
||||
sortedList.add(song)
|
||||
}
|
||||
}
|
||||
|
||||
fr.count = sortedList.size
|
||||
fr.values = sortedList
|
||||
|
||||
return fr
|
||||
}
|
||||
|
||||
|
||||
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
|
||||
try {
|
||||
val items = results!!.values as ArrayList<Song>
|
||||
adp.songItemSource = items
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val msg = ex.message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return songItemSource!!.size
|
||||
}
|
||||
|
||||
|
||||
class SongItemHolder(var v: View): RecyclerView.ViewHolder(v) {
|
||||
private var songItem: Song? = null
|
||||
|
||||
|
||||
fun bindSongItems(songItems: Song, clickList: (Song) -> Unit) {
|
||||
try {
|
||||
val context = v.context
|
||||
this.songItem = songItems
|
||||
|
||||
v.trackTitle.setText(songItems.title)
|
||||
v.trackArtist.setText(songItems.albumArtist)
|
||||
|
||||
v.setOnClickListener { clickList(songItem!!)}
|
||||
if (songItems.downloaded) {
|
||||
v.setBackgroundColor(v.resources.getColor(R.color.track_seek))
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val msg = ex.message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.example.mear.constants
|
||||
|
||||
import android.os.Bundle
|
||||
import android.content.res.Resources
|
||||
import android.os.Environment
|
||||
import com.example.mear.R
|
||||
|
||||
import kotlinx.android.synthetic.main.activity_login.*
|
||||
import kotlinx.android.synthetic.main.content_login.*
|
||||
|
||||
object AppDataPath {
|
||||
val APP_DATA_PATH: String = Environment.getDataDirectory().toString()
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.example.mear.constants
|
||||
|
||||
object CPPLib {
|
||||
const val NATIVE_LIB = "native-lib"
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.example.mear.constants
|
||||
|
||||
object ControlTypes {
|
||||
const val SHUFFLE_ON = "Shuffle On"
|
||||
const val SHUFFLE_OFF = "Shuffle Off"
|
||||
const val REPEAT_ON = "Repeat On"
|
||||
const val REPEAT_OFF = "Repeat Off"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.example.mear.constants
|
||||
|
||||
object DirectoryIgnore {
|
||||
const val Android_Root = "Android/"
|
||||
const val Notifications = "Notifications/"
|
||||
const val Ringtones = "Ringtones/"
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.example.mear.constants
|
||||
|
||||
object FileTypes {
|
||||
const val Mp3 = "mp3"
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.example.mear.constants
|
||||
|
||||
object Filenames {
|
||||
const val TRACK_COVERS = "TrackCover_"
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.example.mear.constants
|
||||
|
||||
object Interval {
|
||||
const val SONG_REWIND = 4
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.example.mear.constants
|
||||
|
||||
object SongSearch {
|
||||
const val INITIAL_SEARCH_AMOUNT = 1
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.example.mear
|
||||
|
||||
import androidx.annotation.LayoutRes
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
|
||||
fun ViewGroup.inflate(@LayoutRes layoutRes: Int, attachToRoot: Boolean = false): View {
|
||||
return LayoutInflater.from(context).inflate(layoutRes, this, attachToRoot)
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.example.mear.holders
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.View
|
||||
|
||||
import com.example.mear.models.SettingItems
|
||||
|
||||
class SettingItemsHolder(view: View): RecyclerView.ViewHolder(view){
|
||||
|
||||
private var view: View = view
|
||||
|
||||
fun bindSettingItem(settingItem: SettingItems, clickable: (SettingItems) -> Unit) {
|
||||
try {
|
||||
// TODO: Implement the binding of setting items
|
||||
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.example.mear.listeners
|
||||
|
||||
import android.os.Handler
|
||||
import android.widget.SeekBar
|
||||
|
||||
import java.lang.Exception
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
import com.example.mear.playback.service.MusicService
|
||||
import com.example.mear.util.ConvertTrackPosition
|
||||
|
||||
|
||||
class TrackElaspingChange(var seekBar: SeekBar?): SeekBar.OnSeekBarChangeListener {
|
||||
|
||||
var musicService: MusicService? = null
|
||||
var mHandler: Handler? = Handler()
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar?) {
|
||||
this.seekBar = seekBar
|
||||
}
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar?) {
|
||||
this.seekBar = seekBar
|
||||
val newPositionPercentage = this.seekBar!!.progress
|
||||
var convertPosition = ConvertTrackPosition(newPositionPercentage)
|
||||
val newPosition = convertPosition.newPosition(musicService!!.durationOfTrack())
|
||||
musicService!!.goToPosition(newPosition)
|
||||
this.seekBar!!.progress = newPosition
|
||||
}
|
||||
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
||||
this.seekBar = seekBar
|
||||
|
||||
if (fromUser ){
|
||||
|
||||
mHandler!!.postDelayed( musicTrackTimeUpdateTask, 250)
|
||||
}
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
mHandler!!.postDelayed(musicTrackTimeUpdateTask, 250)
|
||||
}
|
||||
|
||||
private var musicTrackTimeUpdateTask = object: Runnable {
|
||||
override fun run() {
|
||||
try {
|
||||
var newPosition = 0
|
||||
val currentPosition = musicService!!.currentPositionOfTrack() / 1000
|
||||
val totalDuration = musicService!!.durationOfTrack() / 1000
|
||||
newPosition = (((currentPosition).toDouble() / totalDuration) * 100).toInt()
|
||||
val dur = String.format(
|
||||
"%02d:%02d", TimeUnit.SECONDS.toMinutes(currentPosition.toLong()),
|
||||
(currentPosition % 60)
|
||||
)
|
||||
|
||||
seekBar!!.progress = newPosition
|
||||
|
||||
mHandler!!.postDelayed(this, 250)
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.example.mear.models
|
||||
|
||||
class APIInfo(var uri: String = "", var version: Int = 1,
|
||||
var endpoint: String = "")
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.example.mear.models
|
||||
|
||||
data class PlayControls(val shuffleOn: Boolean?, val repeatOn: Boolean?) {
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.example.mear.models
|
||||
|
||||
data class PlayCount(val id: Int, val playCount: Int, val trackId: Int) {
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.example.mear.models
|
||||
|
||||
data class SettingItems(val id: Int, val settingTitle: String, val settingDescription: String) {
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.example.mear.models
|
||||
|
||||
data class Settings(val id: Int, val darkTheme: Boolean) {
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.example.mear.models
|
||||
|
||||
class Song (var id: Int = 3, var title: String = "", var album: String = "",
|
||||
var albumArtist: String = "", var artist: String = "",
|
||||
var genre: String = "", var year: Int = 0, var duration: Int = 0,
|
||||
var track: Int = 0, var disc: Int = 0,
|
||||
var coverArtId: Int = 0, var downloaded: Boolean = false, var path: String = "",
|
||||
var filename: String = "")
|
||||
@@ -1,3 +0,0 @@
|
||||
package com.example.mear.models
|
||||
|
||||
class Token (var accessToken: String = "")
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.example.mear.models
|
||||
|
||||
data class Track (val id: Int = Int.MAX_VALUE, val title: String = "UNTITLED", val artist: String = "UNTITLED",
|
||||
val album: String = "UNTITLED", val length: Int = Int.MAX_VALUE,
|
||||
val TrackCover: ByteArray = ByteArray(0), val songPath: String = "UNTITLED") {
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.example.mear.models
|
||||
|
||||
data class TrackItems(val id: Int, val trackTitle: String, val artistTitle: String, val trackPath: String,
|
||||
val trackCover: ByteArray) {
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
package com.example.mear.models
|
||||
|
||||
class User (var username: String = "", var password: String = "")
|
||||
@@ -1,312 +0,0 @@
|
||||
package com.example.mear.playback.service
|
||||
|
||||
import java.lang.Exception
|
||||
import kotlin.random.Random
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.media.MediaPlayer
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import android.widget.Toast
|
||||
|
||||
import com.example.mear.constants.Interval
|
||||
import com.example.mear.models.APIInfo
|
||||
import com.example.mear.models.Song
|
||||
import com.example.mear.models.Token
|
||||
import com.example.mear.repositories.*
|
||||
import com.example.mear.repositories.RepeatRepository.RepeatTypes
|
||||
import com.example.mear.repositories.ShuffleRepository.ShuffleTypes
|
||||
|
||||
|
||||
class MusicService(var appPath: String = ""): Service() {
|
||||
|
||||
private var trackPlayer: MediaPlayer? = null
|
||||
private var songQueue = mutableListOf<Song>()
|
||||
private var currentSong = Song()
|
||||
private var currentSongIndex: Int? = null
|
||||
private var shuffleOn: Boolean? = null
|
||||
private val mBinder = LocalBinder()
|
||||
private val seconds = Interval.SONG_REWIND
|
||||
|
||||
|
||||
inner class LocalBinder : Binder() {
|
||||
internal val service: MusicService
|
||||
get() = this@MusicService
|
||||
}
|
||||
|
||||
|
||||
private enum class PlayTypes {
|
||||
PlayNextSong, PlaySong, PlayPreviousSong
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate() {
|
||||
initializeMediaPlayer()
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
val b = intent.extras
|
||||
appPath = b!!.get("appPath") as String
|
||||
initializeMediaPlayer()
|
||||
return Service.START_STICKY
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
val intent = Intent(this, mBinder.javaClass)
|
||||
onUnbind(intent)
|
||||
|
||||
Toast.makeText(this, "Music Service Stopped", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return mBinder
|
||||
}
|
||||
|
||||
override fun onUnbind(intent: Intent?): Boolean {
|
||||
return super.onUnbind(intent)
|
||||
}
|
||||
|
||||
|
||||
fun downloadSong(token: Token, song: Song, appPath: String) {
|
||||
val trackRepo = TrackRepository()
|
||||
val s = trackRepo.download(token, currentSong, appPath)
|
||||
changeSongDownloadStatus(s)
|
||||
}
|
||||
fun icarusPlaySong(token: Token, song: Song, apiInfo: APIInfo) {
|
||||
if (song.downloaded) {
|
||||
offlinePlaySong(song)
|
||||
return
|
||||
}
|
||||
|
||||
val uri = APIRepository.retrieveSongStreamUri(apiInfo, song)
|
||||
val hddr = APIRepository.retrieveSongStreamHeader(token)
|
||||
currentSong = song
|
||||
currentSongIndex = songQueue.indexOfFirst { it.id == currentSong.id }
|
||||
|
||||
try {
|
||||
trackPlayer!!.reset()
|
||||
trackPlayer!!.setDataSource(this, uri, hddr)
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.start()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val msg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
fun changeSongDownloadStatus(song: Song) {
|
||||
if (!song.downloaded) {
|
||||
song.downloaded = true
|
||||
}
|
||||
currentSong = song
|
||||
currentSongIndex = songQueue.indexOfFirst { it.id == currentSong.id }
|
||||
songQueue[currentSongIndex!!] = currentSong
|
||||
|
||||
val curPosition = currentPositionOfTrack()
|
||||
trackPlayer!!.reset()
|
||||
trackPlayer!!.setDataSource(currentSong.path)
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.seekTo(curPosition)
|
||||
trackPlayer!!.start()
|
||||
}
|
||||
|
||||
fun removeSongDownloadStatus(song: Song) {
|
||||
if (song.downloaded) {
|
||||
song.downloaded = false
|
||||
}
|
||||
currentSong = song
|
||||
currentSongIndex = songQueue.indexOfFirst { it.id == currentSong.id }
|
||||
songQueue[currentSongIndex!!] = currentSong
|
||||
}
|
||||
|
||||
fun goToPosition(progress: Int) { trackPlayer!!.seekTo(progress) }
|
||||
|
||||
fun playSongTrack() {
|
||||
try {
|
||||
trackPlayer!!.start()
|
||||
}
|
||||
catch (ex: Exception ) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
fun pauseSongTrack() {
|
||||
try {
|
||||
trackPlayer!!.pause()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
fun playPreviousTrack() {
|
||||
try {
|
||||
val duration = trackPlayer!!.currentPosition / 1000
|
||||
shuffleOn = retrieveShuffleMode()
|
||||
val apiRepo = APIRepository()
|
||||
val repeatRepo = RepeatRepository(null)
|
||||
val tokenRepo = TokenRepository()
|
||||
|
||||
val repeatMode = repeatRepo.repeatMode(appPath)
|
||||
val token = tokenRepo.retrieveToken(appPath)
|
||||
val apiInfo = apiRepo.retrieveRecord(appPath)
|
||||
if (parseRepeatMode(repeatMode) || duration > seconds) {
|
||||
|
||||
trackPlayer!!.pause()
|
||||
trackPlayer!!.seekTo(0)
|
||||
trackPlayer!!.start()
|
||||
|
||||
}
|
||||
else {
|
||||
if (retrieveShuffleMode()!! && !parseRepeatMode(repeatMode)) {
|
||||
currentSongIndex = Random.nextInt(0, songQueue.size - 1)
|
||||
} else if (!parseRepeatMode(repeatMode)) {
|
||||
currentSongIndex = if (currentSongIndex == 0)
|
||||
songQueue.size - 1 else currentSongIndex!! - 1
|
||||
}
|
||||
|
||||
currentSong = songQueue[currentSongIndex!!]
|
||||
trackPlayer!!.reset()
|
||||
if (currentSong.downloaded) {
|
||||
trackPlayer!!.setDataSource(currentSong.path)
|
||||
}
|
||||
else {
|
||||
val uri = APIRepository.retrieveSongStreamUri(apiInfo, currentSong)
|
||||
val hddr = APIRepository.retrieveSongStreamHeader(token)
|
||||
trackPlayer!!.setDataSource(this,
|
||||
uri, hddr)
|
||||
}
|
||||
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.start()
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
fun playNextTrack() {
|
||||
try {
|
||||
trackPlayer!!.reset()
|
||||
shuffleOn = retrieveShuffleMode()
|
||||
val apiRepo = APIRepository()
|
||||
val repeatRepo = RepeatRepository(null)
|
||||
val tokenRepo = TokenRepository()
|
||||
|
||||
val token = tokenRepo.retrieveToken(appPath)
|
||||
val repeatMode = repeatRepo.repeatMode(appPath)
|
||||
val apiInfo = apiRepo.retrieveRecord(appPath)
|
||||
|
||||
if (retrieveShuffleMode()!! && !parseRepeatMode(repeatMode)) {
|
||||
currentSongIndex = Random.nextInt(0, songQueue.size - 1)
|
||||
} else if (!parseRepeatMode(repeatMode)) {
|
||||
currentSongIndex = if ((currentSongIndex!! + 1) == songQueue.size)
|
||||
0 else currentSongIndex!! + 1
|
||||
}
|
||||
|
||||
currentSong = songQueue[currentSongIndex!!]
|
||||
|
||||
if (currentSong.downloaded) {
|
||||
trackPlayer!!.setDataSource(currentSong.path)
|
||||
}
|
||||
else {
|
||||
trackPlayer!!.setDataSource(this,
|
||||
APIRepository.retrieveSongStreamUri(apiInfo, currentSong),
|
||||
APIRepository.retrieveSongStreamHeader(token))
|
||||
}
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.start()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
fun getCurrentSong(): Song { return currentSong }
|
||||
|
||||
|
||||
fun currentPositionOfTrack(): Int { return trackPlayer!!.currentPosition }
|
||||
|
||||
fun durationOfTrack(): Int { return trackPlayer!!.duration }
|
||||
|
||||
|
||||
fun isPlaying(): Boolean { return trackPlayer!!.isPlaying }
|
||||
|
||||
|
||||
private fun initializeMediaPlayer() {
|
||||
try {
|
||||
if (trackPlayer == null) {
|
||||
trackPlayer = MediaPlayer()
|
||||
}
|
||||
if (appPath.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val trackRepo = TrackRepository()
|
||||
val apiRepo = APIRepository()
|
||||
val tokenRepo = TokenRepository()
|
||||
|
||||
val token = tokenRepo.retrieveToken(appPath)
|
||||
val apiInfo = apiRepo.retrieveRecord(appPath)
|
||||
val songs = trackRepo.fetchSongsIncludingDownloaded(token, apiInfo.uri, appPath)
|
||||
songQueue = songs.toMutableList()
|
||||
|
||||
currentSongIndex = if (retrieveShuffleMode()!!)
|
||||
Random.nextInt(0, songQueue.size - 1) else 0
|
||||
|
||||
currentSong = songQueue[currentSongIndex!!]
|
||||
if (currentSong.downloaded) {
|
||||
trackPlayer!!.setDataSource(currentSong.path)
|
||||
}
|
||||
else {
|
||||
trackPlayer!!.setDataSource(this,
|
||||
APIRepository.retrieveSongStreamUri(apiInfo, currentSong),
|
||||
APIRepository.retrieveSongStreamHeader(token))
|
||||
}
|
||||
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.setOnCompletionListener {
|
||||
playNextTrack()
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun retrieveShuffleMode(): Boolean? {
|
||||
val shuffleRepo = ShuffleRepository(null)
|
||||
|
||||
return when (shuffleRepo.shuffleMode(appPath)) {
|
||||
ShuffleTypes.ShuffleOn -> true
|
||||
ShuffleTypes.ShuffleOff -> false
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseRepeatMode(repeatMode: RepeatTypes): Boolean {
|
||||
return when (repeatMode) {
|
||||
RepeatTypes.RepeatOff -> false
|
||||
RepeatTypes.RepeatSong -> true
|
||||
}
|
||||
}
|
||||
|
||||
private fun offlinePlaySong(song: Song) {
|
||||
try {
|
||||
currentSong = song
|
||||
currentSongIndex = songQueue.indexOfFirst { it.id == song.id }
|
||||
songQueue[currentSongIndex!!] = currentSong
|
||||
|
||||
trackPlayer!!.reset()
|
||||
trackPlayer!!.setDataSource(song.path)
|
||||
trackPlayer!!.prepare()
|
||||
trackPlayer!!.start()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
var msg = ex.message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
package com.example.mear.repositories
|
||||
|
||||
import android.net.Uri
|
||||
import com.example.mear.constants.CPPLib
|
||||
import com.example.mear.models.APIInfo
|
||||
import com.example.mear.models.Song
|
||||
import com.example.mear.models.Token
|
||||
|
||||
class APIRepository: BaseRepository() {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary(CPPLib.NATIVE_LIB)
|
||||
}
|
||||
|
||||
|
||||
fun retrieveSongStreamHeader(token: Token): MutableMap<String, String> {
|
||||
val hddr: MutableMap<String, String> = mutableMapOf()
|
||||
hddr["Authorization"] = "Bearer ${token.accessToken}"
|
||||
hddr["Content-type"] = "Keep-alive"
|
||||
|
||||
return hddr
|
||||
}
|
||||
|
||||
|
||||
fun retrieveSongStreamUri(apiInfo: APIInfo, song: Song): Uri {
|
||||
val uriStr = "${apiInfo.uri}/api/v${apiInfo.version}/song/stream/${song.id}"
|
||||
|
||||
return Uri.parse(uriStr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private external fun retrieveAPIInfoRecord(path: String): APIInfo
|
||||
|
||||
private external fun isAPIInfoTableEmpty(path: String): Boolean
|
||||
|
||||
private external fun saveAPIInfoRecord(api: APIInfo, path: String)
|
||||
|
||||
|
||||
fun retrieveRecord(path: String): APIInfo {
|
||||
return retrieveAPIInfoRecord(path)
|
||||
}
|
||||
|
||||
|
||||
fun isTableEmpty(path: String): Boolean {
|
||||
return isAPIInfoTableEmpty(path)
|
||||
}
|
||||
|
||||
|
||||
fun saveRecord(api: APIInfo, path: String) {
|
||||
return saveAPIInfoRecord(api, path)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.example.mear.repositories
|
||||
|
||||
open class BaseRepository {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("native-lib")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private external fun doesDatabaseExist(path: String): Boolean
|
||||
|
||||
|
||||
fun databaseExist(path: String): Boolean {
|
||||
return doesDatabaseExist(path)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.example.mear.repositories
|
||||
|
||||
import com.example.mear.models.Token
|
||||
|
||||
class CoverArtRepository : BaseRepository() {
|
||||
|
||||
private external fun retrieveCoverArtImage(token: Token, coverArt: CoverArt, apiUri: String): ByteArray
|
||||
|
||||
|
||||
fun fetchCoverArtImage(token: Token, coverArt: CoverArt, apiUri: String): ByteArray {
|
||||
val img = retrieveCoverArtImage(token, coverArt, apiUri)
|
||||
|
||||
return img
|
||||
}
|
||||
|
||||
// TODO: Move this to it's own file later on
|
||||
class CoverArt (var id: Int = 0, var title: String = "")
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.example.mear.repositories
|
||||
|
||||
import android.content.Context
|
||||
|
||||
import org.jetbrains.anko.db.*
|
||||
|
||||
import com.example.mear.models.PlayCount
|
||||
import com.example.mear.models.Track
|
||||
|
||||
class PlayCountRepository(val context: Context) {
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package com.example.mear.repositories
|
||||
|
||||
import android.content.Context
|
||||
|
||||
import com.example.mear.constants.CPPLib
|
||||
|
||||
class RepeatRepository(var context: Context?) {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary(CPPLib.NATIVE_LIB)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private external fun retrieveRepeatMode(path: String): Int
|
||||
|
||||
private external fun updateRepeatMode(path: String)
|
||||
|
||||
|
||||
fun repeatMode(path: String): RepeatTypes {
|
||||
val repeatType = RepeatTypes.valueOf(retrieveRepeatMode(path))
|
||||
|
||||
return repeatType!!
|
||||
}
|
||||
|
||||
|
||||
fun alterRepeatMode(path: String) {
|
||||
updateRepeatMode(path)
|
||||
}
|
||||
|
||||
|
||||
enum class RepeatTypes(val value: Int) {
|
||||
RepeatSong(0),
|
||||
RepeatOff(1);
|
||||
|
||||
companion object {
|
||||
fun valueOf(value: Int) = values().find { it.value == value }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.example.mear.repositories
|
||||
|
||||
import android.content.Context
|
||||
|
||||
import com.example.mear.constants.CPPLib
|
||||
|
||||
|
||||
class ShuffleRepository(var context: Context?) {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary(CPPLib.NATIVE_LIB)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private external fun retrieveShuffleMode(path: String): Int
|
||||
|
||||
private external fun updateShuffle(path: String)
|
||||
|
||||
|
||||
fun shuffleMode(path: String): ShuffleTypes {
|
||||
val shuffleType = ShuffleTypes.valueOf(retrieveShuffleMode(path))
|
||||
|
||||
return shuffleType!!
|
||||
}
|
||||
|
||||
|
||||
fun alterShuffleMode(path: String) {
|
||||
updateShuffle(path)
|
||||
}
|
||||
|
||||
|
||||
enum class ShuffleTypes(val value: Int) {
|
||||
ShuffleOn(0),
|
||||
ShuffleOff(1);
|
||||
|
||||
companion object {
|
||||
fun valueOf(value: Int) = values().find { it.value == value }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.example.mear.repositories
|
||||
|
||||
import com.example.mear.models.Token
|
||||
|
||||
class TokenRepository: BaseRepository() {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("native-lib")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private external fun retrieveTokenRecord(path: String): Token
|
||||
|
||||
private external fun isTokenTableEmpty(path: String): Boolean
|
||||
|
||||
private external fun saveTokenRecord(token: Token, path: String)
|
||||
//private external fun deleteTokenRecord(path: String)
|
||||
//private external fun updateTokenRecord(token: Token, path: String)
|
||||
|
||||
|
||||
fun retrieveToken(path: String): Token {
|
||||
return retrieveTokenRecord(path)
|
||||
}
|
||||
|
||||
|
||||
fun isTableEmpty(path: String): Boolean {
|
||||
return isTokenTableEmpty(path)
|
||||
}
|
||||
|
||||
|
||||
fun saveToken(token: Token, path: String) {
|
||||
return saveTokenRecord(token, path)
|
||||
}
|
||||
|
||||
// TODO: implement this
|
||||
/**
|
||||
fun deleteToken(path: String) {
|
||||
return deleteTokenRecord(path)
|
||||
}
|
||||
|
||||
fun updateToken(token: Token, path: String) {
|
||||
return updateTokenRecord(token, path)
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.example.mear.repositories
|
||||
|
||||
import android.content.Context
|
||||
|
||||
import org.jetbrains.anko.db.*
|
||||
|
||||
import com.example.mear.models.Song
|
||||
import com.example.mear.models.Token
|
||||
import com.example.mear.models.Track
|
||||
|
||||
class TrackRepository(var context: Context? = null) {
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("native-lib")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private external fun retrieveSongs(token: Token, uri: String): Array<Song>
|
||||
private external fun retrieveSongsIncludingDownloaded(token: Token, uri: String, path: String): Array<Song>
|
||||
|
||||
private external fun retrieveSong(token: Token, song: Song, uri: String): Song
|
||||
private external fun downloadSong(token: Token, song: Song, path: String): Song
|
||||
|
||||
private external fun deleteSong(song: Song, path: String): Boolean
|
||||
|
||||
|
||||
fun fetchSongs(token: Token, uri: String): Array<Song> {
|
||||
return retrieveSongs(token, uri)
|
||||
}
|
||||
|
||||
fun fetchSongsIncludingDownloaded(token: Token, uri: String, path: String): Array<Song> {
|
||||
return retrieveSongsIncludingDownloaded(token, uri, path)
|
||||
}
|
||||
|
||||
|
||||
fun fetchSong(token: Token, song: Song, uri: String): Song {
|
||||
return retrieveSong(token, song, uri)
|
||||
}
|
||||
|
||||
fun fetchSongFile(token: Token, song: Song, uri: String) {
|
||||
downloadSong(token, song, uri)
|
||||
}
|
||||
|
||||
fun download(token: Token, song: Song, path: String): Song {
|
||||
return downloadSong(token, song, path)
|
||||
}
|
||||
|
||||
fun delete(song: Song, path: String): Boolean {
|
||||
return deleteSong(song, path)
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package com.example.mear.repositories
|
||||
|
||||
import com.example.mear.models.Token
|
||||
import com.example.mear.models.User
|
||||
|
||||
class UserRepository : BaseRepository() {
|
||||
|
||||
private external fun logUser(user: User, apiUri: String) : Token
|
||||
|
||||
private external fun retrieveUserCredentials(path: String) : User
|
||||
|
||||
private external fun isUserTableEmpty(path: String): Boolean
|
||||
|
||||
private external fun saveUserCredentials(username: User, path: String)
|
||||
|
||||
|
||||
fun fetchToken(user: User, apiUri: String): Token {
|
||||
return logUser(user, apiUri)
|
||||
}
|
||||
|
||||
|
||||
fun retrieveCredentials(path: String): User {
|
||||
return retrieveUserCredentials(path)
|
||||
}
|
||||
|
||||
|
||||
fun isTableEmpty(path: String): Boolean {
|
||||
return isUserTableEmpty(path)
|
||||
}
|
||||
|
||||
|
||||
fun saveCredentials(user: User, path: String) {
|
||||
saveUserCredentials(user, path)
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.example.mear.ui.popups
|
||||
|
||||
import android.animation.Animator
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import com.example.mear.R
|
||||
|
||||
import com.xu.xpopupwindow.XPopupWindow
|
||||
|
||||
class AboutPopup(ctx: Context): XPopupWindow(ctx) {
|
||||
override fun exitAnim(view: View): Animator? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.popup_layout
|
||||
}
|
||||
|
||||
override fun getLayoutParentNodeId(): Int {
|
||||
return R.id.parent
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
}
|
||||
|
||||
override fun initViews() {
|
||||
}
|
||||
|
||||
override fun startAnim(view: View): Animator? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun animStyle(): Int {
|
||||
return -1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.example.mear.util
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
|
||||
class ConvertByteArray(private val byteArray: ByteArray?) {
|
||||
|
||||
fun convertToBmp(): Bitmap {
|
||||
val songImage = BitmapFactory
|
||||
.decodeByteArray(byteArray!!, 0, byteArray!!.size)
|
||||
|
||||
return songImage
|
||||
}
|
||||
fun convertToBmp(rawData: ByteArray): Bitmap {
|
||||
val songImage = BitmapFactory.decodeByteArray(rawData, 0, rawData.size)
|
||||
|
||||
return songImage
|
||||
}
|
||||
fun convertToBmptScales(width: Int, height: Int): Bitmap {
|
||||
val b = BitmapFactory.decodeByteArray(byteArray, 0, byteArray!!.size)
|
||||
|
||||
return Bitmap.createScaledBitmap(b, width, height, false)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.example.mear.util
|
||||
|
||||
|
||||
class ConvertTrackPosition(val percentage: Int) {
|
||||
|
||||
fun newPosition(trackDuration: Int): Int {
|
||||
val newPosition = (trackDuration * (percentage.toDouble() / 100)).toInt()
|
||||
|
||||
return newPosition
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package com.example.mear.util
|
||||
|
||||
import android.media.MediaMetadataRetriever
|
||||
|
||||
import java.io.FileInputStream
|
||||
|
||||
import com.example.mear.models.Track
|
||||
import java.lang.Exception
|
||||
|
||||
class ExtractCover(private val trackPath: String?) {
|
||||
|
||||
fun retrieveCover(): ByteArray {
|
||||
var trackData = MediaMetadataRetriever()
|
||||
trackData.setDataSource(trackPath)
|
||||
|
||||
return trackData.embeddedPicture
|
||||
}
|
||||
fun retrieveCover(track: Track): ByteArray? {
|
||||
|
||||
var coverArt: ByteArray? = null
|
||||
|
||||
try {
|
||||
if (!hasCover(track)) {
|
||||
return null
|
||||
}
|
||||
|
||||
val songPath = track.songPath
|
||||
|
||||
val metaData = MediaMetadataRetriever()
|
||||
val fp = FileInputStream(songPath)
|
||||
metaData.setDataSource(fp.fd)
|
||||
|
||||
coverArt = metaData.embeddedPicture
|
||||
|
||||
fp.close()
|
||||
metaData.release()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
|
||||
return coverArt
|
||||
}
|
||||
fun retrieveCover(songPath: String): ByteArray? {
|
||||
|
||||
var coverArt: ByteArray? = null
|
||||
|
||||
try {
|
||||
if (!hasCover(songPath)) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
val metaData = MediaMetadataRetriever()
|
||||
val fp = FileInputStream(songPath)
|
||||
metaData.setDataSource(fp.fd)
|
||||
|
||||
coverArt = metaData.embeddedPicture
|
||||
|
||||
fp.close()
|
||||
metaData.release()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
|
||||
return coverArt
|
||||
}
|
||||
|
||||
fun hasCover(): Boolean {
|
||||
var trackData = MediaMetadataRetriever()
|
||||
trackData.setDataSource(trackPath)
|
||||
|
||||
if (trackData.embeddedPicture == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
fun hasCover(track: Track): Boolean {
|
||||
try {
|
||||
val trackData = MediaMetadataRetriever()
|
||||
val songPath = track.songPath
|
||||
val songStream = FileInputStream(songPath)
|
||||
trackData.setDataSource(songStream.fd)
|
||||
|
||||
if (trackData.embeddedPicture == null) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
fun hasCover(songPath: String): Boolean {
|
||||
try {
|
||||
val trackData = MediaMetadataRetriever()
|
||||
val songPath = songPath
|
||||
val songStream = FileInputStream(songPath)
|
||||
trackData.setDataSource(songStream.fd)
|
||||
|
||||
if (trackData.embeddedPicture == null) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
val exMsg = ex.message
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.example.mear.workers
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.Data
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
|
||||
import com.example.mear.models.Song
|
||||
import com.example.mear.repositories.TokenRepository
|
||||
import com.example.mear.repositories.TrackRepository
|
||||
|
||||
class IcarusSyncManager(context: Context, workerParams: WorkerParameters) :
|
||||
Worker(context, workerParams) {
|
||||
override fun doWork(): Result {
|
||||
val appPath: String = inputData.getString("appPath")!!
|
||||
val songId = inputData.getInt("songId", 0)
|
||||
if (songId == 0) {
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
val tokenRepo = TokenRepository()
|
||||
val trackRepo = TrackRepository()
|
||||
val tok = tokenRepo.retrieveToken(appPath)
|
||||
val song = Song()
|
||||
song.id = songId
|
||||
song.title = inputData.getString("songTitle")!!
|
||||
song.artist = inputData.getString("songArtist")!!
|
||||
song.album = inputData.getString("songAlbum")!!
|
||||
song.albumArtist = inputData.getString("songAlbumArtist")!!
|
||||
song.genre = inputData.getString("songGenre")!!
|
||||
song.year = inputData.getInt("songYear", 0)
|
||||
song.duration = inputData.getInt("songDuration", 0)
|
||||
song.coverArtId = inputData.getInt("songCoverArtId", 0)
|
||||
song.disc = inputData.getInt("songDisc", 0)
|
||||
song.track = inputData.getInt("songTrack", 0)
|
||||
|
||||
val downloadedSong = trackRepo.download(tok, song, appPath)
|
||||
|
||||
val output: Data = workDataOf("songPath" to downloadedSong.path,
|
||||
"songFilename" to downloadedSong.filename,
|
||||
"songDownloaded" to true)
|
||||
|
||||
return Result.success(output)
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 309 B |
|
Before Width: | Height: | Size: 85 B |
|
Before Width: | Height: | Size: 181 B |
|
Before Width: | Height: | Size: 81 B |
@@ -1,34 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0"/>
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
||||
|
Before Width: | Height: | Size: 365 B |
|
Before Width: | Height: | Size: 88 B |
|
Before Width: | Height: | Size: 661 B |
|
Before Width: | Height: | Size: 100 B |
|
Before Width: | Height: | Size: 805 B |
|
Before Width: | Height: | Size: 116 B |