Compare commits
33 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f1b77dae8 | ||
|
|
7eef227154 | ||
|
|
bddea666f5 | ||
|
|
ed0198a7c2 | ||
|
|
f16bb13271 | ||
|
|
18db18c34d | ||
|
|
1bb1052925 | ||
|
|
211c082d91 | ||
|
|
3049a6bd04 | ||
|
|
6196925915 | ||
|
|
92a578c6a7 | ||
|
|
e6d21f1d10 | ||
|
|
dfafd22ec5 | ||
|
|
be32b990f8 | ||
|
|
09885c3403 | ||
|
|
0965f79bc1 | ||
|
|
73ffc047e8 | ||
|
|
919697d3b2 | ||
|
|
583ac1c708 | ||
|
|
7af20f70e0 | ||
|
|
7e209cd739 | ||
|
|
c709aedb9a | ||
|
|
28cff95ffc | ||
|
|
b9c407a918 | ||
|
|
1a3d05eae9 | ||
|
|
66fee3eb55 | ||
|
|
6472bcde65 | ||
|
|
3562e0fb1f | ||
|
|
d348615dee | ||
|
|
27cdcb61bf | ||
|
|
3b1926a8d5 | ||
|
|
36e309cbe7 | ||
|
|
f2e123efd5 |
16
.gitattributes
vendored
|
|
@ -1,16 +0,0 @@
|
|||
* text=auto
|
||||
*.bmp binary
|
||||
*.cat -text
|
||||
*.dll binary
|
||||
*.fnt binary
|
||||
*.icns binary
|
||||
*.ico binary
|
||||
*.inf -text
|
||||
*.jpg binary
|
||||
*.pdf binary
|
||||
*.png binary
|
||||
*.svg binary
|
||||
*.sys binary
|
||||
*.vcproj -text
|
||||
*.wav binary
|
||||
*.xcf binary
|
||||
303
.gitignore
vendored
|
|
@ -1,303 +0,0 @@
|
|||
# /
|
||||
/build*
|
||||
/sim*
|
||||
/output
|
||||
*.elf
|
||||
*.exe
|
||||
*.so
|
||||
*.o
|
||||
*.a
|
||||
*~
|
||||
__pycache__
|
||||
|
||||
# Intermediate language files
|
||||
/apps/lang/*.update
|
||||
/apps/lang/*.new
|
||||
|
||||
# checkwps
|
||||
/tools/checkwps/output
|
||||
/tools/checkwps/Makefile
|
||||
/tools/checkwps/autoconf.h
|
||||
/tools/checkwps/make.dep
|
||||
/tools/checkwps/rockbox-info.txt
|
||||
/tools/checkwps/checkwps.failures
|
||||
|
||||
# android: java build system
|
||||
/android/bin
|
||||
/android/data
|
||||
/android/gen
|
||||
/android/libs
|
||||
/android/local.properties
|
||||
|
||||
# android: our build system
|
||||
/android/autoconf.h
|
||||
/android/Makefile
|
||||
/android/make.dep
|
||||
/android/apps
|
||||
/android/bitmaps
|
||||
/android/pluginbitmaps
|
||||
/android/firmware
|
||||
/android/lang
|
||||
/android/lib
|
||||
/android/rockbox.*
|
||||
/android/rockbox-info.txt
|
||||
/android/sysfont.c
|
||||
/android/sysfont.h
|
||||
/android/version.h
|
||||
/android/credits.raw
|
||||
|
||||
# android: eclipse stuff
|
||||
/android/.settings
|
||||
|
||||
# buflib test code
|
||||
/firmware/test/buflib/test_main
|
||||
/firmware/test/buflib/test_main2
|
||||
/firmware/test/buflib/test_max
|
||||
/firmware/test/buflib/test_move
|
||||
/firmware/test/buflib/test_move2
|
||||
/firmware/test/buflib/test_shrink
|
||||
/firmware/test/buflib/test_shrink_cb
|
||||
/firmware/test/buflib/test_shrink_startchanged
|
||||
/firmware/test/buflib/test_shrink_unaligned
|
||||
|
||||
# /utils/
|
||||
/utils/Makefile
|
||||
/utils/rbutil
|
||||
|
||||
# /utils/ipodpatcher/
|
||||
/utils/ipodpatcher/ipodpatcher
|
||||
|
||||
# /utils/chinachippatcher/
|
||||
/utils/chinachippatcher/chinachip
|
||||
|
||||
# /utils/bspatch/
|
||||
/utils/bspatch/bspatch
|
||||
|
||||
# /utils/rbutilqt/
|
||||
/utils/rbutilqt/build
|
||||
/utils/rbutilqt/RockboxUtility
|
||||
/utils/rbutilqt/RockboxUtility.*
|
||||
/utils/rbutilqt/Makefile
|
||||
/utils/rbutilqt/*.qm
|
||||
/utils/rbutilqt/release
|
||||
/utils/rbutilqt/debug
|
||||
/utils/rbutilqt/*.Debug
|
||||
/utils/rbutilqt/*.Release
|
||||
/utils/rbutilqt/tags
|
||||
/utils/rbutilqt/.qmake.stash
|
||||
|
||||
# /utils/rbutilqt/lang/
|
||||
/utils/rbutilqt/lang/*.qm
|
||||
|
||||
# More rbutil
|
||||
/utils/*/buildposix
|
||||
/utils/*/uninstall_script.[ch]
|
||||
/utils/*/install_script.[ch]
|
||||
/utils/mkimxboot/mkimxboot
|
||||
/utils/mknwzboot/mknwzboot
|
||||
/utils/mkzenboot/mkzenboot
|
||||
/utils/sansapatcher/sansapatcher
|
||||
/utils/jztool/jztool
|
||||
/utils/tools/bin2c
|
||||
|
||||
# /tools/
|
||||
/tools/bdf2bmp
|
||||
/tools/scramble
|
||||
/tools/generate_rocklatin
|
||||
/tools/descramble
|
||||
/tools/convbdf
|
||||
/tools/bmp2rb
|
||||
/tools/codepages
|
||||
/tools/rdf2binary
|
||||
/tools/mkboot
|
||||
/tools/uclpack
|
||||
/tools/ipod_fw
|
||||
/tools/wavtrim
|
||||
/tools/voicefont
|
||||
/tools/rbspeexenc
|
||||
/tools/rbspeexdec
|
||||
/tools/mknkboot
|
||||
/tools/mktccboot
|
||||
/tools/mkzenboot
|
||||
/tools/mkspl-x1000
|
||||
/tools/iaudio_bl_flash.c
|
||||
/tools/iaudio_bl_flash.h
|
||||
/tools/.vagrant
|
||||
/tools/*-console.log
|
||||
|
||||
# /tools/database/
|
||||
/tools/database/database
|
||||
|
||||
# /tools/rbspeex/
|
||||
/tools/rbspeex/build*
|
||||
/tools/rbspeex/libspeex.a
|
||||
/tools/rbspeex/librbspeex.a
|
||||
/tools/rbspeex/dep-speex
|
||||
|
||||
# /tools/ucl/src/
|
||||
/tools/ucl/src/libucl.a
|
||||
|
||||
# /utils/MTP/
|
||||
/utils/MTP/sendfirm
|
||||
|
||||
# /utils/MTP/beastpatcher/
|
||||
/utils/MTP/beastpatcher/bootimg.*
|
||||
/utils/MTP/beastpatcher/beastpatcher
|
||||
/utils/MTP/beastpatcher/bin2c*
|
||||
|
||||
# /utils/MTP/beastpatcher/vs2005/
|
||||
/utils/MTP/beastpatcher/vs2005/*.ncb
|
||||
/utils/MTP/beastpatcher/vs2005/*.suo
|
||||
/utils/MTP/beastpatcher/vs2005/*.user
|
||||
/utils/MTP/beastpatcher/vs2005/Debug
|
||||
/utils/MTP/beastpatcher/vs2005/Release
|
||||
|
||||
# /utils/jz4740_tools/
|
||||
/utils/jz4740_tools/HXFreplace
|
||||
/utils/jz4740_tools/HXF2IHFS
|
||||
/utils/jz4740_tools/usbtool
|
||||
/utils/jz4740_tools/DLanalyser
|
||||
/utils/jz4740_tools/HXFsplit
|
||||
/utils/jz4740_tools/HXFmerge
|
||||
/utils/jz4740_tools/IHFSsplit
|
||||
/utils/jz4740_tools/jz_xloader.*
|
||||
/utils/jz4740_tools/bin2c
|
||||
|
||||
# /utils/jz4760_tools
|
||||
/utils/jz4760_tools/packtools
|
||||
/utils/jz4760_tools/usbboot
|
||||
|
||||
# /utils/ingenic_tools
|
||||
/utils/ingenic_tools/usbboot
|
||||
|
||||
# /utils/nwztools
|
||||
/utils/nwztools/scsitools/scsitool
|
||||
/utils/nwztools/upgtools/upgtool
|
||||
|
||||
# utils/rk27utils
|
||||
/utils/rk27utils/rkboottool/rkboottool
|
||||
|
||||
# /utils/themeeditor/
|
||||
/utils/themeeditor/debug
|
||||
/utils/themeeditor/release
|
||||
/utils/themeeditor/build
|
||||
/utils/themeeditor/Makefile*
|
||||
/utils/themeeditor/object_script*
|
||||
/utils/themeeditor/rbthemeeditor
|
||||
|
||||
# /utils/zenutils/
|
||||
/utils/zenutils/build
|
||||
/utils/zenutils/bin
|
||||
/utils/zenutils/CMakeCache.txt
|
||||
/utils/zenutils/CMakeFiles
|
||||
/utils/zenutils/cmake_install.cmake
|
||||
/utils/zenutils/Makefile
|
||||
|
||||
# /utils/zenutils/libraries/
|
||||
/utils/zenutils/libraries/CMakeCache.txt
|
||||
/utils/zenutils/libraries/CMakeFiles
|
||||
/utils/zenutils/libraries/cmake_install.cmake
|
||||
/utils/zenutils/libraries/Makefile
|
||||
|
||||
# /utils/zenutils/libraries/beecrypt-4.1.2/
|
||||
/utils/zenutils/libraries/beecrypt-4.1.2/CMakeCache.txt
|
||||
/utils/zenutils/libraries/beecrypt-4.1.2/CMakeFiles
|
||||
/utils/zenutils/libraries/beecrypt-4.1.2/cmake_install.cmake
|
||||
/utils/zenutils/libraries/beecrypt-4.1.2/Makefile
|
||||
|
||||
# /utils/zenutils/libraries/beecrypt-4.1.2/beecrypt/
|
||||
/utils/zenutils/libraries/beecrypt-4.1.2/beecrypt/CMakeCache.txt
|
||||
/utils/zenutils/libraries/beecrypt-4.1.2/beecrypt/CMakeFiles
|
||||
/utils/zenutils/libraries/beecrypt-4.1.2/beecrypt/cmake_install.cmake
|
||||
/utils/zenutils/libraries/beecrypt-4.1.2/beecrypt/Makefile
|
||||
|
||||
# /utils/zenutils/libraries/getpot-c++-1.1.18/
|
||||
/utils/zenutils/libraries/getpot-c++-1.1.18/CMakeCache.txt
|
||||
/utils/zenutils/libraries/getpot-c++-1.1.18/CMakeFiles
|
||||
/utils/zenutils/libraries/getpot-c++-1.1.18/cmake_install.cmake
|
||||
/utils/zenutils/libraries/getpot-c++-1.1.18/Makefile
|
||||
|
||||
# /utils/zenutils/libraries/getpot-c++-1.1.18/getpot/
|
||||
/utils/zenutils/libraries/getpot-c++-1.1.18/getpot/CMakeCache.txt
|
||||
/utils/zenutils/libraries/getpot-c++-1.1.18/getpot/CMakeFiles
|
||||
/utils/zenutils/libraries/getpot-c++-1.1.18/getpot/cmake_install.cmake
|
||||
/utils/zenutils/libraries/getpot-c++-1.1.18/getpot/Makefile
|
||||
|
||||
# /utils/zenutils/libraries/pelib-0.9/
|
||||
/utils/zenutils/libraries/pelib-0.9/CMakeCache.txt
|
||||
/utils/zenutils/libraries/pelib-0.9/CMakeFiles
|
||||
/utils/zenutils/libraries/pelib-0.9/cmake_install.cmake
|
||||
/utils/zenutils/libraries/pelib-0.9/Makefile
|
||||
|
||||
# /utils/zenutils/libraries/pelib-0.9/pelib/
|
||||
/utils/zenutils/libraries/pelib-0.9/pelib/CMakeCache.txt
|
||||
/utils/zenutils/libraries/pelib-0.9/pelib/CMakeFiles
|
||||
/utils/zenutils/libraries/pelib-0.9/pelib/cmake_install.cmake
|
||||
/utils/zenutils/libraries/pelib-0.9/pelib/Makefile
|
||||
|
||||
# /utils/zenutils/libraries/pelib-0.9/pelib/buffer/
|
||||
/utils/zenutils/libraries/pelib-0.9/pelib/buffer/CMakeCache.txt
|
||||
/utils/zenutils/libraries/pelib-0.9/pelib/buffer/CMakeFiles
|
||||
/utils/zenutils/libraries/pelib-0.9/pelib/buffer/cmake_install.cmake
|
||||
/utils/zenutils/libraries/pelib-0.9/pelib/buffer/Makefile
|
||||
|
||||
# /utils/zenutils/libraries/zlib123/
|
||||
/utils/zenutils/libraries/zlib123/CMakeCache.txt
|
||||
/utils/zenutils/libraries/zlib123/CMakeFiles
|
||||
/utils/zenutils/libraries/zlib123/cmake_install.cmake
|
||||
/utils/zenutils/libraries/zlib123/Makefile
|
||||
|
||||
# /utils/zenutils/libraries/zlib123/zlib/
|
||||
/utils/zenutils/libraries/zlib123/zlib/CMakeCache.txt
|
||||
/utils/zenutils/libraries/zlib123/zlib/CMakeFiles
|
||||
/utils/zenutils/libraries/zlib123/zlib/cmake_install.cmake
|
||||
/utils/zenutils/libraries/zlib123/zlib/Makefile
|
||||
|
||||
# /utils/zenutils/source/
|
||||
/utils/zenutils/source/CMakeCache.txt
|
||||
/utils/zenutils/source/CMakeFiles
|
||||
/utils/zenutils/source/cmake_install.cmake
|
||||
/utils/zenutils/source/Makefile
|
||||
|
||||
# /utils/zenutils/source/firmware_extract/
|
||||
/utils/zenutils/source/firmware_extract/CMakeCache.txt
|
||||
/utils/zenutils/source/firmware_extract/CMakeFiles
|
||||
/utils/zenutils/source/firmware_extract/cmake_install.cmake
|
||||
/utils/zenutils/source/firmware_extract/Makefile
|
||||
|
||||
# /utils/zenutils/source/firmware_make/
|
||||
/utils/zenutils/source/firmware_make/CMakeCache.txt
|
||||
/utils/zenutils/source/firmware_make/CMakeFiles
|
||||
/utils/zenutils/source/firmware_make/cmake_install.cmake
|
||||
/utils/zenutils/source/firmware_make/Makefile
|
||||
|
||||
# /utils/zenutils/source/shared/
|
||||
/utils/zenutils/source/shared/CMakeCache.txt
|
||||
/utils/zenutils/source/shared/CMakeFiles
|
||||
/utils/zenutils/source/shared/cmake_install.cmake
|
||||
/utils/zenutils/source/shared/Makefile
|
||||
|
||||
# /utils/zenutils/source/update_extract/
|
||||
/utils/zenutils/source/update_extract/CMakeCache.txt
|
||||
/utils/zenutils/source/update_extract/CMakeFiles
|
||||
/utils/zenutils/source/update_extract/cmake_install.cmake
|
||||
/utils/zenutils/source/update_extract/Makefile
|
||||
|
||||
# /utils/zenutils/source/update_patch/
|
||||
/utils/zenutils/source/update_patch/CMakeCache.txt
|
||||
/utils/zenutils/source/update_patch/CMakeFiles
|
||||
/utils/zenutils/source/update_patch/cmake_install.cmake
|
||||
/utils/zenutils/source/update_patch/Makefile
|
||||
|
||||
# /utils/zenutils/source/zen_crypt/
|
||||
/utils/zenutils/source/zen_crypt/CMakeCache.txt
|
||||
/utils/zenutils/source/zen_crypt/CMakeFiles
|
||||
/utils/zenutils/source/zen_crypt/cmake_install.cmake
|
||||
/utils/zenutils/source/zen_crypt/Makefile
|
||||
|
||||
# /utils/regtools/
|
||||
/utils/regtools/headergen_v1
|
||||
/utils/regtools/headergen_v2
|
||||
/utils/regtools/regtool
|
||||
/utils/regtools/swiss_knife
|
||||
/utils/regtools/tester_v1
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[gerrit]
|
||||
host=gerrit.rockbox.org
|
||||
port=29418
|
||||
project=rockbox.git
|
||||
defaultbranch=master
|
||||
|
|
@ -3,7 +3,5 @@
|
|||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${workspace}"/>
|
||||
<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="false"/>
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/bin/make"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="libs NODEPS=''"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Rockbox}"/>
|
||||
</launchConfiguration>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/../tools/configure"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="--target=201 --type=ad --lcdwidth=320 --lcdheight=480"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>
|
||||
</launchConfiguration>
|
||||
|
|
@ -5,26 +5,6 @@
|
|||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>full,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/tools_configure.launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>auto,full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/make libs.launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@
|
|||
|
||||
</application>
|
||||
|
||||
<uses-sdk android:minSdkVersion="5" />
|
||||
<uses-sdk android:minSdkVersion="4" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -7,85 +7,64 @@
|
|||
# $Id$
|
||||
#
|
||||
|
||||
PACKAGE=org.rockbox
|
||||
PACKAGE_PATH=org/rockbox
|
||||
BINLIB_DIR=$(BUILDDIR)/libs/$(ANDROID_ARCH)
|
||||
ANDROID_DIR=$(ROOTDIR)/android
|
||||
|
||||
# this is a glibc compatibility hack to provide a get_nprocs() replacement.
|
||||
# The NDK ships cpu-features.c which has a compatible function android_getCpuCount()
|
||||
CPUFEAT = $(ANDROID_NDK_PATH)/sources/android/cpufeatures
|
||||
CPUFEAT_BUILD = $(BUILDDIR)
|
||||
INCLUDES += -I$(CPUFEAT)
|
||||
OTHER_SRC += $(CPUFEAT)/cpu-features.c
|
||||
CLEANOBJS += $(CPUFEAT_BUILD)/cpu-features.o
|
||||
$(CPUFEAT_BUILD)/cpu-features.o: $(CPUFEAT)/cpu-features.c
|
||||
$(SILENT)mkdir -p $(dir $@)
|
||||
$(call PRINTS,CC $(subst $(CPUFEAT)/,,$<))$(CC) -o $@ -c $^ $(GCCOPTS) -Wno-unused
|
||||
|
||||
.SECONDEXPANSION: # $$(JAVA_OBJ) is not populated until after this
|
||||
.SECONDEXPANSION: # $$(OBJ) is not populated until after this
|
||||
.PHONY: apk classes clean dex dirs libs jar
|
||||
|
||||
$(BUILDDIR)/$(BINARY): $$(OBJ) $(VOICESPEEXLIB) $(FIRMLIB) $(SKINLIB)
|
||||
$(call PRINTS,LD $(BINARY))$(CC) -o $@ $^ $(LDOPTS) $(GLOBAL_LDOPTS)
|
||||
|
||||
PACKAGE=org.rockbox
|
||||
PACKAGE_PATH=org/rockbox
|
||||
ANDROID_DIR=$(ROOTDIR)/android
|
||||
BINLIB_DIR=$(BUILDDIR)/libs/armeabi
|
||||
|
||||
java2class = $(addsuffix .class,$(basename $(subst $(ANDROID_DIR),$(BUILDDIR),$(1))))
|
||||
|
||||
# API version
|
||||
#ANDROID_PLATFORM_VERSION=19 # Set by configure script
|
||||
ANDROID_PLATFORM_VERSION=11
|
||||
ANDROID_PLATFORM=$(ANDROID_SDK_PATH)/platforms/android-$(ANDROID_PLATFORM_VERSION)
|
||||
|
||||
# Use oldest version available..
|
||||
BUILD_TOOLS_VERSION=$(notdir $(firstword $(wildcard $(ANDROID_SDK_PATH)/build-tools/*)))
|
||||
|
||||
# android tools
|
||||
AAPT=$(ANDROID_SDK_PATH)/build-tools/$(BUILD_TOOLS_VERSION)/aapt
|
||||
DX=$(ANDROID_SDK_PATH)/build-tools/$(BUILD_TOOLS_VERSION)/dx
|
||||
ifneq ("$(wildcard $(ANDROID_SDK_PATH)/tools/zipalign)","")
|
||||
ZIPALIGN=$(ANDROID_SDK_PATH)/tools/zipalign
|
||||
else
|
||||
ZIPALIGN=$(ANDROID_SDK_PATH)/build-tools/$(BUILD_TOOLS_VERSION)/zipalign
|
||||
endif
|
||||
AAPT=$(ANDROID_SDK_PATH)/platform-tools/aapt
|
||||
DX=$(ANDROID_SDK_PATH)/platform-tools/dx
|
||||
APKBUILDER=$(ANDROID_SDK_PATH)/tools/apkbuilder
|
||||
ZIPALIGN=$(ANDROID_SDK_PATH)/tools/zipalign
|
||||
KEYSTORE=$(HOME)/.android/debug.keystore
|
||||
ADB=$(ANDROID_SDK_PATH)/platform-tools/adb
|
||||
BUILDAPK=$(ANDROID_DIR)/buildapk.sh
|
||||
|
||||
CLASSPATH := $(BUILDDIR)/bin/classes
|
||||
|
||||
MANIFEST := $(BUILDDIR)/bin/AndroidManifest.xml
|
||||
MANIFEST_SRC := $(ANDROID_DIR)/AndroidManifest.xml
|
||||
|
||||
R_JAVA := $(BUILDDIR)/gen/$(PACKAGE_PATH)/R.java
|
||||
R_OBJ := $(CLASSPATH)/$(PACKAGE_PATH)/R.class
|
||||
R_OBJ := $(BUILDDIR)/bin/$(PACKAGE_PATH)/R.class
|
||||
|
||||
JAVA_SRC := $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/*.java)
|
||||
JAVA_SRC += $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/Helper/*.java)
|
||||
JAVA_SRC := $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/Helper/*.java)
|
||||
JAVA_SRC += $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/*.java)
|
||||
JAVA_SRC += $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/widgets/*.java)
|
||||
JAVA_SRC += $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/monitors/*.java)
|
||||
|
||||
java2class = $(addsuffix .class,$(basename $(subst $(ANDROID_DIR)/src,$(CLASSPATH),$(1))))
|
||||
|
||||
JAVA_OBJ := $(call java2class,$(JAVA_SRC))
|
||||
JAVA_OBJ := $(call java2class,$(subst $(ANDROID)/src/$(PACKAGE_PATH),$(ANDROID)/bin/$(PACKAGE_PATH),$(JAVA_SRC)))
|
||||
|
||||
|
||||
LIBS := $(BINLIB_DIR)/$(BINARY) $(BINLIB_DIR)/libmisc.so
|
||||
LIBS += $(addprefix $(BINLIB_DIR)/lib,$(patsubst %.codec,%.so,$(notdir $(CODECS))))
|
||||
|
||||
TEMP_APK := $(BUILDDIR)/bin/_rockbox.apk
|
||||
TEMP_APK2 := $(BUILDDIR)/bin/__rockbox.apk
|
||||
DEX := $(BUILDDIR)/bin/classes.dex
|
||||
JAR := $(BUILDDIR)/bin/classes.jar
|
||||
AP_ := $(BUILDDIR)/bin/resources.ap_
|
||||
APK := $(BUILDDIR)/rockbox.apk
|
||||
DEX := $(BUILDDIR)/bin/classes.dex
|
||||
JAR := $(BUILDDIR)/bin/classes.jar
|
||||
AP_ := $(BUILDDIR)/bin/resources.ap_
|
||||
APK := $(BUILDDIR)/rockbox.apk
|
||||
|
||||
_DIRS := $(BUILDDIR)/___/$(PACKAGE_PATH)
|
||||
DIRS := $(subst ___,bin,$(_DIRS))
|
||||
DIRS += $(subst ___,gen,$(_DIRS))
|
||||
DIRS += $(subst ___,data,$(_DIRS))
|
||||
DIRS += $(BUILDDIR)/libs/$(ANDROID_ARCH)
|
||||
DIRS += $(CPUFEAT_BUILD)
|
||||
DIRS += $(CLASSPATH)
|
||||
DIRS += $(BUILDDIR)/libs/armeabi
|
||||
|
||||
RES := $(wildcard $(ANDROID_DIR)/res/*/*)
|
||||
|
||||
CLEANOBJS += bin gen libs data
|
||||
|
||||
JAVAC_OPTS += -source 1.6 -target 1.6 -implicit:none -classpath $(ANDROID_PLATFORM)/android.jar:$(CLASSPATH)
|
||||
JAVAC_OPTS += -implicit:none -classpath $(ANDROID_PLATFORM)/android.jar:$(BUILDDIR)/bin
|
||||
|
||||
.PHONY:
|
||||
$(MANIFEST): $(MANIFEST_SRC) $(DIRS)
|
||||
|
|
@ -96,18 +75,21 @@ $(R_JAVA) $(AP_): $(MANIFEST) $(RES) | $(DIRS)
|
|||
-J $(BUILDDIR)/gen -M $(MANIFEST) -S $(ANDROID_DIR)/res \
|
||||
-I $(ANDROID_PLATFORM)/android.jar -F $(AP_)
|
||||
|
||||
$(CLASSPATH)/$(PACKAGE_PATH)/R.class: $(R_JAVA)
|
||||
$(BUILDDIR)/bin/$(PACKAGE_PATH)/R.class: $(R_JAVA)
|
||||
$(call PRINTS,JAVAC $(subst $(ROOTDIR)/,,$<))javac -d $(BUILDDIR)/bin \
|
||||
$(JAVAC_OPTS) -sourcepath $(ANDROID_DIR)/gen $<
|
||||
$(JAVAC_OPTS) \
|
||||
-sourcepath $(ANDROID_DIR)/gen $<
|
||||
|
||||
$(CLASSPATH)/$(PACKAGE_PATH)/%.class: $(ANDROID_DIR)/src/$(PACKAGE_PATH)/%.java $(CLASSPATH)/$(PACKAGE_PATH)/R.class
|
||||
$(call PRINTS,JAVAC $(subst $(ROOTDIR)/,,$<))javac -d $(CLASSPATH) \
|
||||
$(JAVAC_OPTS) -sourcepath $(ANDROID_DIR)/src $<
|
||||
$(BUILDDIR)/bin/$(PACKAGE_PATH)/%.class: $(ANDROID_DIR)/src/$(PACKAGE_PATH)/%.java $(BUILDDIR)/bin/$(PACKAGE_PATH)/R.class
|
||||
$(call PRINTS,JAVAC $(subst $(ROOTDIR)/,,$<))javac -d $(BUILDDIR)/bin \
|
||||
$(JAVAC_OPTS) \
|
||||
-sourcepath $(ANDROID_DIR)/src $<
|
||||
|
||||
$(JAR): $(JAVA_SRC) $(R_JAVA)
|
||||
$(call PRINTS,JAVAC $(subst $(ROOTDIR)/,,$?))javac -d $(CLASSPATH) \
|
||||
$(JAVAC_OPTS) -sourcepath $(ANDROID_DIR)/src:$(ANDROID_DIR)/gen $?
|
||||
$(call PRINTS,JAR $(subst $(BUILDDIR)/,,$@))jar cf $(JAR) -C $(CLASSPATH) org
|
||||
$(call PRINTS,JAVAC $(subst $(ROOTDIR)/,,$?))javac -d $(BUILDDIR)/bin \
|
||||
$(JAVAC_OPTS) \
|
||||
-sourcepath $(ANDROID_DIR)/src:$(ANDROID_DIR)/gen $?
|
||||
$(call PRINTS,JAR $(subst $(BUILDDIR)/,,$@))jar cf $(JAR) -C $(BUILDDIR)/bin org
|
||||
|
||||
jar: $(JAR)
|
||||
|
||||
|
|
@ -120,43 +102,33 @@ dex: $(DEX)
|
|||
|
||||
classes: $(R_OBJ) $(JAVA_OBJ)
|
||||
|
||||
|
||||
$(BUILDDIR)/$(BINARY): $$(OBJ) $(FIRMLIB) $(VOICESPEEXLIB) $(CORE_LIBS) $(CPUFEAT_BUILD)/cpu-features.o
|
||||
$(call PRINTS,LD $(BINARY))$(CC) -o $@ $^ $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,-Map,$(BUILDDIR)/rockbox.map
|
||||
$(call PRINTS,OC $(@F))$(call objcopy,$@,$@)
|
||||
|
||||
$(BINLIB_DIR)/$(BINARY): $(BUILDDIR)/$(BINARY)
|
||||
$(call PRINTS,CP $(BINARY))cp $^ $@
|
||||
|
||||
$(BINLIB_DIR)/libmisc.so: $(BUILDDIR)/rockbox.zip
|
||||
$(call PRINTS,CP rockbox.zip)cp $^ $@
|
||||
|
||||
$(BINLIB_DIR)/lib%.so: $(RBCODEC_BLD)/codecs/%.codec
|
||||
$(BINLIB_DIR)/lib%.so: $(BUILDDIR)/apps/codecs/%.codec
|
||||
$(call PRINTS,CP $(@F))cp $^ $@
|
||||
|
||||
libs: $(DIRS) $(LIBS)
|
||||
libs: $(LIBS)
|
||||
|
||||
$(TEMP_APK): $(AP_) $(LIBS) $(DEX) | $(DIRS)
|
||||
$(call PRINTS,APK $(subst $(BUILDDIR)/,,$@))$(BUILDAPK) $(BUILDDIR) $(notdir $@) $(BUILD_TOOLS_VERSION)
|
||||
$(call PRINTS,APK $(subst $(BUILDDIR)/,,$@))$(APKBUILDER) $@ \
|
||||
-u -z $(AP_) -f $(DEX) -nf $(BUILDDIR)/libs
|
||||
|
||||
$(KEYSTORE):
|
||||
$(SILENT)mkdir -p $(HOME)/.android
|
||||
$(call PRINTS,KEYTOOL debug.keystore)keytool -genkey \
|
||||
-alias androiddebugkey -keystore $@ \
|
||||
-storepass android -keypass android -validity 365 \
|
||||
-sigalg MD5withRSA -keyalg RSA -keysize 1024 \
|
||||
-dname "CN=Android Debug,O=Android,C=US"
|
||||
|
||||
ifdef NODEPS
|
||||
$(APK): $(TEMP_APK) $(KEYSTORE)
|
||||
else
|
||||
$(APK): $(TEMP_APK) $(BUILDDIR)/rockbox.zip $(KEYSTORE)
|
||||
endif
|
||||
$(SILENT)rm -f $@
|
||||
$(call PRINTS,SIGN $(subst $(BUILDDIR)/,,$@))jarsigner \
|
||||
-keystore "$(KEYSTORE)" -storepass "android" -keypass "android" \
|
||||
-signedjar $(TEMP_APK2) $(TEMP_APK) "androiddebugkey" \
|
||||
-sigalg MD5withRSA -digestalg SHA1
|
||||
-signedjar $(TEMP_APK2) $(TEMP_APK) "androiddebugkey"
|
||||
$(SILENT)$(ZIPALIGN) -v 4 $(TEMP_APK2) $@ > /dev/null
|
||||
|
||||
$(DIRS):
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
# Override some props according to android.make
|
||||
# see $ANDROID_SDK_PATH/tools/ant/build.xml for what's overridable
|
||||
# Once we can build signed *release* builds, we should have a different
|
||||
# names for the debug builds
|
||||
|
||||
|
||||
# the signed, unzipaligned file is bin/__rockbox.apk
|
||||
out.packaged.file=bin/__${ant.project.name}.apk
|
||||
|
||||
# the final file is rockbox.apk, in the build dir
|
||||
out.packaged.file=${ant.project.name}.apk
|
||||
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="rockbox" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
|
||||
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||
in between standard targets -->
|
||||
<!--
|
||||
<target name="-pre-build">
|
||||
</target>
|
||||
<target name="-pre-compile">
|
||||
</target>
|
||||
|
||||
/* This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir} */
|
||||
<target name="-post-compile">
|
||||
</target>
|
||||
-->
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
BUILDDIR=$1
|
||||
APK=$2
|
||||
SDKV=$3
|
||||
|
||||
[ -z $ANDROID_SDK_PATH ] && exit 1
|
||||
[ -z $BUILDDIR ] && exit 1
|
||||
[ -d $BUILDDIR ] || exit 1
|
||||
|
||||
# need to cd into the bin dir and create a symlink to the libraries
|
||||
# so that aapt puts the libraries with the correct prefix into the apk
|
||||
cd $BUILDDIR/bin
|
||||
ln -nfs $BUILDDIR/libs lib
|
||||
cp resources.ap_ $APK
|
||||
$ANDROID_SDK_PATH/build-tools/$SDKV/aapt add $APK classes.dex > /dev/null
|
||||
$ANDROID_SDK_PATH/build-tools/$SDKV/aapt add $APK lib/*/* > /dev/null
|
||||
|
||||
exit 0
|
||||
11
android/default.properties
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "build.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-11
|
||||
|
|
@ -6,32 +6,32 @@
|
|||
# it stopped
|
||||
set -e
|
||||
|
||||
SDK_DOWNLOAD_URL="http://developer.android.com/sdk/index.html"
|
||||
NDK_DOWNLOAD_URL="http://developer.android.com/sdk/ndk/index.html"
|
||||
|
||||
find_url() {
|
||||
base_url="$1"
|
||||
os="$2"
|
||||
wget -q -O - $base_url | grep dl.google.com | sed 's/.*"\(http:\/\/.*\)".*/\1/' | grep $os | grep -v bundle | grep -v .exe # Windows hack
|
||||
}
|
||||
# http://developer.android.com/sdk/index.html
|
||||
SDK_URL_LNX="http://dl.google.com/android/android-sdk_r11-linux_x86.tgz"
|
||||
SDK_URL_MAC="http://dl.google.com/android/android-sdk_r11-mac_x86.zip"
|
||||
SDK_URL_WIN="http://dl.google.com/android/android-sdk_r11-windows.zip"
|
||||
# http://developer.android.com/sdk/ndk/index.html
|
||||
NDK_URL_LNX="http://dl.google.com/android/ndk/android-ndk-r5c-linux-x86.tar.bz2"
|
||||
NDK_URL_MAC="http://dl.google.com/android/ndk/android-ndk-r5c-darwin-x86.tar.bz2"
|
||||
NDK_URL_WIN="http://dl.google.com/android/ndk/android-ndk-r5c-windows.zip"
|
||||
|
||||
OS=`uname`
|
||||
case $OS in
|
||||
Linux)
|
||||
SDK_URL=$(find_url $SDK_DOWNLOAD_URL linux)
|
||||
NDK_URL=$(find_url $NDK_DOWNLOAD_URL linux)
|
||||
SDK_URL=$SDK_URL_LNX
|
||||
NDK_URL=$NDK_URL_LNX
|
||||
ANDROID=tools/android
|
||||
;;
|
||||
|
||||
Darwin)
|
||||
SDK_URL=$(find_url $SDK_DOWNLOAD_URL mac)
|
||||
NDK_URL=$(find_url $NDK_DOWNLOAD_URL darwin)
|
||||
SDK_URL=$SDK_URL_MAC
|
||||
NDK_URL=$NDK_URL_MAC
|
||||
ANDROID=tools/android
|
||||
;;
|
||||
|
||||
CYGWIN*)
|
||||
SDK_URL=$(find_url $SDK_DOWNLOAD_URL windows)
|
||||
NDK_URL=$(find_url $NDK_DOWNLOAD_URL windows)
|
||||
SDK_URL=$SDK_URL_WIN
|
||||
NDK_URL=$NDK_URL_WIN
|
||||
ANDROID=tools/android.bat
|
||||
;;
|
||||
esac
|
||||
|
|
@ -52,14 +52,14 @@ download_and_extract() {
|
|||
fi
|
||||
|
||||
echo " * Extracting $name..."
|
||||
case ${local_file} in
|
||||
*.zip)
|
||||
case ${local_file#*.} in
|
||||
zip)
|
||||
unzip -qo -d "$prefix" "$local_file"
|
||||
;;
|
||||
*.tgz|*.tar.gz)
|
||||
(cd $prefix; tar -xzf "$local_file")
|
||||
tgz|tar.gz)
|
||||
(cd $prefix; tar -xf "$local_file")
|
||||
;;
|
||||
*.tar.bz2)
|
||||
tar.bz2)
|
||||
(cd $prefix; tar -xjf "$local_file")
|
||||
;;
|
||||
*)
|
||||
|
|
@ -80,7 +80,7 @@ fi
|
|||
|
||||
if [ -z "$(find $SDK_PATH/platforms -type d -name 'android-*')" ]; then
|
||||
echo " * Installing Android platforms..."
|
||||
$SDK_PATH/$ANDROID update sdk --no-ui --filter platform,platform-tool,tool
|
||||
$SDK_PATH/$ANDROID update sdk --no-ui --filter platform,tool
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
-optimizationpasses 5
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-dontpreverify
|
||||
-verbose
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||
-keep public class * extends android.preference.Preference
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-19
|
||||
|
|
@ -8,20 +8,19 @@
|
|||
android:paddingBottom="0dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView android:id="@+id/artwork"
|
||||
android:gravity="center"
|
||||
android:padding="2dp"
|
||||
android:scaleType="center"
|
||||
android:adjustViewBounds="false"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent">
|
||||
</ImageView>
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView android:src="@drawable/notification_small"
|
||||
android:gravity="center"
|
||||
android:paddingTop="2dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
</ImageView>
|
||||
|
||||
<TextView android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -39,7 +38,7 @@
|
|||
<LinearLayout android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="3dp"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="vertical">
|
||||
<TextView android:id="@+id/content"
|
||||
android:layout_gravity="left"
|
||||
android:scrollHorizontally="true"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
<string name="OK">OK</string>
|
||||
<string name="Cancel">Cancel</string>
|
||||
<string name="KbdInputTitle">Rockbox Keyboard Input</string>
|
||||
<string name="YesNoTitle">Rockbox</string>
|
||||
<string name="Yes">Yes</string>
|
||||
<string name="No">No</string>
|
||||
<string name="error_extraction">Error occured during extraction!</string>
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2011 Thomas Martitz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
package org.rockbox.Helper;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class Logger
|
||||
{
|
||||
private static final String TAG = "Rockbox";
|
||||
|
||||
public static void i(String s)
|
||||
{
|
||||
Log.i(TAG, s);
|
||||
}
|
||||
|
||||
public static void d(String s)
|
||||
{
|
||||
Log.d(TAG, s);
|
||||
}
|
||||
public static void d(String s, Throwable t)
|
||||
{
|
||||
Log.d(TAG, s, t);
|
||||
}
|
||||
|
||||
public static void e(String s)
|
||||
{
|
||||
Log.e(TAG, s);
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.media.AudioManager;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
public class MediaButtonReceiver
|
||||
|
|
@ -58,7 +59,6 @@ public class MediaButtonReceiver
|
|||
/* Throwable includes Exception and the expected
|
||||
* NoClassDefFoundError */
|
||||
api = new OldApi(c);
|
||||
Logger.i("MediaButtonReceiver: Falling back to compatibility API");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ public class MediaButtonReceiver
|
|||
|
||||
public void unregister()
|
||||
{
|
||||
api.unregister();
|
||||
api.register();
|
||||
}
|
||||
|
||||
/* helper class for the manifest */
|
||||
|
|
@ -88,7 +88,7 @@ public class MediaButtonReceiver
|
|||
KeyEvent key = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
|
||||
if (key.getAction() == KeyEvent.ACTION_UP)
|
||||
{ /* pass the pressed key to Rockbox, starting it if needed */
|
||||
RockboxService s = RockboxService.getInstance();
|
||||
RockboxService s = RockboxService.get_instance();
|
||||
if (s == null || !s.isRockboxRunning())
|
||||
startService(context, intent);
|
||||
else if (RockboxFramebuffer.buttonHandler(key.getKeyCode(), false))
|
||||
|
|
@ -144,7 +144,7 @@ public class MediaButtonReceiver
|
|||
|
||||
public void onAudioFocusChange(int focusChange)
|
||||
{
|
||||
Logger.d("Audio focus" + ((focusChange>0)?"gained":"lost")+
|
||||
Log.d("Rockbox", "Audio focus" + ((focusChange>0)?"gained":"lost")+
|
||||
": "+ focusChange);
|
||||
if (running)
|
||||
{ /* Play nice and stop for the the other app */
|
||||
|
|
|
|||
|
|
@ -1,32 +1,24 @@
|
|||
package org.rockbox.Helper;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.rockbox.R;
|
||||
import org.rockbox.RockboxActivity;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
public class RunForegroundManager
|
||||
{
|
||||
/* all below is heavily based on the examples found on
|
||||
* http://developer.android.com/reference/android/app/Service.html#setForeground(boolean)
|
||||
*/
|
||||
private Notification mNotification;
|
||||
private NotificationManager mNM;
|
||||
private IRunForeground api;
|
||||
private Service mCurrentService;
|
||||
private Handler mServiceHandler;
|
||||
private Intent mWidgetUpdate;
|
||||
private int iconheight;
|
||||
|
||||
public RunForegroundManager(Service service)
|
||||
{
|
||||
|
|
@ -38,11 +30,6 @@ public class RunForegroundManager
|
|||
Intent intent = new Intent(service, RockboxActivity.class);
|
||||
intent = intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
/* retrieve height of launcher icon. Used to scale down album art. */
|
||||
Resources resources = service.getResources();
|
||||
Drawable draw = resources.getDrawable(R.drawable.launcher);
|
||||
iconheight = draw.getIntrinsicHeight();
|
||||
|
||||
mNotification = new Notification();
|
||||
mNotification.tickerText = service.getString(R.string.notification);
|
||||
mNotification.icon = R.drawable.notification;
|
||||
|
|
@ -50,99 +37,47 @@ public class RunForegroundManager
|
|||
mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
|
||||
mNotification.contentIntent = PendingIntent.getActivity(service, 0, intent, 0);
|
||||
|
||||
try {
|
||||
api = new NewForegroundApi(R.string.notification, mNotification);
|
||||
} catch (Throwable t) {
|
||||
/* Throwable includes Exception and the expected
|
||||
* NoClassDefFoundError for Android 1.x */
|
||||
try {
|
||||
api = new OldForegroundApi();
|
||||
Logger.i("RunForegroundManager: Falling back to compatibility API");
|
||||
} catch (Exception e) {
|
||||
Logger.e("Cannot run in foreground: No available API");
|
||||
}
|
||||
}
|
||||
mServiceHandler = new Handler(service.getMainLooper());
|
||||
initForegroundCompat();
|
||||
}
|
||||
|
||||
private void LOG(CharSequence text)
|
||||
{
|
||||
Log.d("Rockbox", (String)text);
|
||||
}
|
||||
|
||||
private void LOG(CharSequence text, Throwable tr)
|
||||
{
|
||||
Log.d("Rockbox", (String)text, tr);
|
||||
}
|
||||
|
||||
public void startForeground()
|
||||
{
|
||||
/*
|
||||
* Send the notification.
|
||||
* We use a layout id because it is a unique number.
|
||||
* We use it later to cancel.
|
||||
*/
|
||||
mNM.notify(R.string.notification, mNotification);
|
||||
/*
|
||||
* this call makes the service run as foreground, which
|
||||
* provides enough cpu time to do music decoding in the
|
||||
* background
|
||||
*/
|
||||
api.startForeground();
|
||||
startForegroundCompat(R.string.notification, mNotification);
|
||||
}
|
||||
|
||||
public void stopForeground()
|
||||
{
|
||||
/* Note to cancel BEFORE changing the
|
||||
* foreground state, since we could be killed at that point.
|
||||
*/
|
||||
mNM.cancel(R.string.notification);
|
||||
api.stopForeground();
|
||||
stopForegroundCompat(R.string.notification);
|
||||
mWidgetUpdate = null;
|
||||
}
|
||||
|
||||
public void updateNotification(final String title, final String artist, final String album, final String albumart)
|
||||
public void updateNotification(String title, String artist, String album, String albumart)
|
||||
{
|
||||
/* do this on the main thread for 2 reasons
|
||||
* 1) Don't delay track switching with possibly costly albumart
|
||||
* loading (i.e. off-load from the Rockbox thread)
|
||||
* 2) Work around a bug in Android where decodeFile() fails outside
|
||||
* of the main thread (http://stackoverflow.com/q/7228633)
|
||||
*/
|
||||
mServiceHandler.post(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
final RemoteViews views = mNotification.contentView;
|
||||
views.setTextViewText(R.id.title, title);
|
||||
views.setTextViewText(R.id.content, artist+"\n"+album);
|
||||
if (artist.equals(""))
|
||||
mNotification.tickerText = title;
|
||||
else
|
||||
mNotification.tickerText = title+" - "+artist;
|
||||
RemoteViews views = mNotification.contentView;
|
||||
views.setTextViewText(R.id.title, title);
|
||||
views.setTextViewText(R.id.content, artist+"\n"+album);
|
||||
if (artist.equals(""))
|
||||
mNotification.tickerText = title;
|
||||
else
|
||||
mNotification.tickerText = title+" - "+artist;
|
||||
mNM.notify(R.string.notification, mNotification);
|
||||
|
||||
if (albumart != null) {
|
||||
/* The notification area doesn't have permissions to access the SD card.
|
||||
* Push the data as Bitmap instead of Uri. Scale down to size of
|
||||
* launcher icon -- broadcasting the unscaled image may yield in
|
||||
* too much data, causing UI hangs of Rockbox. */
|
||||
Bitmap b = BitmapFactory.decodeFile(albumart);
|
||||
if(b != null) {
|
||||
/* scale width to keep aspect ratio -- height is the constraint */
|
||||
int scaledwidth = Math.round(iconheight*((float)b.getWidth()/b.getHeight()));
|
||||
views.setImageViewBitmap(R.id.artwork,
|
||||
Bitmap.createScaledBitmap(b, scaledwidth, iconheight, false));
|
||||
}
|
||||
else {
|
||||
views.setImageViewResource(R.id.artwork, R.drawable.launcher);
|
||||
}
|
||||
}
|
||||
else {
|
||||
views.setImageViewResource(R.id.artwork, R.drawable.launcher);
|
||||
}
|
||||
mWidgetUpdate = new Intent("org.rockbox.TrackUpdateInfo");
|
||||
mWidgetUpdate.putExtra("title", title);
|
||||
mWidgetUpdate.putExtra("artist", artist);
|
||||
mWidgetUpdate.putExtra("album", album);
|
||||
mWidgetUpdate.putExtra("albumart", albumart);
|
||||
mCurrentService.sendBroadcast(mWidgetUpdate);
|
||||
|
||||
/* notify in this runnable to make sure the notification
|
||||
* has the correct albumart */
|
||||
mNM.notify(R.string.notification, mNotification);
|
||||
}
|
||||
});
|
||||
mWidgetUpdate = new Intent("org.rockbox.TrackUpdateInfo");
|
||||
mWidgetUpdate.putExtra("title", title);
|
||||
mWidgetUpdate.putExtra("artist", artist);
|
||||
mWidgetUpdate.putExtra("album", album);
|
||||
mWidgetUpdate.putExtra("albumart", albumart);
|
||||
mCurrentService.sendBroadcast(mWidgetUpdate);
|
||||
}
|
||||
|
||||
public void resendUpdateNotification()
|
||||
|
|
@ -153,68 +88,78 @@ public class RunForegroundManager
|
|||
|
||||
public void finishNotification()
|
||||
{
|
||||
Logger.d("TrackFinish");
|
||||
Log.d("Rockbox", "TrackFinish");
|
||||
Intent widgetUpdate = new Intent("org.rockbox.TrackFinish");
|
||||
mCurrentService.sendBroadcast(widgetUpdate);
|
||||
}
|
||||
|
||||
private interface IRunForeground
|
||||
{
|
||||
void startForeground();
|
||||
void stopForeground();
|
||||
}
|
||||
/* Loosely based on http://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification) */
|
||||
private static final Class<?>[] mSetForegroundSignature = new Class[] {boolean.class};
|
||||
private static final Class<?>[] mStartForegroundSignature = new Class[] {int.class, Notification.class};
|
||||
private static final Class<?>[] mStopForegroundSignature = new Class[] {boolean.class};
|
||||
|
||||
private class NewForegroundApi implements IRunForeground
|
||||
{
|
||||
int id;
|
||||
Notification mNotification;
|
||||
NewForegroundApi(int _id, Notification _notification)
|
||||
{
|
||||
id = _id;
|
||||
mNotification = _notification;
|
||||
}
|
||||
private Method mSetForeground;
|
||||
private Method mStartForeground;
|
||||
private Method mStopForeground;
|
||||
|
||||
public void startForeground()
|
||||
{
|
||||
mCurrentService.startForeground(id, mNotification);
|
||||
}
|
||||
|
||||
public void stopForeground()
|
||||
{
|
||||
mCurrentService.stopForeground(true);
|
||||
}
|
||||
}
|
||||
|
||||
private class OldForegroundApi implements IRunForeground
|
||||
{
|
||||
/*
|
||||
* Get the new API through reflection because it's unavailable
|
||||
* in honeycomb
|
||||
*/
|
||||
private Method mSetForeground;
|
||||
|
||||
public OldForegroundApi() throws SecurityException, NoSuchMethodException
|
||||
{
|
||||
mSetForeground = getClass().getMethod("setForeground",
|
||||
new Class[] { boolean.class });
|
||||
}
|
||||
|
||||
public void startForeground()
|
||||
{
|
||||
private void initForegroundCompat() {
|
||||
Class<?> serviceClass = mCurrentService.getClass();
|
||||
try {
|
||||
mStartForeground = serviceClass.getMethod("startForeground", mStartForegroundSignature);
|
||||
mStopForeground = serviceClass.getMethod("stopForeground", mStopForegroundSignature);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// Running on an older platform.
|
||||
mStartForeground = mStopForeground = null;
|
||||
try {
|
||||
mSetForeground.invoke(mCurrentService, Boolean.TRUE);
|
||||
} catch (Exception e) {
|
||||
Logger.e("startForeground compat error: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
mSetForeground = serviceClass.getMethod("setForeground", mSetForegroundSignature);
|
||||
} catch (NoSuchMethodException e2) {
|
||||
throw new IllegalStateException("OS doesn't have Service.startForeground nor Service.setForeground!", e2);
|
||||
}
|
||||
}
|
||||
public void stopForeground()
|
||||
{
|
||||
try {
|
||||
mSetForeground.invoke(mCurrentService, Boolean.FALSE);
|
||||
} catch (Exception e) {
|
||||
Logger.e("stopForeground compat error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void invokeMethod(Method method, Object[] args) {
|
||||
try {
|
||||
method.invoke(mCurrentService, args);
|
||||
} catch (Exception e) {
|
||||
// Should not happen.
|
||||
Log.w("Rockbox", "Unable to invoke method", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper around the new startForeground method, using the older
|
||||
* APIs if it is not available.
|
||||
*/
|
||||
private void startForegroundCompat(int id, Notification notification) {
|
||||
// If we have the new startForeground API, then use it.
|
||||
if (mStartForeground != null) {
|
||||
Object[] startForeGroundArgs = new Object[] {Integer.valueOf(id), notification};
|
||||
invokeMethod(mStartForeground, startForeGroundArgs);
|
||||
} else {
|
||||
// Fall back on the old API.
|
||||
Object[] setForegroundArgs = new Object[] {Boolean.TRUE};
|
||||
invokeMethod(mSetForeground, setForegroundArgs);
|
||||
mNM.notify(id, notification);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a wrapper around the new stopForeground method, using the older
|
||||
* APIs if it is not available.
|
||||
*/
|
||||
private void stopForegroundCompat(int id) {
|
||||
// If we have the new stopForeground API, then use it.
|
||||
if (mStopForeground != null) {
|
||||
Object[] stopForegroundArgs = new Object[] {Boolean.TRUE};
|
||||
invokeMethod(mStopForeground, stopForegroundArgs);
|
||||
} else {
|
||||
// Fall back on the old API. Note to cancel BEFORE changing the
|
||||
// foreground state, since we could be killed at that point.
|
||||
mNM.cancel(id);
|
||||
|
||||
Object[] setForegroundArgs = new Object[] {Boolean.FALSE};
|
||||
invokeMethod(mSetForeground, setForegroundArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import android.content.Intent;
|
|||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.ResultReceiver;
|
||||
import android.util.Log;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
|
@ -42,11 +43,12 @@ public class RockboxActivity extends Activity
|
|||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
|
||||
Intent intent = new Intent(this, RockboxService.class);
|
||||
intent.setAction(Intent.ACTION_MAIN);
|
||||
intent.putExtra("callback", new ResultReceiver(new Handler(getMainLooper())) {
|
||||
private boolean unzip = false;
|
||||
private ProgressDialog loadingdialog;
|
||||
|
||||
private void createProgressDialog()
|
||||
{
|
||||
loadingdialog = new ProgressDialog(RockboxActivity.this);
|
||||
|
|
@ -60,32 +62,20 @@ public class RockboxActivity extends Activity
|
|||
@Override
|
||||
protected void onReceiveResult(final int resultCode, final Bundle resultData)
|
||||
{
|
||||
RockboxFramebuffer fb;
|
||||
switch (resultCode) {
|
||||
case RockboxService.RESULT_INVOKING_MAIN:
|
||||
if (loadingdialog != null)
|
||||
loadingdialog.dismiss();
|
||||
fb = new RockboxFramebuffer(RockboxActivity.this);
|
||||
setContentView(fb);
|
||||
fb.requestFocus();
|
||||
break;
|
||||
case RockboxService.RESULT_LIB_LOAD_PROGRESS:
|
||||
if (loadingdialog == null)
|
||||
createProgressDialog();
|
||||
|
||||
loadingdialog.setIndeterminate(false);
|
||||
loadingdialog.setMax(resultData.getInt("max", 100));
|
||||
loadingdialog.setProgress(resultData.getInt("value", 0));
|
||||
break;
|
||||
case RockboxService.RESULT_LIB_LOADED:
|
||||
unzip = resultData.getBoolean("unzip");
|
||||
break;
|
||||
case RockboxService.RESULT_SERVICE_RUNNING:
|
||||
if (!unzip) /* defer to RESULT_INVOKING_MAIN */
|
||||
{
|
||||
fb = new RockboxFramebuffer(RockboxActivity.this);
|
||||
setContentView(fb);
|
||||
fb.requestFocus();
|
||||
}
|
||||
setServiceActivity(true);
|
||||
break;
|
||||
case RockboxService.RESULT_ERROR_OCCURED:
|
||||
|
|
@ -97,21 +87,21 @@ public class RockboxActivity extends Activity
|
|||
}
|
||||
}
|
||||
});
|
||||
setContentView(new RockboxFramebuffer(this));
|
||||
startService(intent);
|
||||
}
|
||||
|
||||
private void setServiceActivity(boolean set)
|
||||
{
|
||||
RockboxService s = RockboxService.getInstance();
|
||||
RockboxService s = RockboxService.get_instance();
|
||||
if (s != null)
|
||||
s.setActivity(set ? this : null);
|
||||
s.set_activity(set ? this : null);
|
||||
}
|
||||
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
setVisible(true);
|
||||
setServiceActivity(true);
|
||||
}
|
||||
|
||||
/* this is also called when the backlight goes off,
|
||||
|
|
@ -139,4 +129,9 @@ public class RockboxActivity extends Activity
|
|||
super.onDestroy();
|
||||
setServiceActivity(false);
|
||||
}
|
||||
|
||||
private void LOG(CharSequence text)
|
||||
{
|
||||
Log.d("Rockbox", (String) text);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import android.graphics.Bitmap;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
|
|
@ -39,6 +40,7 @@ public class RockboxFramebuffer extends SurfaceView
|
|||
{
|
||||
private final DisplayMetrics metrics;
|
||||
private final ViewConfiguration view_config;
|
||||
private ByteBuffer native_buf;
|
||||
private Bitmap btm;
|
||||
|
||||
/* first stage init; needs to run from a thread that has a Looper
|
||||
|
|
@ -46,6 +48,7 @@ public class RockboxFramebuffer extends SurfaceView
|
|||
public RockboxFramebuffer(Context c)
|
||||
{
|
||||
super(c);
|
||||
|
||||
metrics = c.getResources().getDisplayMetrics();
|
||||
view_config = ViewConfiguration.get(c);
|
||||
getHolder().addCallback(this);
|
||||
|
|
@ -57,14 +60,20 @@ public class RockboxFramebuffer extends SurfaceView
|
|||
setEnabled(false);
|
||||
}
|
||||
|
||||
private void update(ByteBuffer framebuffer)
|
||||
/* second stage init; called from Rockbox with information about the
|
||||
* display framebuffer */
|
||||
private void java_lcd_init(int lcd_width, int lcd_height, ByteBuffer native_fb)
|
||||
{
|
||||
btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565);
|
||||
native_buf = native_fb;
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
private void java_lcd_update()
|
||||
{
|
||||
SurfaceHolder holder = getHolder();
|
||||
Canvas c = holder.lockCanvas();
|
||||
if (c == null)
|
||||
return;
|
||||
|
||||
btm.copyPixelsFromBuffer(framebuffer);
|
||||
Canvas c = holder.lockCanvas(null);
|
||||
btm.copyPixelsFromBuffer(native_buf);
|
||||
synchronized (holder)
|
||||
{ /* draw */
|
||||
c.drawBitmap(btm, 0.0f, 0.0f, null);
|
||||
|
|
@ -72,16 +81,14 @@ public class RockboxFramebuffer extends SurfaceView
|
|||
holder.unlockCanvasAndPost(c);
|
||||
}
|
||||
|
||||
private void update(ByteBuffer framebuffer, Rect dirty)
|
||||
private void java_lcd_update_rect(int x, int y, int width, int height)
|
||||
{
|
||||
SurfaceHolder holder = getHolder();
|
||||
Rect dirty = new Rect(x, y, x+width, y+height);
|
||||
Canvas c = holder.lockCanvas(dirty);
|
||||
|
||||
if (c == null)
|
||||
return;
|
||||
|
||||
/* can't copy a partial buffer, but it doesn't make a noticeable difference anyway */
|
||||
btm.copyPixelsFromBuffer(framebuffer);
|
||||
/* can't copy a partial buffer,
|
||||
* but it doesn't make a noticeable difference anyway */
|
||||
btm.copyPixelsFromBuffer(native_buf);
|
||||
synchronized (holder)
|
||||
{ /* draw */
|
||||
c.drawBitmap(btm, dirty, dirty, null);
|
||||
|
|
@ -89,6 +96,11 @@ public class RockboxFramebuffer extends SurfaceView
|
|||
holder.unlockCanvasAndPost(c);
|
||||
}
|
||||
|
||||
private void LOG(CharSequence text)
|
||||
{
|
||||
Log.d("Rockbox", (String) text);
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(MotionEvent me)
|
||||
{
|
||||
int x = (int) me.getX();
|
||||
|
|
@ -137,7 +149,5 @@ public class RockboxFramebuffer extends SurfaceView
|
|||
public native void surfaceDestroyed(SurfaceHolder holder);
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
|
||||
{
|
||||
btm = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
|
||||
setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public class RockboxKeyboardInput
|
|||
{
|
||||
public void kbd_input(final String text, final String ok, final String cancel)
|
||||
{
|
||||
final Activity c = RockboxService.getInstance().getActivity();
|
||||
final Activity c = RockboxService.get_instance().get_activity();
|
||||
|
||||
c.runOnUiThread(new Runnable() {
|
||||
public void run()
|
||||
|
|
@ -74,6 +74,6 @@ public class RockboxKeyboardInput
|
|||
|
||||
public boolean is_usable()
|
||||
{
|
||||
return RockboxService.getInstance().getActivity() != null;
|
||||
return RockboxService.get_instance().get_activity() != null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
package org.rockbox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.rockbox.Helper.Logger;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
|
@ -33,6 +32,7 @@ import android.media.AudioTrack;
|
|||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Process;
|
||||
import android.util.Log;
|
||||
|
||||
public class RockboxPCM extends AudioTrack
|
||||
{
|
||||
|
|
@ -40,9 +40,13 @@ public class RockboxPCM extends AudioTrack
|
|||
private static final int samplerate = 44100;
|
||||
/* should be CHANNEL_OUT_STEREO in 2.0 and above */
|
||||
private static final int channels =
|
||||
AudioFormat.CHANNEL_OUT_STEREO;
|
||||
AudioFormat.CHANNEL_CONFIGURATION_STEREO;
|
||||
private static final int encoding =
|
||||
AudioFormat.ENCODING_PCM_16BIT;
|
||||
/* 32k is plenty, but some devices may have a higher minimum */
|
||||
private static final int buf_len =
|
||||
Math.max(32<<10, 4*getMinBufferSize(samplerate, channels, encoding));
|
||||
|
||||
private AudioManager audiomanager;
|
||||
private RockboxService rbservice;
|
||||
private byte[] raw_data;
|
||||
|
|
@ -54,24 +58,23 @@ public class RockboxPCM extends AudioTrack
|
|||
private float curpcmvolume = 0;
|
||||
private float pcmrange;
|
||||
|
||||
/* 8k is plenty, but some devices may have a higher minimum.
|
||||
* 8k represents 125ms of audio */
|
||||
private static final int chunkSize =
|
||||
Math.max(8<<10, getMinBufferSize(samplerate, channels, encoding));
|
||||
Streamer streamer;
|
||||
private void LOG(CharSequence text)
|
||||
{
|
||||
Log.d("Rockbox", (String) text);
|
||||
}
|
||||
|
||||
public RockboxPCM()
|
||||
{
|
||||
super(streamtype, samplerate, channels, encoding,
|
||||
chunkSize, AudioTrack.MODE_STREAM);
|
||||
|
||||
streamer = new Streamer(chunkSize);
|
||||
streamer.start();
|
||||
raw_data = new byte[chunkSize]; /* in shorts */
|
||||
buf_len, AudioTrack.MODE_STREAM);
|
||||
HandlerThread ht = new HandlerThread("audio thread",
|
||||
Process.THREAD_PRIORITY_URGENT_AUDIO);
|
||||
ht.start();
|
||||
raw_data = new byte[buf_len]; /* in shorts */
|
||||
Arrays.fill(raw_data, (byte) 0);
|
||||
|
||||
/* find cleaner way to get context? */
|
||||
rbservice = RockboxService.getInstance();
|
||||
rbservice = RockboxService.get_instance();
|
||||
audiomanager =
|
||||
(AudioManager) rbservice.getSystemService(Context.AUDIO_SERVICE);
|
||||
maxstreamvolume = audiomanager.getStreamMaxVolume(streamtype);
|
||||
|
|
@ -81,80 +84,14 @@ public class RockboxPCM extends AudioTrack
|
|||
|
||||
setupVolumeHandler();
|
||||
postVolume(audiomanager.getStreamVolume(streamtype));
|
||||
}
|
||||
refillmark = buf_len / 4; /* higher values don't work on many devices */
|
||||
|
||||
/**
|
||||
* This class does the actual playback work. Its run() method
|
||||
* continuously writes data to the AudioTrack. This operation blocks
|
||||
* and should therefore be run on its own thread.
|
||||
*/
|
||||
private class Streamer extends Thread
|
||||
{
|
||||
byte[] buffer;
|
||||
private boolean quit = false;
|
||||
|
||||
Streamer(int bufsize)
|
||||
{
|
||||
super("audio thread");
|
||||
buffer = new byte[bufsize];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
/* THREAD_PRIORITY_URGENT_AUDIO can only be specified via
|
||||
* setThreadPriority(), and not via thread.setPriority(). This is
|
||||
* also how the android's HandlerThread class implements it */
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
|
||||
while (!quit)
|
||||
{
|
||||
switch(getPlayState())
|
||||
{
|
||||
case PLAYSTATE_PLAYING:
|
||||
nativeWrite(buffer, buffer.length);
|
||||
break;
|
||||
case PLAYSTATE_PAUSED:
|
||||
case PLAYSTATE_STOPPED:
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
try
|
||||
{
|
||||
wait();
|
||||
}
|
||||
catch (InterruptedException e) { e.printStackTrace(); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void quit()
|
||||
{
|
||||
quit = true;
|
||||
notify();
|
||||
}
|
||||
|
||||
synchronized void kick()
|
||||
{
|
||||
notify();
|
||||
}
|
||||
|
||||
void quitAndJoin()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
try
|
||||
{
|
||||
quit();
|
||||
join();
|
||||
return;
|
||||
}
|
||||
catch (InterruptedException e) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
/* getLooper() returns null if thread isn't running */
|
||||
while(!ht.isAlive()) Thread.yield();
|
||||
setPlaybackPositionUpdateListener(
|
||||
new PCMListener(buf_len / 2), new Handler(ht.getLooper()));
|
||||
refillmark = bytes2frames(refillmark);
|
||||
}
|
||||
|
||||
private native void postVolumeChangedEvent(int volume);
|
||||
|
||||
|
|
@ -162,7 +99,7 @@ public class RockboxPCM extends AudioTrack
|
|||
{
|
||||
int rbvolume = ((maxstreamvolume - volume) * -99) /
|
||||
maxstreamvolume;
|
||||
Logger.d("java:postVolumeChangedEvent, avol "+volume+" rbvol "+rbvolume);
|
||||
LOG("java:postVolumeChangedEvent, avol "+volume+" rbvol "+rbvolume);
|
||||
postVolumeChangedEvent(rbvolume);
|
||||
}
|
||||
|
||||
|
|
@ -201,21 +138,24 @@ public class RockboxPCM extends AudioTrack
|
|||
new IntentFilter("android.media.VOLUME_CHANGED_ACTION"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private int bytes2frames(int bytes)
|
||||
{
|
||||
/* 1 sample is 2 bytes, 2 samples are 1 frame */
|
||||
return (bytes/4);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private int frames2bytes(int frames)
|
||||
{
|
||||
/* 1 frame is 2 samples, 1 sample is 2 bytes */
|
||||
return (frames*4);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void play_pause(boolean pause)
|
||||
{
|
||||
RockboxService service = RockboxService.getInstance();
|
||||
RockboxService service = RockboxService.get_instance();
|
||||
if (pause)
|
||||
{
|
||||
Intent widgetUpdate = new Intent("org.rockbox.UpdateState");
|
||||
|
|
@ -232,22 +172,14 @@ public class RockboxPCM extends AudioTrack
|
|||
service.startForeground();
|
||||
if (getPlayState() == AudioTrack.PLAYSTATE_STOPPED)
|
||||
{
|
||||
setNotificationMarkerPosition(refillmark);
|
||||
/* need to fill with silence before starting playback */
|
||||
write(raw_data, 0, raw_data.length);
|
||||
}
|
||||
play();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void play() throws IllegalStateException
|
||||
{
|
||||
super.play();
|
||||
/* when stopped or paused the streamer is in a wait() state. need
|
||||
* it to wake it up */
|
||||
streamer.kick();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized void stop() throws IllegalStateException
|
||||
{
|
||||
|
|
@ -268,27 +200,20 @@ public class RockboxPCM extends AudioTrack
|
|||
|
||||
Intent widgetUpdate = new Intent("org.rockbox.UpdateState");
|
||||
widgetUpdate.putExtra("state", "stop");
|
||||
RockboxService.getInstance().sendBroadcast(widgetUpdate);
|
||||
RockboxService.getInstance().stopForeground();
|
||||
RockboxService.get_instance().sendBroadcast(widgetUpdate);
|
||||
RockboxService.get_instance().stopForeground();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release()
|
||||
{
|
||||
super.release();
|
||||
/* stop streamer if this AudioTrack is destroyed by whomever */
|
||||
streamer.quitAndJoin();
|
||||
}
|
||||
|
||||
|
||||
public int setStereoVolume(float leftVolume, float rightVolume)
|
||||
{
|
||||
curpcmvolume = leftVolume;
|
||||
return super.setStereoVolume(leftVolume, rightVolume);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void set_volume(int volume)
|
||||
{
|
||||
Logger.d("java:set_volume("+volume+")");
|
||||
LOG("java:set_volume("+volume+")");
|
||||
/* Rockbox 'volume' is 0..-990 deci-dB attenuation.
|
||||
Android streams have rather low resolution volume control,
|
||||
typically 8 or 15 steps.
|
||||
|
|
@ -308,11 +233,47 @@ public class RockboxPCM extends AudioTrack
|
|||
|
||||
int oldstreamvolume = audiomanager.getStreamVolume(streamtype);
|
||||
if (streamvolume != oldstreamvolume) {
|
||||
Logger.d("java:setStreamVolume("+streamvolume+")");
|
||||
LOG("java:setStreamVolume("+streamvolume+")");
|
||||
setstreamvolume = streamvolume;
|
||||
audiomanager.setStreamVolume(streamtype, streamvolume, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public native int nativeWrite(byte[] temp, int len);
|
||||
|
||||
private class PCMListener implements OnPlaybackPositionUpdateListener
|
||||
{
|
||||
byte[] pcm_data;
|
||||
public PCMListener(int _refill_bufsize)
|
||||
{
|
||||
pcm_data = new byte[_refill_bufsize];
|
||||
}
|
||||
|
||||
public void onMarkerReached(AudioTrack track)
|
||||
{
|
||||
/* push new data to the hardware */
|
||||
RockboxPCM pcm = (RockboxPCM)track;
|
||||
int result = -1;
|
||||
result = pcm.nativeWrite(pcm_data, pcm_data.length);
|
||||
if (result >= 0)
|
||||
{
|
||||
switch(getPlayState())
|
||||
{
|
||||
case PLAYSTATE_PLAYING:
|
||||
case PLAYSTATE_PAUSED:
|
||||
setNotificationMarkerPosition(pcm.refillmark);
|
||||
break;
|
||||
case PLAYSTATE_STOPPED:
|
||||
LOG("Stopped");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /* stop on error */
|
||||
stop();
|
||||
}
|
||||
|
||||
public void onPeriodicNotification(AudioTrack track)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,18 +27,25 @@ import java.io.File;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import org.rockbox.Helper.Logger;
|
||||
|
||||
import org.rockbox.Helper.MediaButtonReceiver;
|
||||
import org.rockbox.Helper.RunForegroundManager;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.IBinder;
|
||||
import android.os.ResultReceiver;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
/* This class is used as the main glue between java and c.
|
||||
|
|
@ -47,17 +54,27 @@ import android.view.KeyEvent;
|
|||
|
||||
public class RockboxService extends Service
|
||||
{
|
||||
/* this Service is really a singleton class - well almost. */
|
||||
/* this Service is really a singleton class - well almost.
|
||||
* To do it properly this line should be instance = new RockboxService()
|
||||
* but apparently that doesnt work with the way android Services are created.
|
||||
*/
|
||||
private static RockboxService instance = null;
|
||||
|
||||
/* locals needed for the c code and Rockbox state */
|
||||
/* locals needed for the c code and rockbox state */
|
||||
private static volatile boolean rockbox_running;
|
||||
private Activity mCurrentActivity = null;
|
||||
private RunForegroundManager mFgRunner;
|
||||
private Activity current_activity = null;
|
||||
private IntentFilter itf;
|
||||
private IntentFilter ifh;
|
||||
private BroadcastReceiver batt_monitor;
|
||||
private BroadcastReceiver headphone_monitor;
|
||||
private BroadcastReceiver noisy_monitor;
|
||||
private RunForegroundManager fg_runner;
|
||||
private MediaButtonReceiver mMediaButtonReceiver;
|
||||
private ResultReceiver mResultReceiver;
|
||||
private int battery_level;
|
||||
private int headphone_state;
|
||||
private ResultReceiver resultReceiver;
|
||||
private RockboxService rbservice;
|
||||
|
||||
/* possible result values for intent handling */
|
||||
public static final int RESULT_INVOKING_MAIN = 0;
|
||||
public static final int RESULT_LIB_LOAD_PROGRESS = 1;
|
||||
public static final int RESULT_SERVICE_RUNNING = 3;
|
||||
|
|
@ -70,12 +87,12 @@ public class RockboxService extends Service
|
|||
{
|
||||
instance = this;
|
||||
mMediaButtonReceiver = new MediaButtonReceiver(this);
|
||||
mFgRunner = new RunForegroundManager(this);
|
||||
fg_runner = new RunForegroundManager(this);
|
||||
}
|
||||
|
||||
public static RockboxService getInstance()
|
||||
public static RockboxService get_instance()
|
||||
{
|
||||
/* don't call the constructor here, the instances are managed by
|
||||
/* don't call the construtor here, the instances are managed by
|
||||
* android, so we can't just create a new one */
|
||||
return instance;
|
||||
}
|
||||
|
|
@ -84,46 +101,43 @@ public class RockboxService extends Service
|
|||
{
|
||||
return rockbox_running;
|
||||
}
|
||||
public Activity getActivity()
|
||||
public Activity get_activity()
|
||||
{
|
||||
return mCurrentActivity;
|
||||
return current_activity;
|
||||
}
|
||||
public void set_activity(Activity a)
|
||||
{
|
||||
current_activity = a;
|
||||
}
|
||||
|
||||
public void setActivity(Activity a)
|
||||
private void do_start(Intent intent)
|
||||
{
|
||||
mCurrentActivity = a;
|
||||
}
|
||||
|
||||
private void putResult(int resultCode)
|
||||
{
|
||||
putResult(resultCode, null);
|
||||
}
|
||||
|
||||
private void putResult(int resultCode, Bundle resultData)
|
||||
{
|
||||
if (mResultReceiver != null)
|
||||
mResultReceiver.send(resultCode, resultData);
|
||||
}
|
||||
|
||||
private void doStart(Intent intent)
|
||||
{
|
||||
Logger.d("Start RockboxService (Intent: " + intent.getAction() + ")");
|
||||
LOG("Start RockboxService (Intent: " + intent.getAction() + ")");
|
||||
|
||||
if (intent.getAction().equals("org.rockbox.ResendTrackUpdateInfo"))
|
||||
{
|
||||
if (rockbox_running)
|
||||
mFgRunner.resendUpdateNotification();
|
||||
fg_runner.resendUpdateNotification();
|
||||
return;
|
||||
}
|
||||
|
||||
if (intent.hasExtra("callback"))
|
||||
mResultReceiver = (ResultReceiver) intent.getParcelableExtra("callback");
|
||||
resultReceiver = (ResultReceiver) intent.getParcelableExtra("callback");
|
||||
|
||||
if (!rockbox_running)
|
||||
startService();
|
||||
startservice();
|
||||
if (resultReceiver != null)
|
||||
resultReceiver.send(RESULT_LIB_LOADED, null);
|
||||
|
||||
if (intent.getAction().equals(Intent.ACTION_MEDIA_BUTTON))
|
||||
{
|
||||
/* give it a bit of time so we can register button presses
|
||||
* sleeping longer doesn't work here, apparently Android
|
||||
* surpresses long sleeps during intent handling */
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) { }
|
||||
|
||||
KeyEvent kev = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
|
||||
RockboxFramebuffer.buttonHandler(kev.getKeyCode(),
|
||||
kev.getAction() == KeyEvent.ACTION_DOWN);
|
||||
|
|
@ -131,26 +145,33 @@ public class RockboxService extends Service
|
|||
|
||||
/* (Re-)attach the media button receiver, in case it has been lost */
|
||||
mMediaButtonReceiver.register();
|
||||
putResult(RESULT_SERVICE_RUNNING);
|
||||
if (resultReceiver != null)
|
||||
resultReceiver.send(RESULT_SERVICE_RUNNING, null);
|
||||
|
||||
rockbox_running = true;
|
||||
}
|
||||
|
||||
private void LOG(CharSequence text)
|
||||
{
|
||||
Log.d("Rockbox", (String) text);
|
||||
}
|
||||
|
||||
private void LOG(CharSequence text, Throwable tr)
|
||||
{
|
||||
Log.d("Rockbox", (String) text, tr);
|
||||
}
|
||||
|
||||
public void onStart(Intent intent, int startId) {
|
||||
doStart(intent);
|
||||
do_start(intent);
|
||||
}
|
||||
|
||||
public int onStartCommand(Intent intent, int flags, int startId)
|
||||
{
|
||||
/* if null, then the service was most likely restarted by android
|
||||
* after getting killed for memory pressure earlier */
|
||||
if (intent == null)
|
||||
intent = new Intent("org.rockbox.ServiceRestarted");
|
||||
doStart(intent);
|
||||
return START_STICKY;
|
||||
do_start(intent);
|
||||
return 1; /* old API compatibility: 1 == START_STICKY */
|
||||
}
|
||||
|
||||
private void startService()
|
||||
private void startservice()
|
||||
{
|
||||
final Object lock = new Object();
|
||||
Thread rb = new Thread(new Runnable()
|
||||
|
|
@ -159,8 +180,13 @@ public class RockboxService extends Service
|
|||
{
|
||||
final int BUFFER = 8*1024;
|
||||
String rockboxDirPath = "/data/data/org.rockbox/app_rockbox/rockbox";
|
||||
String rockboxCreditsPath = "/data/data/org.rockbox/app_rockbox/rockbox/rocks/viewers";
|
||||
String rockboxSdDirPath = "/sdcard/rockbox";
|
||||
File rockboxDir = new File(rockboxDirPath);
|
||||
|
||||
/* load library before unzipping which may take a while */
|
||||
synchronized (lock) {
|
||||
System.loadLibrary("rockbox");
|
||||
lock.notify();
|
||||
}
|
||||
|
||||
/* the following block unzips libmisc.so, which contains the files
|
||||
* we ship, such as themes. It's needed to put it into a .so file
|
||||
|
|
@ -169,32 +195,9 @@ public class RockboxService extends Service
|
|||
*/
|
||||
File libMisc = new File("/data/data/org.rockbox/lib/libmisc.so");
|
||||
/* use arbitrary file to determine whether extracting is needed */
|
||||
File arbitraryFile = new File(rockboxCreditsPath, "credits.rock");
|
||||
File rockboxInfoFile = new File(rockboxSdDirPath, "rockbox-info.txt");
|
||||
/* unzip newer or doesnt exist */
|
||||
boolean doExtract = !arbitraryFile.exists()
|
||||
|| (libMisc.lastModified() > arbitraryFile.lastModified());
|
||||
|
||||
/* load library before unzipping which may take a while
|
||||
* but at least tell if unzipping is going to be done before*/
|
||||
synchronized (lock) {
|
||||
Bundle bdata = new Bundle();
|
||||
bdata.putBoolean("unzip", doExtract);
|
||||
System.loadLibrary("rockbox");
|
||||
putResult(RESULT_LIB_LOADED, bdata);
|
||||
lock.notify();
|
||||
}
|
||||
|
||||
if (doExtract)
|
||||
File arbitraryFile = new File(rockboxDir, "viewers.config");
|
||||
if (!arbitraryFile.exists() || (libMisc.lastModified() > arbitraryFile.lastModified()))
|
||||
{
|
||||
boolean extractToSd = false;
|
||||
if(rockboxInfoFile.exists()) {
|
||||
extractToSd = true;
|
||||
Logger.d("extracting resources to SD card");
|
||||
}
|
||||
else {
|
||||
Logger.d("extracting resources to internal memory");
|
||||
}
|
||||
try
|
||||
{
|
||||
Bundle progressData = new Bundle();
|
||||
|
|
@ -210,16 +213,7 @@ public class RockboxService extends Service
|
|||
/* strip off /.rockbox when extracting */
|
||||
String fileName = entry.getName();
|
||||
int slashIndex = fileName.indexOf('/', 1);
|
||||
/* codecs are now stored as libs, only keep rocks on internal */
|
||||
if(extractToSd == false
|
||||
|| fileName.substring(slashIndex).startsWith("/rocks"))
|
||||
{
|
||||
file = new File(rockboxDirPath + fileName.substring(slashIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
file = new File(rockboxSdDirPath + fileName.substring(slashIndex));
|
||||
}
|
||||
file = new File(rockboxDirPath + fileName.substring(slashIndex));
|
||||
|
||||
if (!entry.isDirectory())
|
||||
{
|
||||
|
|
@ -242,16 +236,19 @@ public class RockboxService extends Service
|
|||
is.close();
|
||||
}
|
||||
|
||||
progressData.putInt("value", progressData.getInt("value", 0) + 1);
|
||||
putResult(RESULT_LIB_LOAD_PROGRESS, progressData);
|
||||
if (resultReceiver != null) {
|
||||
progressData.putInt("value", progressData.getInt("value", 0) + 1);
|
||||
resultReceiver.send(RESULT_LIB_LOAD_PROGRESS, progressData);
|
||||
}
|
||||
}
|
||||
arbitraryFile.setLastModified(libMisc.lastModified());
|
||||
} catch(Exception e) {
|
||||
Logger.d("Exception when unzipping", e);
|
||||
Bundle bundle = new Bundle();
|
||||
LOG("Exception when unzipping", e);
|
||||
e.printStackTrace();
|
||||
bundle.putString("error", getString(R.string.error_extraction));
|
||||
putResult(RESULT_ERROR_OCCURED, bundle);
|
||||
if (resultReceiver != null) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("error", getString(R.string.error_extraction));
|
||||
resultReceiver.send(RESULT_ERROR_OCCURED, bundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -270,19 +267,21 @@ public class RockboxService extends Service
|
|||
strm.write("lang: /.rockbox/langs/" + getString(R.string.rockbox_language_file) + "\n");
|
||||
strm.close();
|
||||
} catch(Exception e) {
|
||||
Logger.d("Exception when writing default config", e);
|
||||
LOG("Exception when writing default config", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* Start native code */
|
||||
putResult(RESULT_INVOKING_MAIN);
|
||||
if (resultReceiver != null)
|
||||
resultReceiver.send(RESULT_INVOKING_MAIN, null);
|
||||
|
||||
main();
|
||||
|
||||
putResult(RESULT_ROCKBOX_EXIT);
|
||||
if (resultReceiver != null)
|
||||
resultReceiver.send(RESULT_ROCKBOX_EXIT, null);
|
||||
|
||||
Logger.d("Stop service: main() returned");
|
||||
stopSelf(); /* service is of no use anymore */
|
||||
LOG("Stop service: main() returned");
|
||||
stopSelf(); /* serivce is of no use anymore */
|
||||
}
|
||||
}, "Rockbox thread");
|
||||
rb.setDaemon(false);
|
||||
|
|
@ -307,17 +306,84 @@ public class RockboxService extends Service
|
|||
@Override
|
||||
public IBinder onBind(Intent intent)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void initBatteryMonitor()
|
||||
{
|
||||
itf = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
||||
batt_monitor = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
/* we get literally spammed with battery statuses
|
||||
* if we don't delay the re-attaching
|
||||
*/
|
||||
TimerTask tk = new TimerTask()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
registerReceiver(batt_monitor, itf);
|
||||
}
|
||||
};
|
||||
Timer t = new Timer();
|
||||
context.unregisterReceiver(this);
|
||||
int rawlevel = intent.getIntExtra("level", -1);
|
||||
int scale = intent.getIntExtra("scale", -1);
|
||||
if (rawlevel >= 0 && scale > 0)
|
||||
battery_level = (rawlevel * 100) / scale;
|
||||
else
|
||||
battery_level = -1;
|
||||
/* query every 30s should be sufficient */
|
||||
t.schedule(tk, 30000);
|
||||
}
|
||||
};
|
||||
registerReceiver(batt_monitor, itf);
|
||||
}
|
||||
|
||||
|
||||
private void initHeadphoneMonitor()
|
||||
{
|
||||
ifh = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
|
||||
headphone_monitor = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
int state = intent.getIntExtra("state", -1);
|
||||
LOG("headphone state:" + state);
|
||||
headphone_state = state;
|
||||
}
|
||||
};
|
||||
registerReceiver(headphone_monitor, ifh);
|
||||
noisy_monitor = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
LOG("audio becoming noisy");
|
||||
headphone_state = 0;
|
||||
}
|
||||
};
|
||||
rbservice = RockboxService.get_instance();
|
||||
/* We're relying on internal API's here,
|
||||
this can break in the future! */
|
||||
rbservice.registerReceiver(noisy_monitor,
|
||||
new IntentFilter("android.media.AUDIO_BECOMING_NOISY"));
|
||||
}
|
||||
|
||||
|
||||
void startForeground()
|
||||
{
|
||||
mFgRunner.startForeground();
|
||||
fg_runner.startForeground();
|
||||
}
|
||||
|
||||
void stopForeground()
|
||||
{
|
||||
mFgRunner.stopForeground();
|
||||
fg_runner.stopForeground();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -325,7 +391,7 @@ public class RockboxService extends Service
|
|||
{
|
||||
super.onDestroy();
|
||||
/* Don't unregister so we can receive them (and startup the service)
|
||||
* after idle power-off. Hopefully it's OK if mMediaButtonReceiver is
|
||||
* after idle poweroff. Hopefully it's ok if mMediaButtonReceiver is
|
||||
* garbage collected.
|
||||
* mMediaButtonReceiver.unregister(); */
|
||||
mMediaButtonReceiver = null;
|
||||
|
|
|
|||
97
android/src/org/rockbox/RockboxTelephony.java
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2010 Thomas Martitz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
package org.rockbox;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
public class RockboxTelephony
|
||||
{
|
||||
public RockboxTelephony(Context c)
|
||||
{
|
||||
final Handler handler = new Handler(c.getMainLooper());
|
||||
final TelephonyManager tm = (TelephonyManager)
|
||||
c.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
handler.post(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{ /* need to instantiate from a thread that has a Looper */
|
||||
tm.listen(new RockboxCallStateListener(), PhoneStateListener.LISTEN_CALL_STATE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class RockboxCallStateListener extends PhoneStateListener
|
||||
{
|
||||
private int last_state;
|
||||
|
||||
public RockboxCallStateListener()
|
||||
{
|
||||
super();
|
||||
/* set artificial initial state,
|
||||
* we will get an initial event shortly after this,
|
||||
* so to handle it correctly we need an invalid state set */
|
||||
last_state = TelephonyManager.CALL_STATE_IDLE - 10;
|
||||
}
|
||||
|
||||
private void handleState(int state)
|
||||
{
|
||||
if (state == last_state)
|
||||
return;
|
||||
switch (state)
|
||||
{
|
||||
case TelephonyManager.CALL_STATE_IDLE:
|
||||
postCallHungUp();
|
||||
break;
|
||||
case TelephonyManager.CALL_STATE_RINGING:
|
||||
postCallIncoming();
|
||||
break;
|
||||
case TelephonyManager.CALL_STATE_OFFHOOK:
|
||||
/* for incoming calls we handled at RINGING already,
|
||||
* if the previous state was IDLE then
|
||||
* this is an outgoing call
|
||||
*/
|
||||
if (last_state == TelephonyManager.CALL_STATE_IDLE)
|
||||
{ /* currently handled the same as incoming calls */
|
||||
postCallIncoming();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
last_state = state;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCallStateChanged(int state, String number)
|
||||
{
|
||||
super.onCallStateChanged(state, number);
|
||||
handleState(state);
|
||||
}
|
||||
}
|
||||
private native void postCallIncoming();
|
||||
private native void postCallHungUp();
|
||||
}
|
||||
|
|
@ -27,52 +27,40 @@ import android.content.DialogInterface;
|
|||
|
||||
public class RockboxYesno
|
||||
{
|
||||
private class Listener implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener
|
||||
{
|
||||
/* default to "No" if onClick isn't called at all */
|
||||
private boolean result = false;
|
||||
|
||||
/* called when the user presses the Yes or the No button */
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
result = (which == DialogInterface.BUTTON_POSITIVE);
|
||||
}
|
||||
|
||||
/* onDismiss is (hopefully) also called when the dialog is closed
|
||||
* for any reason other than clicking yes or no. This should
|
||||
* avoid the native code waiting for the result indefinitely in
|
||||
* case the dialog just disappears */
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog)
|
||||
{
|
||||
put_result(result);
|
||||
}
|
||||
}
|
||||
|
||||
private void yesno_display(final String text, final String yes, final String no)
|
||||
{
|
||||
final Activity c = RockboxService.getInstance().getActivity();
|
||||
final Activity c = RockboxService.get_instance().get_activity();
|
||||
|
||||
c.runOnUiThread(new Runnable() {
|
||||
public void run()
|
||||
{
|
||||
Listener l = new Listener();
|
||||
new AlertDialog.Builder(c)
|
||||
.setTitle(R.string.YesNoTitle)
|
||||
.setTitle(R.string.KbdInputTitle)
|
||||
.setIcon(R.drawable.icon)
|
||||
.setCancelable(false)
|
||||
.setMessage(text)
|
||||
.setPositiveButton(yes, l)
|
||||
.setNegativeButton(no, l)
|
||||
.show()
|
||||
.setOnDismissListener(l);
|
||||
.setPositiveButton(yes, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int whichButton)
|
||||
{
|
||||
put_result(true);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(no, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int whichButton)
|
||||
{
|
||||
put_result(false);
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean is_usable()
|
||||
{
|
||||
return RockboxService.getInstance().getActivity() != null;
|
||||
return RockboxService.get_instance().get_activity() != null;
|
||||
}
|
||||
|
||||
private native void put_result(boolean result);
|
||||
|
|
|
|||
|
|
@ -1,74 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2011 Thomas Martitz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
package org.rockbox.monitors;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
|
||||
public class BatteryMonitor extends BroadcastReceiver
|
||||
{
|
||||
private final IntentFilter mBattFilter;
|
||||
private final Context mContext;
|
||||
@SuppressWarnings("unused")
|
||||
private int mBattLevel; /* read by native code */
|
||||
|
||||
/*
|
||||
* We get literally spammed with battery status updates
|
||||
* Therefore we actually unregister after each onReceive() and
|
||||
* setup a timer to re-register in 30s */
|
||||
public BatteryMonitor(Context c)
|
||||
{
|
||||
mBattFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
||||
mContext = c;
|
||||
Timer t = new Timer();
|
||||
TimerTask task = new TimerTask()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
attach();
|
||||
}
|
||||
};
|
||||
t.schedule(task, 5000, 30000);
|
||||
attach();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context arg0, Intent intent)
|
||||
{
|
||||
int rawlevel = intent.getIntExtra("level", -1);
|
||||
int scale = intent.getIntExtra("scale", -1);
|
||||
if (rawlevel >= 0 && scale > 0)
|
||||
mBattLevel = (rawlevel * 100) / scale;
|
||||
else
|
||||
mBattLevel = -1;
|
||||
mContext.unregisterReceiver(this);
|
||||
}
|
||||
|
||||
void attach()
|
||||
{
|
||||
mContext.registerReceiver(this, mBattFilter);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2011 Thomas Martitz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
package org.rockbox.monitors;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
|
||||
public class HeadphoneMonitor extends BroadcastReceiver
|
||||
{
|
||||
public HeadphoneMonitor(Context c)
|
||||
{
|
||||
IntentFilter hpFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
|
||||
/* caution: hidden API; might break */
|
||||
IntentFilter noisyFilter = new IntentFilter("android.media.AUDIO_BECOMING_NOISY");
|
||||
|
||||
c.registerReceiver(this, hpFilter);
|
||||
c.registerReceiver(new NoisyMonitor(), noisyFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context arg0, Intent intent)
|
||||
{
|
||||
int state = intent.getIntExtra("state", -1);
|
||||
postHpStateChanged(state);
|
||||
}
|
||||
|
||||
/* audio becoming noise acts as headphones extracted */
|
||||
private class NoisyMonitor extends BroadcastReceiver
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context arg0, Intent arg1)
|
||||
{
|
||||
postHpStateChanged(0);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized native void postHpStateChanged(int state);
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2010 Thomas Martitz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
package org.rockbox.monitors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
public class TelephonyMonitor
|
||||
{
|
||||
public TelephonyMonitor(Context c)
|
||||
{
|
||||
final Handler handler = new Handler(c.getMainLooper());
|
||||
final TelephonyManager tm = (TelephonyManager)
|
||||
c.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
handler.post(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{ /* need to instantiate from a thread that has a Looper */
|
||||
tm.listen(new RockboxCallStateListener(), PhoneStateListener.LISTEN_CALL_STATE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class RockboxCallStateListener extends PhoneStateListener
|
||||
{
|
||||
private int last_state;
|
||||
|
||||
public RockboxCallStateListener()
|
||||
{
|
||||
super();
|
||||
/* set artificial initial state,
|
||||
* we will get an initial event shortly after this,
|
||||
* so to handle it correctly we need an invalid state set */
|
||||
last_state = TelephonyManager.CALL_STATE_IDLE - 10;
|
||||
}
|
||||
|
||||
private void handleState(int state)
|
||||
{
|
||||
if (state == last_state)
|
||||
return;
|
||||
switch (state)
|
||||
{
|
||||
case TelephonyManager.CALL_STATE_IDLE:
|
||||
postCallHungUp();
|
||||
break;
|
||||
case TelephonyManager.CALL_STATE_RINGING:
|
||||
postCallIncoming();
|
||||
break;
|
||||
case TelephonyManager.CALL_STATE_OFFHOOK:
|
||||
/* for incoming calls we handled at RINGING already,
|
||||
* if the previous state was IDLE then
|
||||
* this is an outgoing call
|
||||
*/
|
||||
if (last_state == TelephonyManager.CALL_STATE_IDLE)
|
||||
{ /* currently handled the same as incoming calls */
|
||||
postCallIncoming();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
last_state = state;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCallStateChanged(int state, String number)
|
||||
{
|
||||
super.onCallStateChanged(state, number);
|
||||
handleState(state);
|
||||
}
|
||||
}
|
||||
private native void postCallIncoming();
|
||||
private native void postCallHungUp();
|
||||
}
|
||||
172
apps/SOURCES
|
|
@ -7,7 +7,6 @@ alarm_menu.c
|
|||
#endif
|
||||
abrepeat.c
|
||||
bookmark.c
|
||||
core_keymap.c
|
||||
debug_menu.c
|
||||
filetypes.c
|
||||
language.c
|
||||
|
|
@ -20,13 +19,17 @@ menus/plugin_menu.c
|
|||
#if CONFIG_TUNER
|
||||
menus/radio_menu.c
|
||||
#endif
|
||||
#if CONFIG_CODEC == SWCODEC
|
||||
#ifdef HAVE_WM8978
|
||||
menus/audiohw_eq_menu.c
|
||||
#endif
|
||||
menus/eq_menu.c
|
||||
buffering.c
|
||||
voice_thread.c
|
||||
rbcodec_helpers.c
|
||||
replaygain.c
|
||||
#else /* !SWCODEC */
|
||||
mpeg.c
|
||||
#endif
|
||||
menus/main_menu.c
|
||||
menus/playback_menu.c
|
||||
menus/playlist_menu.c
|
||||
|
|
@ -39,7 +42,7 @@ menus/sound_menu.c
|
|||
menus/time_menu.c
|
||||
#endif
|
||||
misc.c
|
||||
open_plugin.c
|
||||
mp3data.c
|
||||
onplay.c
|
||||
playlist.c
|
||||
playlist_catalog.c
|
||||
|
|
@ -49,7 +52,6 @@ root_menu.c
|
|||
screens.c
|
||||
settings.c
|
||||
settings_list.c
|
||||
shortcuts.c
|
||||
status.c
|
||||
cuesheet.c
|
||||
talk.c
|
||||
|
|
@ -58,42 +60,39 @@ tree.c
|
|||
tagtree.c
|
||||
#endif
|
||||
filetree.c
|
||||
scrobbler.c
|
||||
#ifdef IPOD_ACCESSORY_PROTOCOL
|
||||
iap/iap-core.c
|
||||
iap/iap-lingo0.c
|
||||
#ifdef HAVE_LINE_REC
|
||||
iap/iap-lingo1.c
|
||||
#endif
|
||||
iap/iap-lingo2.c
|
||||
iap/iap-lingo3.c
|
||||
iap/iap-lingo4.c
|
||||
#if CONFIG_TUNER
|
||||
iap/iap-lingo7.c
|
||||
#endif
|
||||
iap.c
|
||||
#endif
|
||||
|
||||
screen_access.c
|
||||
#ifdef HAVE_BUTTONBAR
|
||||
gui/buttonbar.c
|
||||
#endif
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
gui/icon.c
|
||||
#endif
|
||||
gui/list.c
|
||||
gui/line.c
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
gui/bitmap/list.c
|
||||
gui/bitmap/list-skinned.c
|
||||
#else
|
||||
gui/charcell/list.c
|
||||
#endif
|
||||
gui/option_select.c
|
||||
#ifdef HAVE_PITCHCONTROL
|
||||
#ifdef HAVE_PITCHSCREEN
|
||||
gui/pitchscreen.c
|
||||
#endif
|
||||
#ifdef HAVE_QUICKSCREEN
|
||||
gui/quickscreen.c
|
||||
#endif
|
||||
gui/folder_select.c
|
||||
#if defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD)
|
||||
gui/mask_select.c
|
||||
#endif
|
||||
|
||||
gui/wps.c
|
||||
gui/scrollbar.c
|
||||
gui/splash.c
|
||||
gui/statusbar.c
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
gui/statusbar-skinned.c
|
||||
#endif
|
||||
#if (CONFIG_PLATFORM&PLATFORM_ANDROID)
|
||||
hosted/android/yesno.c
|
||||
hosted/android/notification.c
|
||||
|
|
@ -105,6 +104,9 @@ gui/viewport.c
|
|||
gui/skin_engine/skin_backdrops.c
|
||||
gui/skin_engine/skin_display.c
|
||||
gui/skin_engine/skin_engine.c
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
gui/skin_engine/skin_fonts.c
|
||||
#endif
|
||||
gui/skin_engine/skin_parser.c
|
||||
gui/skin_engine/skin_render.c
|
||||
gui/skin_engine/skin_tokens.c
|
||||
|
|
@ -116,6 +118,11 @@ gui/skin_engine/skin_touchsupport.c
|
|||
gui/backdrop.c
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LCD_CHARCELLS
|
||||
player/icons.c
|
||||
player/keyboard.c
|
||||
#endif
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
recorder/bmp.c
|
||||
recorder/icons.c
|
||||
#if (CONFIG_PLATFORM&PLATFORM_ANDROID)
|
||||
|
|
@ -139,7 +146,7 @@ recorder/albumart.c
|
|||
#ifdef HAVE_LCD_COLOR
|
||||
gui/color_picker.c
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#ifdef HAVE_RECORDING
|
||||
recorder/recording.c
|
||||
#endif
|
||||
|
|
@ -153,27 +160,71 @@ radio/radioart.c
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_CODEC == SWCODEC
|
||||
#if INPUT_SRC_CAPS != 0
|
||||
audio_path.c
|
||||
#endif /* INPUT_SRC_CAPS != 0 */
|
||||
audio_thread.c
|
||||
fixedpoint.c
|
||||
pcmbuf.c
|
||||
codec_thread.c
|
||||
playback.c
|
||||
codecs.c
|
||||
#ifndef HAVE_HARDWARE_BEEP
|
||||
beep.c
|
||||
dsp.c
|
||||
#ifdef HAVE_PITCHSCREEN
|
||||
tdspeed.c
|
||||
#endif
|
||||
#ifdef HAVE_RECORDING
|
||||
enc_config.c
|
||||
recorder/pcm_record.c
|
||||
#endif
|
||||
eq.c
|
||||
#if defined(CPU_COLDFIRE)
|
||||
dsp_cf.S
|
||||
eq_cf.S
|
||||
#elif defined(CPU_ARM)
|
||||
dsp_arm.S
|
||||
#if ARM_ARCH >= 6
|
||||
dsp_arm_v6.S
|
||||
#endif
|
||||
eq_arm.S
|
||||
#endif
|
||||
#endif
|
||||
#ifdef USB_ENABLE_HID
|
||||
usb_keymaps.c
|
||||
#endif
|
||||
#ifndef USB_NONE
|
||||
gui/usb_screen.c
|
||||
#endif
|
||||
metadata.c
|
||||
metadata/id3tags.c
|
||||
metadata/mp3.c
|
||||
#if CONFIG_CODEC == SWCODEC
|
||||
metadata/metadata_common.c
|
||||
metadata/aiff.c
|
||||
metadata/ape.c
|
||||
metadata/asf.c
|
||||
metadata/adx.c
|
||||
metadata/flac.c
|
||||
metadata/monkeys.c
|
||||
metadata/mp4.c
|
||||
metadata/mpc.c
|
||||
metadata/ogg.c
|
||||
metadata/sid.c
|
||||
metadata/mod.c
|
||||
metadata/spc.c
|
||||
metadata/vorbis.c
|
||||
metadata/wave.c
|
||||
metadata/wavpack.c
|
||||
metadata/a52.c
|
||||
metadata/asap.c
|
||||
metadata/rm.c
|
||||
metadata/nsf.c
|
||||
metadata/oma.c
|
||||
metadata/smaf.c
|
||||
metadata/au.c
|
||||
metadata/vox.c
|
||||
metadata/tta.c
|
||||
#endif
|
||||
#ifdef HAVE_TAGCACHE
|
||||
tagcache.c
|
||||
#endif
|
||||
|
|
@ -187,6 +238,12 @@ keymaps/keymap-h1x0_h3x0.c
|
|||
|| (CONFIG_KEYPAD == IPOD_3G_PAD) \
|
||||
|| (CONFIG_KEYPAD == IPOD_1G2G_PAD))
|
||||
keymaps/keymap-ipod.c
|
||||
#elif CONFIG_KEYPAD == RECORDER_PAD
|
||||
keymaps/keymap-recorder.c
|
||||
#elif CONFIG_KEYPAD == ONDIO_PAD
|
||||
keymaps/keymap-ondio.c
|
||||
#elif CONFIG_KEYPAD == PLAYER_PAD
|
||||
keymaps/keymap-player.c
|
||||
#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
|
||||
keymaps/keymap-x5.c
|
||||
#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
|
||||
|
|
@ -197,6 +254,8 @@ keymaps/keymap-gigabeat.c
|
|||
keymaps/keymap-gigabeat-s.c
|
||||
#elif CONFIG_KEYPAD == IRIVER_H10_PAD
|
||||
keymaps/keymap-h10.c
|
||||
#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
|
||||
keymaps/keymap-ifp7xx.c
|
||||
#elif CONFIG_KEYPAD == SANSA_E200_PAD
|
||||
keymaps/keymap-e200.c
|
||||
#elif CONFIG_KEYPAD == SANSA_C200_PAD
|
||||
|
|
@ -205,6 +264,8 @@ keymaps/keymap-c200.c
|
|||
keymaps/keymap-m200.c
|
||||
#elif CONFIG_KEYPAD == SANSA_CLIP_PAD
|
||||
keymaps/keymap-clip.c
|
||||
#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
|
||||
keymaps/keymap-av300.c
|
||||
#elif CONFIG_KEYPAD == MROBE500_PAD
|
||||
keymaps/keymap-mr500.c
|
||||
#elif CONFIG_KEYPAD == MROBE100_PAD
|
||||
|
|
@ -219,16 +280,18 @@ keymaps/keymap-meizu-m6sp.c
|
|||
keymaps/keymap-creativezvm.c
|
||||
#elif CONFIG_KEYPAD == CREATIVEZV_PAD
|
||||
keymaps/keymap-creativezv.c
|
||||
#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD
|
||||
keymaps/keymap-zenxfi2.c
|
||||
#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD
|
||||
keymaps/keymap-zenxfi3.c
|
||||
#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
|
||||
keymaps/keymap-sa9200.c
|
||||
#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
|
||||
keymaps/keymap-hdd1630.c
|
||||
#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
|
||||
keymaps/keymap-hdd6330.c
|
||||
#elif CONFIG_KEYPAD == IAUDIO67_PAD
|
||||
keymaps/keymap-iaudio67.c
|
||||
#elif CONFIG_KEYPAD == SANSA_C100_PAD
|
||||
keymaps/keymap-c100.c
|
||||
#elif CONFIG_KEYPAD == LOGIK_DAX_PAD
|
||||
keymaps/keymap-logikdax.c
|
||||
#elif CONFIG_KEYPAD == SANSA_FUZE_PAD
|
||||
keymaps/keymap-fuze.c
|
||||
#elif CONFIG_KEYPAD == ONDAVX747_PAD
|
||||
|
|
@ -237,8 +300,7 @@ keymaps/keymap-ondavx747.c
|
|||
keymaps/keymap-ondavx777.c
|
||||
#elif CONFIG_KEYPAD == ONDAVX767_PAD
|
||||
keymaps/keymap-ondavx767.c
|
||||
#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) \
|
||||
|| (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD)
|
||||
#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
|
||||
keymaps/keymap-yh8xx_yh9xx.c
|
||||
#elif CONFIG_KEYPAD == MINI2440_PAD
|
||||
keymaps/keymap-mini2440.c
|
||||
|
|
@ -252,50 +314,4 @@ keymaps/keymap-mpio-hd300.c
|
|||
keymaps/keymap-android.c
|
||||
#elif CONFIG_KEYPAD == SDL_PAD
|
||||
keymaps/keymap-sdl.c
|
||||
#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
|
||||
keymaps/keymap-fuzeplus.c
|
||||
#elif CONFIG_KEYPAD == RK27XX_GENERIC_PAD
|
||||
keymaps/keymap-rk27xx-generic.c
|
||||
#elif CONFIG_KEYPAD == HM60X_PAD
|
||||
keymaps/keymap-hm60x.c
|
||||
#elif CONFIG_KEYPAD == HM801_PAD
|
||||
keymaps/keymap-hm801.c
|
||||
#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
|
||||
keymaps/keymap-sansa-connect.c
|
||||
#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
|
||||
keymaps/keymap-ypr0.c
|
||||
#elif CONFIG_KEYPAD == CREATIVE_ZEN_PAD
|
||||
keymaps/keymap-zen.c
|
||||
#elif CONFIG_KEYPAD == MA_PAD
|
||||
keymaps/keymap-ma.c
|
||||
#elif CONFIG_KEYPAD == SONY_NWZ_PAD
|
||||
keymaps/keymap-nwz.c
|
||||
#elif CONFIG_KEYPAD == SONY_NWZA860_PAD
|
||||
keymaps/keymap-nwza860.c
|
||||
#elif CONFIG_KEYPAD == IHIFI_PAD
|
||||
keymaps/keymap-ihifi.c
|
||||
#elif CONFIG_KEYPAD == IHIFI_770_PAD
|
||||
keymaps/keymap-ihifi770.c
|
||||
#elif CONFIG_KEYPAD == IHIFI_800_PAD
|
||||
keymaps/keymap-ihifi800.c
|
||||
#elif CONFIG_KEYPAD == SAMSUNG_YPR1_PAD
|
||||
keymaps/keymap-ypr1.c
|
||||
#elif CONFIG_KEYPAD == DX50_PAD
|
||||
keymaps/keymap-dx50.c
|
||||
#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD
|
||||
keymaps/keymap-agptekrocker.c
|
||||
#elif CONFIG_KEYPAD == XDUOO_X3_PAD
|
||||
keymaps/keymap-xduoox3.c
|
||||
#elif CONFIG_KEYPAD == XDUOO_X3II_PAD
|
||||
keymaps/keymap-xduoox3ii.c
|
||||
#elif CONFIG_KEYPAD == XDUOO_X20_PAD
|
||||
keymaps/keymap-xduoox20.c
|
||||
#elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD
|
||||
keymaps/keymap-fiiom3klinux.c
|
||||
#elif CONFIG_KEYPAD == FIIO_M3K_PAD
|
||||
keymaps/keymap-fiiom3k.c
|
||||
#elif CONFIG_KEYPAD == EROSQ_PAD
|
||||
keymaps/keymap-erosq.c
|
||||
#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
|
||||
keymaps/keymap-shanlingq1.c
|
||||
#endif
|
||||
|
|
|
|||
111
apps/abrepeat.c
|
|
@ -27,7 +27,6 @@
|
|||
unsigned int ab_A_marker IDATA_ATTR = AB_MARKER_NONE;
|
||||
unsigned int ab_B_marker IDATA_ATTR = AB_MARKER_NONE;
|
||||
|
||||
|
||||
static inline bool ab_A_marker_set(void)
|
||||
{
|
||||
return ab_A_marker != AB_MARKER_NONE;
|
||||
|
|
@ -38,7 +37,7 @@ static inline bool ab_B_marker_set(void)
|
|||
return ab_B_marker != AB_MARKER_NONE;
|
||||
}
|
||||
|
||||
|
||||
#if (CONFIG_CODEC == SWCODEC)
|
||||
void ab_end_of_track_report(void)
|
||||
{
|
||||
if ( ab_A_marker_set() && ! ab_B_marker_set() )
|
||||
|
|
@ -46,6 +45,38 @@ void ab_end_of_track_report(void)
|
|||
ab_jump_to_A_marker();
|
||||
}
|
||||
}
|
||||
#else
|
||||
static int ab_audio_event_handler(unsigned short event, unsigned long data)
|
||||
{
|
||||
int rc = AUDIO_EVENT_RC_IGNORED;
|
||||
if ( ab_repeat_mode_enabled() )
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case AUDIO_EVENT_POS_REPORT:
|
||||
{
|
||||
if ( ! (audio_status() & AUDIO_STATUS_PAUSE) &&
|
||||
ab_reached_B_marker(data) )
|
||||
{
|
||||
ab_jump_to_A_marker();
|
||||
rc = AUDIO_EVENT_RC_HANDLED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AUDIO_EVENT_END_OF_TRACK:
|
||||
{
|
||||
if ( ab_A_marker_set() && ! ab_B_marker_set() )
|
||||
{
|
||||
ab_jump_to_A_marker();
|
||||
rc = AUDIO_EVENT_RC_HANDLED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ab_repeat_init(void)
|
||||
{
|
||||
|
|
@ -53,6 +84,10 @@ void ab_repeat_init(void)
|
|||
if ( ! ab_initialized )
|
||||
{
|
||||
ab_initialized = true;
|
||||
#if (CONFIG_CODEC != SWCODEC)
|
||||
audio_register_event_handler(ab_audio_event_handler,
|
||||
AUDIO_EVENT_POS_REPORT | AUDIO_EVENT_END_OF_TRACK );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +114,16 @@ reasonable amount of time for the typical user to react */
|
|||
|
||||
void ab_jump_to_A_marker(void)
|
||||
{
|
||||
#if (CONFIG_CODEC != SWCODEC)
|
||||
bool paused = (audio_status() & AUDIO_STATUS_PAUSE) != 0;
|
||||
if ( ! paused )
|
||||
audio_pause();
|
||||
#endif
|
||||
audio_ff_rewind(ab_A_marker);
|
||||
#if (CONFIG_CODEC != SWCODEC)
|
||||
if ( ! paused )
|
||||
audio_resume();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ab_reset_markers(void)
|
||||
|
|
@ -114,16 +158,67 @@ void ab_set_B_marker(unsigned int song_position)
|
|||
ab_A_marker = AB_MARKER_NONE;
|
||||
}
|
||||
|
||||
bool ab_get_A_marker(unsigned *song_position)
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
|
||||
static int ab_calc_mark_x_pos(int mark, int capacity,
|
||||
int offset, int size)
|
||||
{
|
||||
*song_position = ab_A_marker;
|
||||
return ab_A_marker_set();
|
||||
return offset + ( (size * mark) / capacity );
|
||||
}
|
||||
|
||||
bool ab_get_B_marker(unsigned *song_position)
|
||||
static void ab_draw_vertical_line_mark(struct screen * screen,
|
||||
int x, int y, int h)
|
||||
{
|
||||
*song_position = ab_B_marker;
|
||||
return ab_B_marker_set();
|
||||
screen->set_drawmode(DRMODE_COMPLEMENT);
|
||||
screen->vline(x, y, y+h-1);
|
||||
}
|
||||
|
||||
#define DIRECTION_RIGHT 1
|
||||
#define DIRECTION_LEFT -1
|
||||
|
||||
static void ab_draw_arrow_mark(struct screen * screen,
|
||||
int x, int y, int h, int direction)
|
||||
{
|
||||
/* draw lines in decreasing size until a height of zero is reached */
|
||||
screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
||||
while( h > 0 )
|
||||
{
|
||||
screen->vline(x, y, y+h-1);
|
||||
h -= 2;
|
||||
y++;
|
||||
x += direction;
|
||||
screen->set_drawmode(DRMODE_COMPLEMENT);
|
||||
}
|
||||
}
|
||||
|
||||
void ab_draw_markers(struct screen * screen, int capacity,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
int xa = ab_calc_mark_x_pos(ab_A_marker, capacity, x, w);
|
||||
int xb = ab_calc_mark_x_pos(ab_B_marker, capacity, x, w);
|
||||
/* if both markers are set, determine if they're far enough apart
|
||||
to draw arrows */
|
||||
if ( ab_A_marker_set() && ab_B_marker_set() )
|
||||
{
|
||||
int arrow_width = (h+1) / 2;
|
||||
if ( (xb-xa) < (arrow_width*2) )
|
||||
{
|
||||
ab_draw_vertical_line_mark(screen, xa, y, h);
|
||||
ab_draw_vertical_line_mark(screen, xb, y, h);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ab_A_marker_set())
|
||||
{
|
||||
ab_draw_arrow_mark(screen, xa, y, h, DIRECTION_RIGHT);
|
||||
}
|
||||
if (ab_B_marker_set())
|
||||
{
|
||||
ab_draw_arrow_mark(screen, xb, y, h, DIRECTION_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_LCD_BITMAP */
|
||||
|
||||
#endif /* AB_REPEAT_ENABLE */
|
||||
|
|
|
|||
|
|
@ -20,38 +20,9 @@
|
|||
****************************************************************************/
|
||||
#ifndef _ABREPEAT_H_
|
||||
#define _ABREPEAT_H_
|
||||
|
||||
#ifdef AB_REPEAT_ENABLE
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef AB_REPEAT_ENABLE /* Dummy functions */
|
||||
static inline bool ab_repeat_mode_enabled(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline bool ab_bool_dummy_marker(unsigned int song_position)
|
||||
{
|
||||
(void) song_position;
|
||||
return false;
|
||||
}
|
||||
static inline void ab_void_dummy_marker(unsigned int song_position)
|
||||
{
|
||||
(void) song_position;
|
||||
}
|
||||
static inline void ab_dummy_voidfn(void){}
|
||||
|
||||
#define ab_repeat_init ab_dummy_voidfn
|
||||
#define ab_before_A_marker ab_bool_dummy_marker
|
||||
#define ab_after_A_marker ab_bool_dummy_marker
|
||||
#define ab_jump_to_A_marker ab_dummy_voidfn
|
||||
#define ab_reset_markers ab_dummy_voidfn
|
||||
#define ab_set_A_marker ab_void_dummy_marker
|
||||
#define ab_set_B_marker ab_void_dummy_marker
|
||||
#define ab_get_A_marker ab_bool_dummy_marker
|
||||
#define ab_get_B_marker ab_bool_dummy_marker
|
||||
#define ab_end_of_track_report ab_dummy_voidfn
|
||||
#define ab_reached_B_marker ab_bool_dummy_marker
|
||||
#define ab_position_report ab_void_dummy_marker
|
||||
|
||||
#else /*def AB_REPEAT_ENABLE*/
|
||||
#include "audio.h"
|
||||
#include "kernel.h" /* needed for HZ */
|
||||
|
||||
|
|
@ -66,11 +37,14 @@ void ab_jump_to_A_marker(void);
|
|||
void ab_reset_markers(void);
|
||||
void ab_set_A_marker(unsigned int song_position);
|
||||
void ab_set_B_marker(unsigned int song_position);
|
||||
/* These return whether the marker are actually set.
|
||||
* The actual positions are returned via output parameter */
|
||||
bool ab_get_A_marker(unsigned int *song_position);
|
||||
bool ab_get_B_marker(unsigned int *song_position);
|
||||
#if (CONFIG_CODEC == SWCODEC)
|
||||
void ab_end_of_track_report(void);
|
||||
#endif
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
#include "screen_access.h"
|
||||
void ab_draw_markers(struct screen * screen, int capacity,
|
||||
int x, int y, int w, int h);
|
||||
#endif
|
||||
|
||||
/* These functions really need to be inlined for speed */
|
||||
extern unsigned int ab_A_marker;
|
||||
|
|
@ -86,9 +60,16 @@ static inline bool ab_reached_B_marker(unsigned int song_position)
|
|||
/* following is the size of the window in which we'll detect that the B marker
|
||||
was hit; it must be larger than the frequency (in milliseconds) at which this
|
||||
function is called otherwise detection of the B marker will be unreliable */
|
||||
#if (CONFIG_CODEC == SWCODEC)
|
||||
/* On swcodec, the worst case seems to be 9600kHz with 1024 samples between
|
||||
* calls, meaning ~9 calls per second, look within 1/5 of a second */
|
||||
#define B_MARKER_DETECT_WINDOW 200
|
||||
#else
|
||||
/* we assume that this function will be called on each system tick and derive
|
||||
the window size from this with a generous margin of error (note: the number
|
||||
of ticks per second is given by HZ) */
|
||||
#define B_MARKER_DETECT_WINDOW ((1000/HZ)*10)
|
||||
#endif
|
||||
if (ab_B_marker != AB_MARKER_NONE)
|
||||
{
|
||||
if ( (song_position >= ab_B_marker)
|
||||
|
|
@ -98,6 +79,7 @@ function is called otherwise detection of the B marker will be unreliable */
|
|||
return false;
|
||||
}
|
||||
|
||||
#if (CONFIG_CODEC == SWCODEC)
|
||||
static inline void ab_position_report(unsigned long position)
|
||||
{
|
||||
if (ab_repeat_mode_enabled())
|
||||
|
|
@ -109,6 +91,7 @@ static inline void ab_position_report(unsigned long position)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
1581
apps/action.c
212
apps/action.h
|
|
@ -28,99 +28,50 @@
|
|||
#define TIMEOUT_NOBLOCK 0
|
||||
|
||||
#define CONTEXT_STOPSEARCHING 0xFFFFFFFF
|
||||
|
||||
#define CONTEXT_REMOTE 0x80000000 /* | this against another context to get remote buttons for that context */
|
||||
#define CONTEXT_CUSTOM 0x40000000 /* | this against anything to get your context number */
|
||||
#define CONTEXT_CUSTOM2 0x20000000 /* as above */
|
||||
#define CONTEXT_PLUGIN 0x10000000 /* for plugins using get_custom_action */
|
||||
#define CONTEXT_REMAPPED 0x08000000 /* marker for key remap context table */
|
||||
#define CORE_CONTEXT_REMAP(context) (CONTEXT_REMAPPED | context)
|
||||
#define CONTEXT_LOCKED 0x04000000 /* flag to use alternate keymap when screen is locked */
|
||||
|
||||
|
||||
#define LAST_ITEM_IN_LIST { CONTEXT_STOPSEARCHING, BUTTON_NONE, BUTTON_NONE }
|
||||
#define LAST_ITEM_IN_LIST__NEXTLIST(a) { a, BUTTON_NONE, BUTTON_NONE }
|
||||
|
||||
#if !defined(HAS_BUTTON_HOLD)
|
||||
#ifndef HAS_BUTTON_HOLD
|
||||
#define ALLOW_SOFTLOCK 0x08000000 /* will be stripped.. never needed except in calls to get_action() */
|
||||
#else
|
||||
#define ALLOW_SOFTLOCK 0
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD)
|
||||
/* Selective action selection flags */
|
||||
#define SEL_ACTION_NONE 0
|
||||
#define SEL_ACTION_VOL 0x001U
|
||||
#define SEL_ACTION_PLAY 0x002U
|
||||
#define SEL_ACTION_SEEK 0x004U
|
||||
#define SEL_ACTION_SKIP 0x008U
|
||||
#define SEL_ACTION_NOUNMAPPED 0x010U/* disable backlight on unmapped buttons */
|
||||
#define SEL_ACTION_ALLNONOTIFY 0x020U/* disable switch for all softlock notifications */
|
||||
#define SEL_ACTION_ALWAYSAUTOLOCK 0x040U/* always prime autolock, requires autolock enabled */
|
||||
#define SEL_ACTION_NOTOUCH 0x080U/* disable touch screen/pad on screen lock */
|
||||
#define SEL_ACTION_AUTOLOCK 0x100U/* autolock on backlight off */
|
||||
#define SEL_ACTION_NOEXT 0x200U/* disable selective backlight while charge*/
|
||||
#define SEL_ACTION_NONOTIFY 0x200U/* don't notify user softlock is active */
|
||||
/* Flags below are internal to selective functions */
|
||||
#define SEL_ACTION_ALOCK_OK 0x400U/*autolock only active after key lock once*/
|
||||
#define SEL_ACTION_FFKEYPRESS 0x400U/* backlight Filter First Keypress active*/
|
||||
#define SEL_ACTION_ENABLED 0x800U
|
||||
/* Selective Actions flags */
|
||||
|
||||
#if !defined(HAS_BUTTON_HOLD)
|
||||
/* returns true if keys_locked and screen_has_lock */
|
||||
bool is_keys_locked(void);
|
||||
|
||||
/* Enable selected actions to bypass a locked state
|
||||
* mask is combination of Selective action selection flags */
|
||||
void set_selective_softlock_actions(bool selective, unsigned int mask);
|
||||
|
||||
/* search the standard and wps contexts for ACTION_STD_KEYLOCK,
|
||||
* load it into unlock_combo if we find it,
|
||||
* also arm autolock if enabled. */
|
||||
void action_autosoftlock_init(void);
|
||||
|
||||
#endif /* !defined(HAS_BUTTON_HOLD) */
|
||||
|
||||
#if defined(HAVE_BACKLIGHT)
|
||||
/* Enable selected actions to leave the backlight off
|
||||
* mask is combination of Selective action selection flags */
|
||||
void set_selective_backlight_actions(bool selective, unsigned int mask,
|
||||
bool filter_fkp);
|
||||
#endif
|
||||
|
||||
#endif /* defined(HAVE_BACKLIGHT) || !defined(HAS_BUTTON_HOLD) */
|
||||
|
||||
enum {
|
||||
CONTEXT_STD = 0,
|
||||
/* These CONTEXT_ values were here before me,
|
||||
their values may have significance, so dont touch! */
|
||||
there values may have significance, so dont touch! */
|
||||
CONTEXT_WPS = 1,
|
||||
CONTEXT_TREE = 2,
|
||||
CONTEXT_TREE = 2,
|
||||
CONTEXT_RECORD = 3,
|
||||
CONTEXT_MAINMENU = 4, /* uses CONTEXT_TREE and ACTION_TREE_* */
|
||||
CONTEXT_ID3DB = 5,
|
||||
/* Add new contexts here, no need to explicitly define a value for them */
|
||||
/* Add new contexts here, no need to explicitly define a value for them */
|
||||
CONTEXT_LIST,
|
||||
CONTEXT_SETTINGS, /* regular setting screens (and debug screens) */
|
||||
/* bellow are setting screens which may need to redefine the standard
|
||||
/* bellow are setting screens which may need to redefine the standard
|
||||
setting screen keys, targets should return the CONTEXT_SETTINGS
|
||||
keymap unless they are not adequate for the screen
|
||||
NOTE: uses ACTION_STD_[NEXT|PREV] so make sure they are there also
|
||||
NOTE: uses ACTION_STD_[NEXT|PREV] so make sure they are there also
|
||||
and (possibly) ACTION_SETTINGS_[INC|DEC] */
|
||||
CONTEXT_SETTINGS_EQ,
|
||||
CONTEXT_SETTINGS_COLOURCHOOSER,
|
||||
CONTEXT_SETTINGS_TIME,
|
||||
CONTEXT_SETTINGS_EQ,
|
||||
CONTEXT_SETTINGS_COLOURCHOOSER,
|
||||
CONTEXT_SETTINGS_TIME,
|
||||
CONTEXT_SETTINGS_RECTRIGGER,
|
||||
|
||||
|
||||
/* The following contexts should use ACTION_STD_[NEXT|PREV]
|
||||
and (possibly) ACTION_SETTINGS_[INC|DEC]
|
||||
and (possibly) ACTION_SETTINGS_[INC|DEC]
|
||||
Also add any extra actions they need */
|
||||
CONTEXT_BOOKMARKSCREEN, /* uses ACTION_BMS_ defines */
|
||||
CONTEXT_ALARMSCREEN, /* uses ACTION_AS_ defines */
|
||||
CONTEXT_ALARMSCREEN, /* uses ACTION_AS_ defines */
|
||||
CONTEXT_QUICKSCREEN, /* uses ACTION_QS_ defines below */
|
||||
CONTEXT_PITCHSCREEN, /* uses ACTION_PS_ defines below */
|
||||
|
||||
|
||||
CONTEXT_YESNOSCREEN, /*NOTE: make sure your target has this and ACTION_YESNO_ACCEPT */
|
||||
CONTEXT_RECSCREEN,
|
||||
CONTEXT_KEYBOARD,
|
||||
|
|
@ -131,25 +82,23 @@ enum {
|
|||
CONTEXT_USB_HID_MODE_PRESENTATION,
|
||||
CONTEXT_USB_HID_MODE_BROWSER,
|
||||
CONTEXT_USB_HID_MODE_MOUSE,
|
||||
LAST_CONTEXT_PLACEHOLDER,
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
|
||||
|
||||
ACTION_NONE = BUTTON_NONE,
|
||||
ACTION_UNKNOWN,
|
||||
ACTION_REDRAW, /* returned if keys are locked and we splash()'ed */
|
||||
ACTION_TOUCHSCREEN,
|
||||
ACTION_TOUCHSCREEN_MODE, /* toggle the touchscreen mode */
|
||||
ACTION_TOUCHSCREEN_IGNORE, /* used for the 'none' action in skins */
|
||||
|
||||
|
||||
/* standard actions, use these first */
|
||||
ACTION_STD_PREV,
|
||||
ACTION_STD_PREV,
|
||||
ACTION_STD_PREVREPEAT,
|
||||
ACTION_STD_NEXT,
|
||||
ACTION_STD_NEXTREPEAT,
|
||||
|
||||
|
||||
ACTION_STD_OK,
|
||||
ACTION_STD_CANCEL,
|
||||
ACTION_STD_CONTEXT,
|
||||
|
|
@ -158,9 +107,10 @@ enum {
|
|||
ACTION_STD_KEYLOCK,
|
||||
ACTION_STD_REC,
|
||||
ACTION_STD_HOTKEY,
|
||||
|
||||
|
||||
ACTION_F3, /* just so everything works again, possibly change me */
|
||||
/* code context actions */
|
||||
|
||||
|
||||
/* WPS codes */
|
||||
ACTION_WPS_BROWSE,
|
||||
ACTION_WPS_PLAY,
|
||||
|
|
@ -178,11 +128,9 @@ enum {
|
|||
ACTION_WPS_QUICKSCREEN,/* optional */
|
||||
ACTION_WPS_MENU, /*this should be the same as ACTION_STD_MENU */
|
||||
ACTION_WPS_VIEW_PLAYLIST,
|
||||
ACTION_WPS_LIST_BOOKMARKS,/* optional */
|
||||
ACTION_WPS_CREATE_BOOKMARK,/* optional */
|
||||
ACTION_WPS_REC,
|
||||
#if 0
|
||||
ACTION_WPSAB_SINGLE, /* This needs to be #defined in
|
||||
ACTION_WPSAB_SINGLE, /* This needs to be #defined in
|
||||
the config-<target>.h to one of the ACTION_WPS_ actions
|
||||
so it can be used */
|
||||
#endif
|
||||
|
|
@ -190,23 +138,23 @@ enum {
|
|||
ACTION_WPS_ABSETB_NEXTDIR, /* you shouldnt want to change dir in ab-mode */
|
||||
ACTION_WPS_ABRESET,
|
||||
ACTION_WPS_HOTKEY,
|
||||
|
||||
/* list and tree page up/down */
|
||||
|
||||
/* list and tree page up/down */
|
||||
ACTION_LISTTREE_PGUP,/* optional */
|
||||
ACTION_LISTTREE_PGDOWN,/* optional */
|
||||
#ifdef HAVE_VOLUME_IN_LIST
|
||||
ACTION_LIST_VOLUP,
|
||||
ACTION_LIST_VOLDOWN,
|
||||
#endif
|
||||
|
||||
/* tree */
|
||||
|
||||
/* tree */
|
||||
ACTION_TREE_ROOT_INIT,
|
||||
ACTION_TREE_PGLEFT,/* optional */
|
||||
ACTION_TREE_PGRIGHT,/* optional */
|
||||
ACTION_TREE_STOP,
|
||||
ACTION_TREE_WPS,
|
||||
ACTION_TREE_HOTKEY,
|
||||
|
||||
|
||||
/* radio */
|
||||
ACTION_FM_MENU,
|
||||
ACTION_FM_PRESET,
|
||||
|
|
@ -226,7 +174,7 @@ enum {
|
|||
ACTION_REC_NEWFILE,
|
||||
ACTION_REC_F2,
|
||||
ACTION_REC_F3,
|
||||
|
||||
|
||||
/* main menu */
|
||||
/* These are not strictly actions, but must be here
|
||||
so they dont conflict with real actions in the menu code */
|
||||
|
|
@ -235,11 +183,11 @@ enum {
|
|||
ACTION_EXIT_AFTER_THIS_MENUITEM, /* if a menu returns this the menu will exit
|
||||
once the subitem returns */
|
||||
ACTION_ENTER_MENUITEM,
|
||||
|
||||
|
||||
/* id3db */
|
||||
|
||||
|
||||
/* list */
|
||||
|
||||
|
||||
/* settings */
|
||||
ACTION_SETTINGS_INC,
|
||||
ACTION_SETTINGS_INCREPEAT,
|
||||
|
|
@ -247,19 +195,18 @@ enum {
|
|||
ACTION_SETTINGS_DEC,
|
||||
ACTION_SETTINGS_DECREPEAT,
|
||||
ACTION_SETTINGS_DECBIGSTEP,
|
||||
ACTION_SETTINGS_RESET,
|
||||
ACTION_SETTINGS_SET, /* Used by touchscreen targets */
|
||||
|
||||
|
||||
/* bookmark screen */
|
||||
ACTION_BMS_DELETE,
|
||||
|
||||
|
||||
/* quickscreen */
|
||||
ACTION_QS_LEFT,
|
||||
ACTION_QS_RIGHT,
|
||||
ACTION_QS_DOWN,
|
||||
ACTION_QS_TOP,
|
||||
ACTION_QS_VOLUP,
|
||||
ACTION_QS_VOLDOWN,
|
||||
|
||||
|
||||
/* pitchscreen */
|
||||
/* obviously ignore if you dont have thise screen */
|
||||
ACTION_PS_INC_SMALL,
|
||||
|
|
@ -275,10 +222,10 @@ enum {
|
|||
ACTION_PS_EXIT, /* _STD_* isnt going to work here */
|
||||
ACTION_PS_SLOWER,
|
||||
ACTION_PS_FASTER,
|
||||
|
||||
|
||||
/* yesno screen */
|
||||
ACTION_YESNO_ACCEPT,
|
||||
|
||||
|
||||
/* keyboard screen */
|
||||
ACTION_KBD_LEFT,
|
||||
ACTION_KBD_RIGHT,
|
||||
|
|
@ -293,7 +240,7 @@ enum {
|
|||
ACTION_KBD_DOWN,
|
||||
ACTION_KBD_MORSE_INPUT,
|
||||
ACTION_KBD_MORSE_SELECT,
|
||||
|
||||
|
||||
#ifdef HAVE_TOUCHSCREEN
|
||||
/* the following are helper actions for touchscreen targets,
|
||||
* These are for actions which are not doable or required if buttons are
|
||||
|
|
@ -303,9 +250,7 @@ enum {
|
|||
ACTION_TOUCH_MUTE,
|
||||
ACTION_TOUCH_SCROLLBAR,
|
||||
ACTION_TOUCH_VOLUME,
|
||||
ACTION_TOUCH_SOFTLOCK,
|
||||
ACTION_TOUCH_SETTING,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* USB HID codes */
|
||||
ACTION_USB_HID_FIRST, /* Place holder */
|
||||
|
|
@ -379,60 +324,11 @@ enum {
|
|||
LAST_ACTION_PLACEHOLDER, /* custom actions should be this + something */
|
||||
};
|
||||
|
||||
/* act_cur holds action state during get_action() call */
|
||||
typedef struct
|
||||
{
|
||||
int action;
|
||||
int button;
|
||||
int context;
|
||||
int timeout;
|
||||
const struct button_mapping *items;
|
||||
const struct button_mapping* (*get_context_map)(int);
|
||||
bool is_prebutton;
|
||||
} action_cur_t;
|
||||
|
||||
/* act_last holds action state between get_action() calls */
|
||||
typedef struct
|
||||
{
|
||||
int action;
|
||||
long tick;
|
||||
int button;
|
||||
int context;
|
||||
intptr_t data;
|
||||
|
||||
#if defined(HAVE_BACKLIGHT)
|
||||
unsigned int backlight_mask;
|
||||
long bl_filter_tick;
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_BUTTON_HOLD)
|
||||
long sl_filter_tick;
|
||||
unsigned int softlock_mask;
|
||||
int unlock_combo;
|
||||
bool keys_locked;
|
||||
bool screen_has_lock;
|
||||
|
||||
#endif
|
||||
|
||||
bool repeated;
|
||||
bool wait_for_release;
|
||||
|
||||
#ifndef DISABLE_ACTION_REMAP
|
||||
int key_remap;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TOUCHSCREEN
|
||||
bool ts_short_press;
|
||||
int ts_data;
|
||||
#endif
|
||||
} action_last_t;
|
||||
|
||||
struct button_mapping {
|
||||
int action_code;
|
||||
int button_code;
|
||||
int pre_button_code;
|
||||
};
|
||||
|
||||
/* use if you want to supply your own button mappings, PLUGINS ONLY */
|
||||
/* get_context_map is a function which returns a button_mapping* depedning on the given context */
|
||||
/* custom button_mappings may "chain" to inbuilt CONTEXT's */
|
||||
|
|
@ -446,13 +342,11 @@ bool action_userabort(int timeout);
|
|||
|
||||
/* no other code should need this apart from action.c */
|
||||
const struct button_mapping* get_context_mapping(int context);
|
||||
#ifndef HAS_BUTTON_HOLD
|
||||
bool is_keys_locked(void);
|
||||
#endif
|
||||
|
||||
/* load a key map to allow buttons for actions to be remapped see: core_keymap */
|
||||
int action_set_keymap(struct button_mapping* core_keymap, int count);
|
||||
/* load keymap in a handle: takes ownership of the handle on success */
|
||||
int action_set_keymap_handle(int handle, int count);
|
||||
|
||||
/* returns the status code variable from action.c for the button just pressed
|
||||
/* returns the status code variable from action.c for the button just pressed
|
||||
If button != NULL it will be set to the actual button code */
|
||||
#define ACTION_REMOTE 0x1 /* remote was pressed */
|
||||
#define ACTION_REPEAT 0x2 /* action was repeated (NOT button) */
|
||||
|
|
@ -479,27 +373,15 @@ int action_get_touchscreen_press(short *x, short *y);
|
|||
* the press was within the viewport,
|
||||
* ACTION_UNKNOWN (and x1, y1 untouched) if the press was outside
|
||||
* BUTTON_NONE else
|
||||
*
|
||||
*
|
||||
**/
|
||||
int action_get_touchscreen_press_in_vp(short *x1, short *y1, struct viewport *vp);
|
||||
#endif
|
||||
|
||||
/*******************************************************
|
||||
* action_wait_for_release will not allow
|
||||
* get_action(|_custom)() to return
|
||||
* any ACTION_* values until the current buttons
|
||||
* have been released.
|
||||
* SYS_* and BUTTON_NONE will pass through.
|
||||
* but, any actions relying on _RELEASE won't be seen.
|
||||
*
|
||||
* Note this doesn't currently work for
|
||||
* touchscreen targets if called when the
|
||||
* screen isn't currently touched because,
|
||||
* if the touch coordinates change they can send
|
||||
* normal (non-BUTTON_REPEAT) events repeatedly,
|
||||
* this cannot be distinguished
|
||||
* from normal button events.
|
||||
*/
|
||||
/* Don't let get_action*() return any ACTION_* values until the current buttons
|
||||
* have been released. SYS_* and BUTTON_NONE will go through.
|
||||
* Any actions relying on _RELEASE won't get seen.
|
||||
*/
|
||||
void action_wait_for_release(void);
|
||||
|
||||
#endif /* __ACTION_H__ */
|
||||
|
|
|
|||
|
|
@ -38,56 +38,161 @@
|
|||
#include "splash.h"
|
||||
#include "viewport.h"
|
||||
|
||||
int alarm_screen(void)
|
||||
static void speak_time(int hours, int minutes, bool speak_hours, bool enqueue)
|
||||
{
|
||||
bool usb, update;
|
||||
struct tm *now = get_time();
|
||||
struct tm atm;
|
||||
memcpy(&atm, now, sizeof(struct tm));
|
||||
rtc_get_alarm(&atm.tm_hour, &atm.tm_min);
|
||||
if (global_settings.talk_menu){
|
||||
if(speak_hours) {
|
||||
talk_value(hours, UNIT_HOUR, enqueue);
|
||||
talk_value(minutes, UNIT_MIN, true);
|
||||
} else {
|
||||
talk_value(minutes, UNIT_MIN, enqueue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool alarm_screen(void)
|
||||
{
|
||||
int h, m;
|
||||
bool done = false;
|
||||
struct tm *tm;
|
||||
int togo;
|
||||
int button;
|
||||
int i;
|
||||
bool update = true;
|
||||
bool hour_wrapped = false;
|
||||
struct viewport vp[NB_SCREENS];
|
||||
|
||||
rtc_get_alarm(&h, &m);
|
||||
|
||||
/* After a battery change the RTC values are out of range */
|
||||
if (!valid_time(&atm))
|
||||
memcpy(&atm, now, sizeof(struct tm));
|
||||
atm.tm_sec = 0;
|
||||
|
||||
usb = set_time_screen(str(LANG_ALARM_MOD_TIME), &atm, false);
|
||||
update = valid_time(&atm); /* set_time returns invalid time if canceled */
|
||||
|
||||
if (!usb && update)
|
||||
if (m > 60 || h > 24) {
|
||||
m = 0;
|
||||
h = 12;
|
||||
} else {
|
||||
m = m / 5 * 5; /* 5 min accuracy should be enough */
|
||||
}
|
||||
FOR_NB_SCREENS(i)
|
||||
{
|
||||
viewport_set_defaults(&vp[i], i);
|
||||
}
|
||||
|
||||
now = get_time();
|
||||
int nmins = now->tm_min + (now->tm_hour * 60);
|
||||
int amins = atm.tm_min + (atm.tm_hour * 60);
|
||||
int mins_togo = (amins - nmins + 1440) % 1440;
|
||||
while(!done) {
|
||||
if(update)
|
||||
{
|
||||
FOR_NB_SCREENS(i)
|
||||
{
|
||||
screens[i].set_viewport(&vp[i]);
|
||||
screens[i].clear_viewport();
|
||||
screens[i].puts(0, 4, str(LANG_ALARM_MOD_KEYS));
|
||||
}
|
||||
/* Talk when entering the wakeup screen */
|
||||
speak_time(h, m, true, true);
|
||||
update = false;
|
||||
}
|
||||
|
||||
FOR_NB_SCREENS(i)
|
||||
{
|
||||
screens[i].set_viewport(&vp[i]);
|
||||
screens[i].putsf(0, 1, str(LANG_ALARM_MOD_TIME));
|
||||
screens[i].putsf(0, 2, "%02d:%02d", h, m);
|
||||
screens[i].update_viewport();
|
||||
screens[i].set_viewport(NULL);
|
||||
}
|
||||
button = get_action(CONTEXT_SETTINGS,HZ);
|
||||
|
||||
switch(button) {
|
||||
case ACTION_STD_OK:
|
||||
/* prevent that an alarm occurs in the shutdown procedure */
|
||||
/* accept alarms only if they are in 2 minutes or more */
|
||||
if (mins_togo > 1) {
|
||||
tm = get_time();
|
||||
togo = (m + h * 60 - tm->tm_min - tm->tm_hour * 60 + 1440) % 1440;
|
||||
|
||||
if (togo > 1) {
|
||||
rtc_init();
|
||||
rtc_set_alarm(atm.tm_hour,atm.tm_min);
|
||||
rtc_set_alarm(h,m);
|
||||
rtc_enable_alarm(true);
|
||||
if (global_settings.talk_menu)
|
||||
{
|
||||
talk_id(LANG_ALARM_MOD_TIME_TO_GO, true);
|
||||
talk_value(mins_togo / 60, UNIT_HOUR, true);
|
||||
talk_value(mins_togo % 60, UNIT_MIN, true);
|
||||
talk_value(togo / 60, UNIT_HOUR, true);
|
||||
talk_value(togo % 60, UNIT_MIN, true);
|
||||
talk_force_enqueue_next();
|
||||
}
|
||||
splashf(HZ*2, str(LANG_ALARM_MOD_TIME_TO_GO),
|
||||
mins_togo / 60, mins_togo % 60);
|
||||
togo / 60, togo % 60);
|
||||
done = true;
|
||||
} else {
|
||||
splash(HZ, ID2P(LANG_ALARM_MOD_ERROR));
|
||||
update = false;
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
if (usb || !update)
|
||||
{
|
||||
if (!usb)
|
||||
/* inc(m) */
|
||||
case ACTION_SETTINGS_INC:
|
||||
case ACTION_SETTINGS_INCREPEAT:
|
||||
m += 5;
|
||||
if (m == 60) {
|
||||
h += 1;
|
||||
m = 0;
|
||||
hour_wrapped = true;
|
||||
}
|
||||
if (h == 24)
|
||||
h = 0;
|
||||
|
||||
speak_time(h, m, hour_wrapped, false);
|
||||
break;
|
||||
|
||||
/* dec(m) */
|
||||
case ACTION_SETTINGS_DEC:
|
||||
case ACTION_SETTINGS_DECREPEAT:
|
||||
m -= 5;
|
||||
if (m == -5) {
|
||||
h -= 1;
|
||||
m = 55;
|
||||
hour_wrapped = true;
|
||||
}
|
||||
if (h == -1)
|
||||
h = 23;
|
||||
|
||||
speak_time(h, m, hour_wrapped, false);
|
||||
break;
|
||||
|
||||
/* inc(h) */
|
||||
case ACTION_STD_NEXT:
|
||||
case ACTION_STD_NEXTREPEAT:
|
||||
h = (h+1) % 24;
|
||||
|
||||
if (global_settings.talk_menu)
|
||||
talk_value(h, UNIT_HOUR, false);
|
||||
break;
|
||||
|
||||
/* dec(h) */
|
||||
case ACTION_STD_PREV:
|
||||
case ACTION_STD_PREVREPEAT:
|
||||
h = (h+23) % 24;
|
||||
|
||||
if (global_settings.talk_menu)
|
||||
talk_value(h, UNIT_HOUR, false);
|
||||
break;
|
||||
|
||||
case ACTION_STD_CANCEL:
|
||||
rtc_enable_alarm(false);
|
||||
splash(HZ*2, ID2P(LANG_ALARM_MOD_DISABLE));
|
||||
rtc_enable_alarm(false);
|
||||
return 1;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case ACTION_NONE:
|
||||
hour_wrapped = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
if(default_event_handler(button) == SYS_USB_CONNECTED)
|
||||
{
|
||||
rtc_enable_alarm(false);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,6 @@
|
|||
#ifndef _ALARM_MENU_H
|
||||
#define _ALARM_MENU_H
|
||||
|
||||
int alarm_screen(void);
|
||||
bool alarm_screen(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -31,36 +31,22 @@
|
|||
|
||||
/** Playback events **/
|
||||
enum {
|
||||
/* Playback is starting from a stopped state
|
||||
data = NULL */
|
||||
/* Playback is starting from a stopped state */
|
||||
PLAYBACK_EVENT_START_PLAYBACK = (EVENT_CLASS_PLAYBACK|1),
|
||||
/* Audio has begun buffering for decoding track (or is already completed)
|
||||
data = &(struct track_event){} */
|
||||
/* Audio has begun buffering for decoding track (or is already completed) */
|
||||
PLAYBACK_EVENT_TRACK_BUFFER,
|
||||
/* Handles for current user track are ready (other than audio or codec)
|
||||
data = &(struct track_event){} */
|
||||
/* Handles for current user track are ready (other than audio or codec) */
|
||||
PLAYBACK_EVENT_CUR_TRACK_READY,
|
||||
/* Current user track finished
|
||||
data = &(struct track_event){} */
|
||||
/* Current user track finished */
|
||||
PLAYBACK_EVENT_TRACK_FINISH,
|
||||
/* A new current user track has begun
|
||||
data = &(struct track_event){} */
|
||||
/* A new current user track has begun */
|
||||
PLAYBACK_EVENT_TRACK_CHANGE,
|
||||
/* A manual skip is about to be processed
|
||||
data = NULL */
|
||||
/* A manual skip is about to be processed */
|
||||
PLAYBACK_EVENT_TRACK_SKIP,
|
||||
/* Next track medadata was just loaded
|
||||
data = &(struct track_event){} */
|
||||
/* Next track medadata was just loaded */
|
||||
PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE,
|
||||
};
|
||||
|
||||
/** VOICE events **/
|
||||
enum {
|
||||
/* Voice is playing
|
||||
data = &(bool){true|false} */
|
||||
VOICE_EVENT_IS_PLAYING = (EVENT_CLASS_VOICE|1),
|
||||
};
|
||||
|
||||
/** Buffering events **/
|
||||
enum {
|
||||
BUFFER_EVENT_BUFFER_LOW = (EVENT_CLASS_BUFFERING|1),
|
||||
|
|
@ -68,7 +54,6 @@ enum {
|
|||
BUFFER_EVENT_CLOSED,
|
||||
BUFFER_EVENT_MOVED,
|
||||
BUFFER_EVENT_FINISHED,
|
||||
BUFFER_EVENT_BUFFER_RESET
|
||||
};
|
||||
|
||||
/** Generic GUI class events **/
|
||||
|
|
@ -76,9 +61,6 @@ enum {
|
|||
GUI_EVENT_STATUSBAR_TOGGLE = (EVENT_CLASS_GUI|1),
|
||||
GUI_EVENT_ACTIONUPDATE,
|
||||
GUI_EVENT_THEME_CHANGED,
|
||||
/* Called when the UI viewport is cleared in the skin engine to
|
||||
* notify the current screen that it needs to do an update */
|
||||
GUI_EVENT_NEED_UI_UPDATE,
|
||||
};
|
||||
|
||||
/** Recording events **/
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ $(BUILDDIR)/apps/features: $(APPSDIR)/features.txt $(BUILDDIR)/firmware/common/
|
|||
$(call PRINTS,PP $(<F))
|
||||
$(SILENT)$(CC) $(PPCFLAGS) \
|
||||
-E -P -imacros "config.h" -imacros "button.h" -x c $< | \
|
||||
grep -v "^#" | grep -v "^ *$$" > $(BUILDDIR)/apps/features; \
|
||||
grep -v "^\#" | grep -v "^ *$$" > $(BUILDDIR)/apps/features; \
|
||||
|
||||
$(BUILDDIR)/apps/genlang-features: $(BUILDDIR)/apps/features
|
||||
$(call PRINTS,GEN $(subst $(BUILDDIR)/,,$@))tr \\n : < $< > $@
|
||||
|
|
|
|||
|
|
@ -34,9 +34,6 @@
|
|||
#if CONFIG_TUNER
|
||||
#include "radio.h"
|
||||
#endif
|
||||
#if defined(IPOD_ACCESSORY_PROTOCOL) && defined(HAVE_LINE_REC)
|
||||
#include "iap.h"
|
||||
#endif
|
||||
|
||||
/* Some audio sources may require a boosted CPU */
|
||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||
|
|
@ -45,8 +42,7 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if ((CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) \
|
||||
|| (defined(SONY_NWZ_LINUX) && !defined(SIMULATOR)))
|
||||
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
||||
|
||||
#ifdef AUDIO_CPU_BOOST
|
||||
static void audio_cpu_boost(bool state)
|
||||
|
|
@ -99,13 +95,6 @@ void audio_set_input_source(int source, unsigned flags)
|
|||
radio_start();
|
||||
#endif
|
||||
|
||||
#if defined(IPOD_ACCESSORY_PROTOCOL) && defined(HAVE_LINE_REC)
|
||||
static bool last_rec_onoff = false;
|
||||
bool onoff = (source == AUDIO_SRC_LINEIN) ? true : false;
|
||||
if (last_rec_onoff != onoff)
|
||||
last_rec_onoff = iap_record(onoff);
|
||||
#endif
|
||||
|
||||
/* set hardware inputs */
|
||||
audio_input_mux(source, flags);
|
||||
} /* audio_set_source */
|
||||
|
|
@ -165,25 +154,3 @@ int audio_get_spdif_sample_rate(void)
|
|||
#endif /* HAVE_SPDIF_IN */
|
||||
|
||||
#endif /* PLATFORM_NATIVE */
|
||||
|
||||
#ifdef HAVE_SPEAKER
|
||||
void audio_enable_speaker(int mode)
|
||||
{
|
||||
#if defined(HAVE_HEADPHONE_DETECTION) || defined(HAVE_LINEOUT_DETECTION)
|
||||
/* if needed, query jack state */
|
||||
if(mode == 2)
|
||||
{
|
||||
#ifdef HAVE_HEADPHONE_DETECTION
|
||||
if (headphones_inserted())
|
||||
mode = 0;
|
||||
#endif
|
||||
#ifdef HAVE_LINEOUT_DETECTION
|
||||
if (lineout_inserted())
|
||||
mode = 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/* treat any nonzero value as enable */
|
||||
audiohw_enable_speaker(mode);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,188 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005-2007 Miika Pekkarinen
|
||||
* Copyright (C) 2007-2008 Nicolas Pennequin
|
||||
* Copyright (C) 2011-2013 Michael Sevakis
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "kernel.h"
|
||||
#include "logf.h"
|
||||
#include "usb.h"
|
||||
#include "pcm.h"
|
||||
#include "sound.h"
|
||||
#include "pcmbuf.h"
|
||||
#include "appevents.h"
|
||||
#include "audio_thread.h"
|
||||
#ifdef AUDIO_HAVE_RECORDING
|
||||
#include "pcm_record.h"
|
||||
#endif
|
||||
#include "codec_thread.h"
|
||||
#include "voice_thread.h"
|
||||
#include "talk.h"
|
||||
#include "settings.h"
|
||||
|
||||
/* Macros to enable logf for queues
|
||||
logging on SYS_TIMEOUT can be disabled */
|
||||
#ifdef SIMULATOR
|
||||
/* Define this for logf output of all queuing except SYS_TIMEOUT */
|
||||
#define AUDIO_LOGQUEUES
|
||||
/* Define this to logf SYS_TIMEOUT messages */
|
||||
/*#define AUDIO_LOGQUEUES_SYS_TIMEOUT*/
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_LOGQUEUES
|
||||
#define LOGFQUEUE logf
|
||||
#else
|
||||
#define LOGFQUEUE(...)
|
||||
#endif
|
||||
|
||||
bool audio_is_initialized = false;
|
||||
|
||||
/* Event queues */
|
||||
struct event_queue audio_queue SHAREDBSS_ATTR;
|
||||
static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR;
|
||||
|
||||
/* Audio thread */
|
||||
static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
|
||||
static const char audio_thread_name[] = "audio";
|
||||
unsigned int audio_thread_id = 0;
|
||||
|
||||
static void NORETURN_ATTR audio_thread(void)
|
||||
{
|
||||
struct queue_event ev;
|
||||
ev.id = Q_NULL; /* something not in switch below */
|
||||
|
||||
pcm_postinit();
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (ev.id)
|
||||
{
|
||||
/* Starts the playback engine branch */
|
||||
case Q_AUDIO_PLAY:
|
||||
LOGFQUEUE("audio < Q_AUDIO_PLAY");
|
||||
audio_playback_handler(&ev);
|
||||
continue;
|
||||
|
||||
/* Playback has to handle these, even if not playing */
|
||||
case Q_AUDIO_REMAKE_AUDIO_BUFFER:
|
||||
#ifdef HAVE_DISK_STORAGE
|
||||
case Q_AUDIO_UPDATE_WATERMARK:
|
||||
#endif
|
||||
audio_playback_handler(&ev);
|
||||
break;
|
||||
|
||||
#ifdef AUDIO_HAVE_RECORDING
|
||||
/* Starts the recording engine branch */
|
||||
case Q_AUDIO_INIT_RECORDING:
|
||||
LOGFQUEUE("audio < Q_AUDIO_INIT_RECORDING");
|
||||
audio_recording_handler(&ev);
|
||||
continue;
|
||||
#endif
|
||||
|
||||
/* All return upon USB */
|
||||
case SYS_USB_CONNECTED:
|
||||
LOGFQUEUE("audio < SYS_USB_CONNECTED");
|
||||
voice_stop();
|
||||
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
||||
usb_wait_for_disconnect(&audio_queue);
|
||||
break;
|
||||
}
|
||||
|
||||
queue_wait(&audio_queue, &ev);
|
||||
}
|
||||
}
|
||||
|
||||
void audio_voice_event(unsigned short id, void *data)
|
||||
{
|
||||
(void)id;
|
||||
/* Make audio play softly while voice is speaking */
|
||||
pcmbuf_soft_mode(*(bool *)data);
|
||||
}
|
||||
|
||||
void audio_queue_post(long id, intptr_t data)
|
||||
{
|
||||
queue_post(&audio_queue, id, data);
|
||||
}
|
||||
|
||||
intptr_t audio_queue_send(long id, intptr_t data)
|
||||
{
|
||||
return queue_send(&audio_queue, id, data);
|
||||
}
|
||||
|
||||
/* Return the playback and recording status */
|
||||
int audio_status(void)
|
||||
{
|
||||
return playback_status()
|
||||
#ifdef AUDIO_HAVE_RECORDING
|
||||
| pcm_rec_status()
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
/* Clear all accumulated audio errors for playback and recording */
|
||||
void audio_error_clear(void)
|
||||
{
|
||||
#ifdef AUDIO_HAVE_RECORDING
|
||||
pcm_rec_error_clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** -- Startup -- **/
|
||||
|
||||
/* Initialize the audio system - called from init() in main.c */
|
||||
void INIT_ATTR audio_init(void)
|
||||
{
|
||||
/* Can never do this twice */
|
||||
if (audio_is_initialized)
|
||||
{
|
||||
logf("audio: already initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
logf("audio: initializing");
|
||||
|
||||
/* Initialize queues before giving control elsewhere in case it likes
|
||||
to send messages. Thread creation will be delayed however so nothing
|
||||
starts running until ready if something yields such as talk_init. */
|
||||
queue_init(&audio_queue, true);
|
||||
codec_thread_init();
|
||||
|
||||
/* This thread does buffer, so match its priority */
|
||||
audio_thread_id = create_thread(audio_thread, audio_stack,
|
||||
sizeof(audio_stack), 0, audio_thread_name
|
||||
IF_PRIO(, MIN(PRIORITY_BUFFERING, PRIORITY_USER_INTERFACE))
|
||||
IF_COP(, CPU));
|
||||
|
||||
queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
|
||||
audio_thread_id);
|
||||
|
||||
playback_init();
|
||||
#ifdef AUDIO_HAVE_RECORDING
|
||||
recording_init();
|
||||
#endif
|
||||
|
||||
add_event(VOICE_EVENT_IS_PLAYING, audio_voice_event);
|
||||
|
||||
/* Probably safe to say */
|
||||
audio_is_initialized = true;
|
||||
|
||||
sound_settings_apply();
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005-2007 Miika Pekkarinen
|
||||
* Copyright (C) 2007-2008 Nicolas Pennequin
|
||||
* Copyright (C) 2011-2013 Michael Sevakis
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef AUDIO_THREAD_H
|
||||
#define AUDIO_THREAD_H
|
||||
|
||||
/* Define one constant that includes recording related functionality */
|
||||
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
|
||||
#define AUDIO_HAVE_RECORDING
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
Q_NULL = 0, /* reserved */
|
||||
|
||||
/* -> audio */
|
||||
Q_AUDIO_PLAY,
|
||||
Q_AUDIO_STOP,
|
||||
Q_AUDIO_PAUSE,
|
||||
Q_AUDIO_SKIP,
|
||||
Q_AUDIO_PRE_FF_REWIND,
|
||||
Q_AUDIO_FF_REWIND,
|
||||
Q_AUDIO_FLUSH,
|
||||
Q_AUDIO_DIR_SKIP,
|
||||
|
||||
/* pcmbuf -> audio */
|
||||
Q_AUDIO_TRACK_CHANGED,
|
||||
|
||||
/* audio -> audio */
|
||||
Q_AUDIO_FILL_BUFFER, /* continue buffering next track */
|
||||
|
||||
/* buffering -> audio */
|
||||
Q_AUDIO_BUFFERING, /* some buffer event */
|
||||
Q_AUDIO_FINISH_LOAD_TRACK, /* metadata is buffered */
|
||||
Q_AUDIO_HANDLE_FINISHED, /* some other type is buffered */
|
||||
|
||||
/* codec -> audio (*) */
|
||||
Q_AUDIO_CODEC_SEEK_COMPLETE,
|
||||
Q_AUDIO_CODEC_COMPLETE,
|
||||
|
||||
/* audio -> codec */
|
||||
Q_CODEC_LOAD,
|
||||
Q_CODEC_RUN,
|
||||
Q_CODEC_PAUSE,
|
||||
Q_CODEC_SEEK,
|
||||
Q_CODEC_STOP,
|
||||
Q_CODEC_UNLOAD,
|
||||
|
||||
/* -> codec */
|
||||
Q_CODEC_DO_CALLBACK,
|
||||
|
||||
/* -> recording */
|
||||
#ifdef HAVE_RECORDING
|
||||
Q_AUDIO_INIT_RECORDING,
|
||||
Q_AUDIO_CLOSE_RECORDING,
|
||||
Q_AUDIO_RECORDING_OPTIONS,
|
||||
Q_AUDIO_RECORD,
|
||||
Q_AUDIO_RECORD_STOP,
|
||||
Q_AUDIO_RECORD_PAUSE,
|
||||
Q_AUDIO_RECORD_RESUME,
|
||||
Q_AUDIO_RECORD_FLUSH,
|
||||
#endif
|
||||
|
||||
/*- settings -*/
|
||||
|
||||
#ifdef HAVE_DISK_STORAGE
|
||||
/* -> audio */
|
||||
Q_AUDIO_UPDATE_WATERMARK, /* buffering watermark needs updating */
|
||||
#endif
|
||||
/* -> audio */
|
||||
Q_AUDIO_REMAKE_AUDIO_BUFFER, /* buffer needs to be reinitialized */
|
||||
};
|
||||
|
||||
/* (*) If you change these, you must check audio_clear_track_notifications
|
||||
in playback.c for correctness */
|
||||
|
||||
void audio_init(void);
|
||||
void playback_init(void);
|
||||
unsigned int playback_status(void);
|
||||
|
||||
void audio_playback_handler(struct queue_event *ev);
|
||||
#ifdef AUDIO_HAVE_RECORDING
|
||||
void audio_recording_handler(struct queue_event *ev);
|
||||
#endif
|
||||
|
||||
/** --- audio_queue helpers --- **/
|
||||
void audio_queue_post(long id, intptr_t data);
|
||||
intptr_t audio_queue_send(long id, intptr_t data);
|
||||
|
||||
#endif /* AUDIO_THREAD_H */
|
||||
103
apps/beep.c
|
|
@ -1,103 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2011 Michael Sevakis
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "settings.h"
|
||||
#include "pcm.h"
|
||||
#include "pcm_mixer.h"
|
||||
#include "misc.h"
|
||||
#include "fixedpoint.h"
|
||||
|
||||
/** Beep generation, CPU optimized **/
|
||||
#include "asm/beep.c"
|
||||
|
||||
static uint32_t beep_phase; /* Phase of square wave generator */
|
||||
static uint32_t beep_step; /* Step of square wave generator on each sample */
|
||||
#ifdef BEEP_GENERIC
|
||||
static int16_t beep_amplitude; /* Amplitude of square wave generator */
|
||||
#else
|
||||
/* Optimized routines do XOR with phase sign bit in both channels at once */
|
||||
static uint32_t beep_amplitude; /* Amplitude of square wave generator */
|
||||
#endif
|
||||
static int beep_count; /* Number of samples remaining to generate */
|
||||
|
||||
#define BEEP_COUNT(fs, duration) ((fs) / 1000 * (duration))
|
||||
|
||||
/* Reserve enough static space for keyclick to fit in worst case */
|
||||
#define BEEP_BUF_COUNT BEEP_COUNT(PLAY_SAMPR_MAX, KEYCLICK_DURATION)
|
||||
static int16_t beep_buf[BEEP_BUF_COUNT*2] IBSS_ATTR __attribute__((aligned(4)));
|
||||
|
||||
/* Callback to generate the beep frames - also don't want inlining of
|
||||
call below in beep_play */
|
||||
static void __attribute__((noinline))
|
||||
beep_get_more(const void **start, size_t *size)
|
||||
{
|
||||
int count = beep_count;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
count = MIN(count, BEEP_BUF_COUNT);
|
||||
beep_count -= count;
|
||||
*start = beep_buf;
|
||||
*size = count * 2 * sizeof (int16_t);
|
||||
beep_generate((void *)beep_buf, count, &beep_phase,
|
||||
beep_step, beep_amplitude);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generates a constant square wave sound with a given frequency in Hertz for
|
||||
a duration in milliseconds */
|
||||
void beep_play(unsigned int frequency, unsigned int duration,
|
||||
unsigned int amplitude)
|
||||
{
|
||||
mixer_channel_stop(PCM_MIXER_CHAN_BEEP);
|
||||
|
||||
if (frequency == 0 || duration == 0 || amplitude == 0)
|
||||
return;
|
||||
|
||||
if (amplitude > INT16_MAX)
|
||||
amplitude = INT16_MAX;
|
||||
|
||||
/* Setup the parameters for the square wave generator */
|
||||
uint32_t fout = mixer_get_frequency();
|
||||
beep_phase = 0;
|
||||
beep_step = fp_div(frequency, fout, 32);
|
||||
beep_count = BEEP_COUNT(fout, duration);
|
||||
|
||||
#ifdef BEEP_GENERIC
|
||||
beep_amplitude = amplitude;
|
||||
#else
|
||||
/* Optimized routines do XOR with phase sign bit in both channels at once */
|
||||
beep_amplitude = amplitude | (amplitude << 16); /* Word:|AMP16|AMP16| */
|
||||
#endif
|
||||
|
||||
/* If it fits - avoid cb overhead */
|
||||
const void *start;
|
||||
size_t size;
|
||||
|
||||
/* Generate first frame here */
|
||||
beep_get_more(&start, &size);
|
||||
|
||||
mixer_channel_set_amplitude(PCM_MIXER_CHAN_BEEP, MIX_AMP_UNITY);
|
||||
mixer_channel_play_data(PCM_MIXER_CHAN_BEEP,
|
||||
beep_count ? beep_get_more : NULL,
|
||||
start, size);
|
||||
}
|
||||
|
|
@ -25,28 +25,27 @@ ifneq ($(strip $(BMP2RB_REMOTENATIVE)),)
|
|||
BMP += $(call preprocess, $(BITMAPDIR)/remote_native/SOURCES)
|
||||
endif
|
||||
|
||||
BMPOBJ = $(call full_path_subst,$(ROOTDIR)/%.bmp,$(BUILDDIR)/%.o,$(BMP))
|
||||
BMPOBJ = $(BMP:$(ROOTDIR)/%.bmp=$(BUILDDIR)/%.o)
|
||||
|
||||
BMPHFILES = $(BMPINCDIR)/usblogo.h $(BMPINCDIR)/remote_usblogo.h \
|
||||
$(BMPINCDIR)/default_icons.h $(BMPINCDIR)/remote_default_icons.h \
|
||||
$(BMPINCDIR)/rockboxlogo.h $(BMPINCDIR)/remote_rockboxlogo.h \
|
||||
$(BMPINCDIR)/rockboxicon.h $(BMPINCDIR)/toolsicon.h
|
||||
$(BMPINCDIR)/rockboxlogo.h $(BMPINCDIR)/remote_rockboxlogo.h
|
||||
|
||||
$(BMPHFILES): $(BMPOBJ)
|
||||
|
||||
# pattern rules to create .c files from .bmp, one for each subdir:
|
||||
$(BUILDDIR)/apps/bitmaps/mono/%.c: $(ROOTDIR)/apps/bitmaps/mono/%.bmp $(TOOLSDIR)/bmp2rb
|
||||
$(SILENT)mkdir -p $(dir $@) $(BMPINCDIR)
|
||||
$(call PRINTS,BMP2RB $(<F))$(BMP2RB_MONO) -b -h $(BMPINCDIR) $< > $@
|
||||
$(call PRINTS,BMP2RB $(<F))$(BMP2RB_MONO) -h $(BMPINCDIR) $< > $@
|
||||
|
||||
$(BUILDDIR)/apps/bitmaps/native/%.c: $(ROOTDIR)/apps/bitmaps/native/%.bmp $(TOOLSDIR)/bmp2rb
|
||||
$(SILENT)mkdir -p $(dir $@) $(BMPINCDIR)
|
||||
$(call PRINTS,BMP2RB $(<F))$(BMP2RB_NATIVE) -b -h $(BMPINCDIR) $< > $@
|
||||
$(call PRINTS,BMP2RB $(<F))$(BMP2RB_NATIVE) -h $(BMPINCDIR) $< > $@
|
||||
|
||||
$(BUILDDIR)/apps/bitmaps/remote_mono/%.c: $(ROOTDIR)/apps/bitmaps/remote_mono/%.bmp $(TOOLSDIR)/bmp2rb
|
||||
$(SILENT)mkdir -p $(dir $@) $(BMPINCDIR)
|
||||
$(call PRINTS,BMP2RB $(<F))$(BMP2RB_REMOTEMONO) -b -h $(BMPINCDIR) $< > $@
|
||||
$(call PRINTS,BMP2RB $(<F))$(BMP2RB_REMOTEMONO) -h $(BMPINCDIR) $< > $@
|
||||
|
||||
$(BUILDDIR)/apps/bitmaps/remote_native/%.c: $(ROOTDIR)/apps/bitmaps/remote_native/%.bmp $(TOOLSDIR)/bmp2rb
|
||||
$(SILENT)mkdir -p $(dir $@) $(BMPINCDIR)
|
||||
$(call PRINTS,BMP2RB $(<F))$(BMP2RB_REMOTENATIVE) -b -h $(BMPINCDIR) $< > $@
|
||||
$(call PRINTS,BMP2RB $(<F))$(BMP2RB_REMOTENATIVE) -h $(BMPINCDIR) $< > $@
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
default_icons.bmp
|
||||
|
||||
#if (CONFIG_PLATFORM & PLATFORM_HOSTED) && defined(__APPLE__)
|
||||
osx_dummy.bmp
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#ifdef HAVE_LCD_BITMAP
|
||||
|
||||
/* Rockbox logo */
|
||||
#if (LCD_DEPTH == 1)
|
||||
#if (LCD_WIDTH == 160)
|
||||
|
|
@ -7,56 +9,34 @@ rockboxlogo.128x42x1.bmp
|
|||
#else
|
||||
rockboxlogo.112x30x1.bmp
|
||||
#endif
|
||||
#elif (LCD_WIDTH == 96) && (LCD_DEPTH >= 16)
|
||||
rockboxlogo.96x30x16.bmp
|
||||
#elif (LCD_WIDTH == 128) && (LCD_DEPTH == 2)
|
||||
rockboxlogo.128x42x2.bmp
|
||||
#elif (LCD_WIDTH == 128) && (LCD_DEPTH >= 16)
|
||||
#elif (LCD_WIDTH == 128) && (LCD_DEPTH == 16)
|
||||
rockboxlogo.128x40x16.bmp
|
||||
#elif (LCD_WIDTH == 132) && (LCD_DEPTH >= 16)
|
||||
#elif (LCD_WIDTH == 132) && (LCD_DEPTH == 16)
|
||||
rockboxlogo.132x40x16.bmp
|
||||
#elif (LCD_WIDTH == 138) && (LCD_DEPTH >= 2)
|
||||
#elif (LCD_WIDTH == 138) && (LCD_DEPTH == 2)
|
||||
rockboxlogo.138x46x2.bmp
|
||||
#elif (LCD_WIDTH == 160) && (LCD_DEPTH == 2)
|
||||
rockboxlogo.160x53x2.bmp
|
||||
#elif (LCD_WIDTH == 320) && (LCD_DEPTH == 2)
|
||||
rockboxlogo.160x53x2.bmp
|
||||
#elif (LCD_WIDTH == 160) && (LCD_DEPTH >= 16)
|
||||
#elif (LCD_WIDTH == 160) && (LCD_DEPTH == 16)
|
||||
rockboxlogo.160x50x16.bmp
|
||||
#elif (LCD_WIDTH == 176) && (LCD_DEPTH >= 16)
|
||||
#elif (LCD_WIDTH == 176) && (LCD_DEPTH == 16)
|
||||
rockboxlogo.176x54x16.bmp
|
||||
#elif (LCD_WIDTH == 220) && (LCD_DEPTH >= 16)
|
||||
#elif (LCD_WIDTH == 220) && (LCD_DEPTH == 16)
|
||||
rockboxlogo.220x68x16.bmp
|
||||
#elif (LCD_WIDTH == 240) && (LCD_DEPTH >= 16)
|
||||
#elif (LCD_WIDTH == 240) && (LCD_DEPTH == 16)
|
||||
rockboxlogo.240x74x16.bmp
|
||||
#elif (LCD_WIDTH >= 320) && (LCD_WIDTH < 480) && (LCD_DEPTH >= 16)
|
||||
#elif (LCD_WIDTH >= 320) && (LCD_WIDTH < 480) && (LCD_DEPTH == 16)
|
||||
rockboxlogo.320x98x16.bmp
|
||||
#elif (LCD_WIDTH >= 480) && (LCD_WIDTH < 640) && (LCD_DEPTH >= 16)
|
||||
#elif (LCD_WIDTH >= 480) && (LCD_WIDTH < 640) && (LCD_DEPTH == 16)
|
||||
rockboxlogo.480x149x16.bmp
|
||||
#elif (LCD_WIDTH >= 640) && (LCD_DEPTH >= 16)
|
||||
#elif (LCD_WIDTH >= 640) && (LCD_DEPTH == 16)
|
||||
rockboxlogo.640x198x16.bmp
|
||||
#endif
|
||||
|
||||
/* The Sony NWZ linux bootloader needs icons to display a menu */
|
||||
#if defined(BOOTLOADER)
|
||||
#if defined(SONY_NWZ_LINUX)
|
||||
rockboxicon.130x130x16.bmp
|
||||
toolsicon.130x130x16.bmp
|
||||
#elif defined(AGPTEK_ROCKER)
|
||||
hibyicon.70x70x16.bmp
|
||||
rockboxicon.70x70x16.bmp
|
||||
toolsicon.70x70x16.bmp
|
||||
#elif (defined(XDUOO_X3II) || defined(XDUOO_X20) || defined(EROS_Q))
|
||||
hibyicon.130x130x16.bmp
|
||||
rockboxicon.130x130x16.bmp
|
||||
toolsicon.130x130x16.bmp
|
||||
#elif defined(FIIO_M3K_LINUX)
|
||||
fiioicon.130x130x16.bmp
|
||||
rockboxicon.130x130x16.bmp
|
||||
toolsicon.130x130x16.bmp
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOTLOADER /* We don't need these for the bootloader */
|
||||
|
||||
/* USB logo */
|
||||
|
|
@ -65,8 +45,6 @@ toolsicon.130x130x16.bmp
|
|||
usblogo.176x48x16.bmp
|
||||
#elif LCD_WIDTH >= 128
|
||||
usblogo.128x37x16.bmp
|
||||
#elif LCD_WIDTH >= 88
|
||||
usblogo.88x24x16.bmp
|
||||
#endif
|
||||
#elif LCD_DEPTH > 1 /* greyscale */
|
||||
#ifdef IPOD_1G2G /* use firewire logo */
|
||||
|
|
@ -82,4 +60,15 @@ usblogo.104x27x1.bmp
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* List Icons */
|
||||
#if LCD_DEPTH == 16
|
||||
default_icons.6x8x16.bmp
|
||||
#elif LCD_DEPTH > 1 /* greyscale */
|
||||
default_icons.6x8x2.bmp
|
||||
#else
|
||||
default_icons.6x8x1.bmp
|
||||
#endif
|
||||
|
||||
#endif /* BOOTLOADER */
|
||||
|
||||
#endif /* HAVE_LCD_BITMAP */
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
BIN
apps/bitmaps/native/default_icons.6x8x16.bmp
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
|
@ -1,5 +1,3 @@
|
|||
remote_default_icons.bmp
|
||||
|
||||
#if (CONFIG_PLATFORM & PLATFORM_HOSTED) && defined(__APPLE__)
|
||||
osx_remote_dummy.bmp
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@
|
|||
#if (LCD_REMOTE_DEPTH == 1)
|
||||
remote_rockboxlogo.128x42x1.bmp
|
||||
remote_usblogo.104x27x1.bmp
|
||||
remote_default_icons.6x8x1.bmp
|
||||
#elif (LCD_REMOTE_DEPTH == 2)
|
||||
remote_rockboxlogo.128x42x2.bmp
|
||||
remote_usblogo.104x27x2.bmp
|
||||
remote_default_icons.6x8x2.bmp
|
||||
#endif
|
||||
|
||||
#endif /* BOOTLOADER */
|
||||
|
|
|
|||
BIN
apps/bitmaps/remote_native/remote_default_icons.6x8x1.bmp
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
apps/bitmaps/remote_native/remote_default_icons.6x8x2.bmp
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
1485
apps/bookmark.c
|
|
@ -23,26 +23,13 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
enum {
|
||||
BOOKMARK_FAIL = -1,
|
||||
BOOKMARK_SUCCESS = 0,
|
||||
BOOKMARK_USB_CONNECTED = 1
|
||||
};
|
||||
|
||||
enum {
|
||||
BOOKMARK_CANCEL,
|
||||
BOOKMARK_DONT_RESUME,
|
||||
BOOKMARK_DO_RESUME
|
||||
};
|
||||
|
||||
int bookmark_load_menu(void);
|
||||
bool bookmark_load_menu(void);
|
||||
bool bookmark_autobookmark(bool prompt_ok);
|
||||
bool bookmark_create_menu(void);
|
||||
bool bookmark_mrb_load(void);
|
||||
int bookmark_autoload(const char* file);
|
||||
bool bookmark_autoload(const char* file);
|
||||
bool bookmark_load(const char* file, bool autoload);
|
||||
bool bookmark_exists(void);
|
||||
bool bookmark_is_bookmarkable_state(void);
|
||||
|
||||
#endif /* __BOOKMARK_H__ */
|
||||
|
||||
|
|
|
|||
1323
apps/buffering.c
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include "config.h"
|
||||
#include "appevents.h"
|
||||
|
||||
|
||||
|
|
@ -36,7 +35,6 @@ enum data_type {
|
|||
TYPE_ATOMIC_AUDIO,
|
||||
TYPE_CUESHEET,
|
||||
TYPE_BITMAP,
|
||||
TYPE_RAW_ATOMIC,
|
||||
};
|
||||
|
||||
/* Error return values */
|
||||
|
|
@ -46,10 +44,10 @@ enum data_type {
|
|||
#define ERR_FILE_ERROR -4
|
||||
#define ERR_HANDLE_NOT_DONE -5
|
||||
#define ERR_UNSUPPORTED_TYPE -6
|
||||
#define ERR_BITMAP_TOO_LARGE -7
|
||||
|
||||
|
||||
/* Initialise the buffering subsystem */
|
||||
void buffering_init(void) INIT_ATTR;
|
||||
void buffering_init(void);
|
||||
|
||||
/* Reset the buffering system */
|
||||
bool buffering_reset(char *buf, size_t buflen);
|
||||
|
|
@ -67,13 +65,17 @@ bool buffering_reset(char *buf, size_t buflen);
|
|||
* bufftell : Return the handle's file read position
|
||||
* bufread : Copy data from a handle to a buffer
|
||||
* bufgetdata: Obtain a pointer for linear access to a "size" amount of data
|
||||
* bufgettail: Out-of-band get the last size bytes of a handle.
|
||||
* bufcuttail: Out-of-band remove the trailing 'size' bytes of a handle.
|
||||
*
|
||||
* NOTE: bufread and bufgetdata will block the caller until the requested
|
||||
* amount of data is ready (unless EOF is reached).
|
||||
* NOTE: Tail operations are only legal when the end of the file is buffered.
|
||||
****************************************************************************/
|
||||
|
||||
int bufopen(const char *file, off_t offset, enum data_type type,
|
||||
#define BUF_MAX_HANDLES 256
|
||||
|
||||
int bufopen(const char *file, size_t offset, enum data_type type,
|
||||
void *user_data);
|
||||
int bufalloc(const void *src, size_t size, enum data_type type);
|
||||
bool bufclose(int handle_id);
|
||||
|
|
@ -82,6 +84,8 @@ int bufadvance(int handle_id, off_t offset);
|
|||
off_t bufftell(int handle_id);
|
||||
ssize_t bufread(int handle_id, size_t size, void *dest);
|
||||
ssize_t bufgetdata(int handle_id, size_t size, void **data);
|
||||
ssize_t bufgettail(int handle_id, size_t size, void **data);
|
||||
ssize_t bufcuttail(int handle_id, size_t size);
|
||||
|
||||
/***************************************************************************
|
||||
* SECONDARY FUNCTIONS
|
||||
|
|
@ -97,19 +101,24 @@ ssize_t bufgetdata(int handle_id, size_t size, void **data);
|
|||
* buf_back_off_storage: tell buffering thread to take it easy
|
||||
****************************************************************************/
|
||||
|
||||
enum data_type buf_handle_data_type(int handle_id);
|
||||
ssize_t buf_handle_remaining(int handle_id);
|
||||
bool buf_is_handle(int handle_id);
|
||||
int buf_handle_data_type(int handle_id);
|
||||
off_t buf_filesize(int handle_id);
|
||||
off_t buf_handle_offset(int handle_id);
|
||||
off_t buf_handle_remaining(int handle_id);
|
||||
bool buf_pin_handle(int handle_id, bool pin);
|
||||
bool buf_signal_handle(int handle_id, bool signal);
|
||||
|
||||
ssize_t buf_handle_offset(int handle_id);
|
||||
void buf_set_base_handle(int handle_id);
|
||||
size_t buf_length(void);
|
||||
size_t buf_used(void);
|
||||
bool buf_pin_handle(int handle_id, bool pin);
|
||||
bool buf_signal_handle(int handle_id, bool signal);
|
||||
#ifdef HAVE_IO_PRIORITY
|
||||
void buf_back_off_storage(bool back_off);
|
||||
#endif
|
||||
|
||||
/* Settings */
|
||||
void buf_set_base_handle(int handle_id);
|
||||
enum {
|
||||
BUFFERING_SET_WATERMARK = 1,
|
||||
BUFFERING_SET_CHUNKSIZE,
|
||||
};
|
||||
void buf_set_watermark(size_t bytes);
|
||||
size_t buf_get_watermark(void);
|
||||
|
||||
|
|
@ -117,6 +126,7 @@ size_t buf_get_watermark(void);
|
|||
struct buffering_debug {
|
||||
int num_handles;
|
||||
size_t buffered_data;
|
||||
size_t wasted_space;
|
||||
size_t data_rem;
|
||||
size_t useful_data;
|
||||
size_t watermark;
|
||||
|
|
|
|||
|
|
@ -20,19 +20,16 @@
|
|||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "kernel.h"
|
||||
#include "codecs.h"
|
||||
#include "codec_thread.h"
|
||||
#include "pcmbuf.h"
|
||||
#include "audio_thread.h"
|
||||
#include "playback.h"
|
||||
#include "buffering.h"
|
||||
#include "dsp_core.h"
|
||||
#include "dsp.h"
|
||||
#include "metadata.h"
|
||||
#include "settings.h"
|
||||
|
||||
/* Define LOGF_ENABLE to enable logf output in this file */
|
||||
/*#define LOGF_ENABLE*/
|
||||
|
|
@ -80,26 +77,16 @@ struct codec_load_info
|
|||
static int codec_type = AFMT_UNKNOWN; /* Codec type (C,A-) */
|
||||
|
||||
/* Private interfaces to main playback control */
|
||||
extern void audio_codec_update_elapsed(unsigned long elapsed);
|
||||
extern void audio_codec_update_offset(size_t offset);
|
||||
extern void audio_codec_complete(int status);
|
||||
extern void audio_codec_seek_complete(void);
|
||||
extern void audio_codec_update_elapsed(unsigned long value);
|
||||
extern void audio_codec_update_offset(size_t value);
|
||||
extern void audio_queue_post(long id, intptr_t data);
|
||||
extern struct codec_api ci; /* from codecs.c */
|
||||
|
||||
/* Codec thread */
|
||||
static unsigned int codec_thread_id; /* For modifying thread priority later */
|
||||
static struct event_queue codec_queue SHAREDBSS_ATTR;
|
||||
static struct queue_sender_list codec_queue_sender_list SHAREDBSS_ATTR;
|
||||
|
||||
/* Workaround stack overflow in opus codec on highmem devices (see FS#13060). */
|
||||
/* Fixed 2019-8-14 (see FS#13131) */
|
||||
#if 0 /*!defined(CPU_COLDFIRE) && (MEMORYSIZE >= 8) && defined(IRAMSIZE) && IRAMSIZE > (32 * 1024)*/
|
||||
#define WORKAROUND_FS13060 0x800
|
||||
#else
|
||||
#define WORKAROUND_FS13060 0
|
||||
#endif
|
||||
|
||||
static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000 + WORKAROUND_FS13060)/sizeof(long)] IBSS_ATTR;
|
||||
static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)] IBSS_ATTR;
|
||||
static const char codec_thread_name[] = "codec";
|
||||
|
||||
static void unload_codec(void);
|
||||
|
|
@ -134,13 +121,13 @@ static int codec_check_queue__have_msg(void)
|
|||
switch (ev.id)
|
||||
{
|
||||
case Q_CODEC_SEEK:
|
||||
LOGFQUEUE("codec - Q_CODEC_SEEK %ld", ev.id);
|
||||
LOGFQUEUE("codec - Q_CODEC_SEEK", ev.id);
|
||||
return -1;
|
||||
case Q_CODEC_PAUSE:
|
||||
LOGFQUEUE("codec - Q_CODEC_PAUSE %ld", ev.id);
|
||||
LOGFQUEUE("codec - Q_CODEC_PAUSE", ev.id);
|
||||
return -1;
|
||||
case Q_CODEC_STOP:
|
||||
LOGFQUEUE("codec - Q_CODEC_STOP %ld", ev.id);
|
||||
LOGFQUEUE("codec - Q_CODEC_STOP", ev.id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -183,16 +170,14 @@ const char * get_codec_filename(int cod_spec)
|
|||
/* Can choose decoder or encoder if one available */
|
||||
int type = cod_spec & CODEC_TYPE_MASK;
|
||||
int afmt = cod_spec & CODEC_AFMT_MASK;
|
||||
int tmp_fmt = afmt;
|
||||
|
||||
if ((unsigned)afmt >= AFMT_NUM_CODECS)
|
||||
{
|
||||
type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
|
||||
tmp_fmt = AFMT_UNKNOWN;
|
||||
}
|
||||
|
||||
fname = (type == CODEC_TYPE_ENCODER) ?
|
||||
audio_formats[tmp_fmt].codec_enc_root_fn :
|
||||
audio_formats[tmp_fmt].codec_root_fn;
|
||||
|
||||
audio_formats[afmt].codec_enc_root_fn :
|
||||
audio_formats[afmt].codec_root_fn;
|
||||
|
||||
logf("%s: %d - %s",
|
||||
(type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
|
||||
afmt, fname ? fname : "<unknown>");
|
||||
|
|
@ -226,41 +211,49 @@ void codec_thread_do_callback(void (*fn)(void), unsigned int *id)
|
|||
static void codec_pcmbuf_insert_callback(
|
||||
const void *ch1, const void *ch2, int count)
|
||||
{
|
||||
struct dsp_buffer src;
|
||||
src.remcount = count;
|
||||
src.pin[0] = ch1;
|
||||
src.pin[1] = ch2;
|
||||
src.proc_mask = 0;
|
||||
const char *src[2] = { ch1, ch2 };
|
||||
|
||||
while (LIKELY(queue_empty(&codec_queue)) ||
|
||||
codec_check_queue__have_msg() >= 0)
|
||||
while (count > 0)
|
||||
{
|
||||
struct dsp_buffer dst;
|
||||
dst.remcount = 0;
|
||||
dst.bufcount = MAX(src.remcount, 1024); /* Arbitrary min request */
|
||||
int out_count = dsp_output_count(ci.dsp, count);
|
||||
int inp_count;
|
||||
char *dest;
|
||||
|
||||
if ((dst.p16out = pcmbuf_request_buffer(&dst.bufcount)) == NULL)
|
||||
while (1)
|
||||
{
|
||||
if ((dest = pcmbuf_request_buffer(&out_count)) != NULL)
|
||||
break;
|
||||
|
||||
cancel_cpu_boost();
|
||||
|
||||
/* It may be awhile before space is available but we want
|
||||
/* It will be awhile before space is available but we want
|
||||
"instant" response to any message */
|
||||
queue_wait_w_tmo(&codec_queue, NULL, HZ/20);
|
||||
}
|
||||
else
|
||||
{
|
||||
dsp_process(ci.dsp, &src, &dst);
|
||||
|
||||
if (dst.remcount > 0)
|
||||
{
|
||||
pcmbuf_write_complete(dst.remcount, ci.id3->elapsed,
|
||||
ci.id3->offset);
|
||||
}
|
||||
else if (src.remcount <= 0)
|
||||
{
|
||||
return; /* No input remains and DSP purged */
|
||||
}
|
||||
if (!queue_empty(&codec_queue) &&
|
||||
codec_check_queue__have_msg() < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the real input_size for output_size bytes, guarding
|
||||
* against resampling buffer overflows. */
|
||||
inp_count = dsp_input_count(ci.dsp, out_count);
|
||||
|
||||
if (inp_count <= 0)
|
||||
return;
|
||||
|
||||
/* Input size has grown, no error, just don't write more than length */
|
||||
if (inp_count > count)
|
||||
inp_count = count;
|
||||
|
||||
out_count = dsp_process(ci.dsp, dest, src, inp_count);
|
||||
|
||||
if (out_count <= 0)
|
||||
return;
|
||||
|
||||
pcmbuf_write_complete(out_count);
|
||||
|
||||
count -= inp_count;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -341,11 +334,9 @@ static void codec_seek_complete_callback(void)
|
|||
/* Clear DSP */
|
||||
dsp_configure(ci.dsp, DSP_FLUSH, 0);
|
||||
|
||||
/* Sync position */
|
||||
audio_codec_update_offset(ci.curpos);
|
||||
|
||||
/* Post notification to audio thread */
|
||||
audio_codec_seek_complete();
|
||||
LOGFQUEUE("audio > Q_AUDIO_CODEC_SEEK_COMPLETE");
|
||||
audio_queue_post(Q_AUDIO_CODEC_SEEK_COMPLETE, 0);
|
||||
|
||||
/* Wait for urgent or go message */
|
||||
do
|
||||
|
|
@ -357,10 +348,14 @@ static void codec_seek_complete_callback(void)
|
|||
|
||||
static void codec_configure_callback(int setting, intptr_t value)
|
||||
{
|
||||
dsp_configure(ci.dsp, setting, value);
|
||||
if (!dsp_configure(ci.dsp, setting, value))
|
||||
{
|
||||
logf("Illegal key: %d", setting);
|
||||
}
|
||||
}
|
||||
|
||||
static long codec_get_command_callback(intptr_t *param)
|
||||
static enum codec_command_action
|
||||
codec_get_command_callback(intptr_t *param)
|
||||
{
|
||||
yield();
|
||||
|
||||
|
|
@ -371,73 +366,58 @@ static long codec_get_command_callback(intptr_t *param)
|
|||
be expected) */
|
||||
while (1)
|
||||
{
|
||||
long action = CODEC_ACTION_NULL;
|
||||
enum codec_command_action action = CODEC_ACTION_NULL;
|
||||
struct queue_event ev;
|
||||
queue_wait(&codec_queue, &ev);
|
||||
|
||||
queue_peek(&codec_queue, &ev); /* Find out what it is */
|
||||
|
||||
intptr_t id = ev.id;
|
||||
|
||||
switch (id)
|
||||
switch (ev.id)
|
||||
{
|
||||
case Q_NULL:
|
||||
LOGFQUEUE("codec < Q_NULL");
|
||||
break;
|
||||
|
||||
case Q_CODEC_RUN: /* Already running */
|
||||
LOGFQUEUE("codec < Q_CODEC_RUN");
|
||||
break;
|
||||
|
||||
case Q_CODEC_PAUSE: /* Stay here and wait */
|
||||
LOGFQUEUE("codec < Q_CODEC_PAUSE");
|
||||
queue_wait(&codec_queue, &ev); /* Remove message */
|
||||
codec_queue_ack(Q_CODEC_PAUSE);
|
||||
queue_wait(&codec_queue, NULL); /* Wait for next (no remove) */
|
||||
continue;
|
||||
|
||||
case Q_CODEC_SEEK: /* Audio wants codec to seek */
|
||||
LOGFQUEUE("codec < Q_CODEC_SEEK %ld", ev.data);
|
||||
*param = ev.data;
|
||||
action = CODEC_ACTION_SEEK_TIME;
|
||||
trigger_cpu_boost();
|
||||
break;
|
||||
|
||||
case Q_CODEC_STOP: /* Must only return 0 in main loop */
|
||||
LOGFQUEUE("codec < Q_CODEC_STOP: %ld", ev.data);
|
||||
#ifdef HAVE_RECORDING
|
||||
if (type_is_encoder(codec_type))
|
||||
{
|
||||
/* Stream finish request (soft stop)? */
|
||||
if (ev.data && param)
|
||||
{
|
||||
/* ev.data is pointer to size */
|
||||
*param = ev.data;
|
||||
action = CODEC_ACTION_STREAM_FINISH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_RECORDING */
|
||||
{
|
||||
dsp_configure(ci.dsp, DSP_FLUSH, 0); /* Discontinuity */
|
||||
}
|
||||
|
||||
return CODEC_ACTION_HALT; /* Leave in queue */
|
||||
LOGFQUEUE("codec < Q_CODEC_STOP");
|
||||
action = CODEC_ACTION_HALT;
|
||||
break;
|
||||
|
||||
default: /* This is in error in this context. */
|
||||
ev.id = Q_NULL;
|
||||
logf("codec bad req %ld (%s)", ev.id, __func__);
|
||||
id = Q_NULL;
|
||||
}
|
||||
|
||||
queue_wait(&codec_queue, &ev); /* Actually remove it */
|
||||
codec_queue_ack(id);
|
||||
codec_queue_ack(ev.id);
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
||||
static bool codec_loop_track_callback(void)
|
||||
/* Initialize codec API */
|
||||
void codec_init_codec_api(void)
|
||||
{
|
||||
return global_settings.repeat_mode == REPEAT_ONE;
|
||||
ci.dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP,
|
||||
CODEC_IDX_AUDIO);
|
||||
ci.codec_get_buffer = codec_get_buffer_callback;
|
||||
ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
|
||||
ci.set_elapsed = audio_codec_update_elapsed;
|
||||
ci.read_filebuf = codec_filebuf_callback;
|
||||
ci.request_buffer = codec_request_buffer_callback;
|
||||
ci.advance_buffer = codec_advance_buffer_callback;
|
||||
ci.seek_buffer = codec_seek_buffer_callback;
|
||||
ci.seek_complete = codec_seek_complete_callback;
|
||||
ci.set_offset = audio_codec_update_offset;
|
||||
ci.configure = codec_configure_callback;
|
||||
ci.get_command = codec_get_command_callback;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -480,11 +460,18 @@ static void load_codec(const struct codec_load_info *ev_data)
|
|||
/* Either not a valid handle or the buffer method failed */
|
||||
const char *codec_fn = get_codec_filename(data.afmt);
|
||||
if (codec_fn)
|
||||
{
|
||||
#ifdef HAVE_IO_PRIORITY
|
||||
buf_back_off_storage(true);
|
||||
#endif
|
||||
status = codec_load_file(codec_fn, &ci);
|
||||
#ifdef HAVE_IO_PRIORITY
|
||||
buf_back_off_storage(false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Types must agree */
|
||||
if (status >= 0 && encoder == !!codec_get_enc_callback())
|
||||
if (status >= 0)
|
||||
{
|
||||
codec_type = data.afmt;
|
||||
codec_queue_ack(Q_CODEC_LOAD);
|
||||
|
|
@ -510,7 +497,6 @@ static void run_codec(void)
|
|||
codec_queue_ack(Q_CODEC_RUN);
|
||||
|
||||
trigger_cpu_boost();
|
||||
dsp_configure(ci.dsp, DSP_SET_OUT_FREQUENCY, pcmbuf_get_frequency());
|
||||
|
||||
if (!encoder)
|
||||
{
|
||||
|
|
@ -535,7 +521,8 @@ static void run_codec(void)
|
|||
|
||||
/* Notify audio that we're done for better or worse - advise of the
|
||||
status */
|
||||
audio_codec_complete(status);
|
||||
LOGFQUEUE("codec > audio Q_AUDIO_CODEC_COMPLETE: %d", status);
|
||||
audio_queue_post(Q_AUDIO_CODEC_COMPLETE, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -573,9 +560,9 @@ static void do_callback(void (* callback)(void))
|
|||
|
||||
if (callback)
|
||||
{
|
||||
commit_discard_idcache();
|
||||
cpucache_commit_discard();
|
||||
callback();
|
||||
commit_dcache();
|
||||
cpucache_commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -584,7 +571,7 @@ static void NORETURN_ATTR codec_thread(void)
|
|||
{
|
||||
struct queue_event ev;
|
||||
|
||||
while (1)
|
||||
while (1)
|
||||
{
|
||||
cancel_cpu_boost();
|
||||
|
||||
|
|
@ -630,34 +617,31 @@ static void NORETURN_ATTR codec_thread(void)
|
|||
|
||||
/** --- Miscellaneous external interfaces -- **/
|
||||
|
||||
/* Initialize playback's codec interface */
|
||||
void INIT_ATTR codec_thread_init(void)
|
||||
/* Create the codec thread and init kernel objects */
|
||||
void make_codec_thread(void)
|
||||
{
|
||||
/* Init API */
|
||||
ci.dsp = dsp_get_config(CODEC_IDX_AUDIO);
|
||||
ci.codec_get_buffer = codec_get_buffer_callback;
|
||||
ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
|
||||
ci.set_elapsed = audio_codec_update_elapsed;
|
||||
ci.read_filebuf = codec_filebuf_callback;
|
||||
ci.request_buffer = codec_request_buffer_callback;
|
||||
ci.advance_buffer = codec_advance_buffer_callback;
|
||||
ci.seek_buffer = codec_seek_buffer_callback;
|
||||
ci.seek_complete = codec_seek_complete_callback;
|
||||
ci.set_offset = audio_codec_update_offset;
|
||||
ci.configure = codec_configure_callback;
|
||||
ci.get_command = codec_get_command_callback;
|
||||
ci.loop_track = codec_loop_track_callback;
|
||||
|
||||
/* Init threading */
|
||||
queue_init(&codec_queue, false);
|
||||
codec_thread_id = create_thread(
|
||||
codec_thread, codec_stack, sizeof(codec_stack), 0,
|
||||
codec_thread, codec_stack, sizeof(codec_stack),
|
||||
CREATE_THREAD_FROZEN,
|
||||
codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
|
||||
IF_COP(, CPU));
|
||||
queue_enable_queue_send(&codec_queue, &codec_queue_sender_list,
|
||||
codec_thread_id);
|
||||
}
|
||||
|
||||
/* Unfreeze the codec thread */
|
||||
void codec_thread_resume(void)
|
||||
{
|
||||
thread_thaw(codec_thread_id);
|
||||
}
|
||||
|
||||
/* Is the current thread the codec thread? */
|
||||
bool is_codec_thread(void)
|
||||
{
|
||||
return thread_self() == codec_thread_id;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PRIORITY_SCHEDULING
|
||||
/* Obtain codec thread's current priority */
|
||||
int codec_thread_get_priority(void)
|
||||
|
|
@ -711,33 +695,10 @@ bool codec_pause(void)
|
|||
void codec_stop(void)
|
||||
{
|
||||
/* Wait until it's in the main loop */
|
||||
LOGFQUEUE("audio >| codec Q_CODEC_STOP: 0");
|
||||
LOGFQUEUE("audio >| codec Q_CODEC_STOP");
|
||||
while (codec_queue_send(Q_CODEC_STOP, 0) != Q_NULL);
|
||||
}
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
/* Tells codec to take final encoding step and then exit -
|
||||
Returns minimum buffer size required or 0 if complete */
|
||||
size_t codec_finish_stream(void)
|
||||
{
|
||||
size_t size = 0;
|
||||
|
||||
LOGFQUEUE("audio >| codec Q_CODEC_STOP: &size");
|
||||
if (codec_queue_send(Q_CODEC_STOP, (intptr_t)&size) != Q_NULL)
|
||||
{
|
||||
/* Sync to keep size in scope and get response */
|
||||
LOGFQUEUE("audio >| codec Q_NULL");
|
||||
codec_queue_send(Q_NULL, 0);
|
||||
|
||||
if (size == 0)
|
||||
codec_stop(); /* Replied with 0 size */
|
||||
}
|
||||
/* else thread running in the main loop */
|
||||
|
||||
return size;
|
||||
}
|
||||
#endif /* HAVE_RECORDING */
|
||||
|
||||
/* Call the codec's exit routine and close all references */
|
||||
void codec_unload(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,18 +23,20 @@
|
|||
#define _CODEC_THREAD_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "config.h"
|
||||
|
||||
/* codec identity */
|
||||
const char *get_codec_filename(int cod_spec);
|
||||
|
||||
/* codec thread */
|
||||
void codec_thread_init(void) INIT_ATTR;
|
||||
|
||||
/* Audio MUST be stopped before requesting callback! */
|
||||
void codec_thread_do_callback(void (*fn)(void),
|
||||
unsigned int *codec_thread_id);
|
||||
|
||||
void codec_init_codec_api(void);
|
||||
void make_codec_thread(void);
|
||||
void codec_thread_resume(void);
|
||||
bool is_codec_thread(void);
|
||||
#ifdef HAVE_PRIORITY_SCHEDULING
|
||||
int codec_thread_get_priority(void);
|
||||
int codec_thread_set_priority(int priority);
|
||||
|
|
@ -46,9 +48,6 @@ void codec_go(void);
|
|||
bool codec_pause(void);
|
||||
void codec_seek(long time);
|
||||
void codec_stop(void);
|
||||
#ifdef HAVE_RECORDING
|
||||
size_t codec_finish_stream(void);
|
||||
#endif
|
||||
void codec_unload(void);
|
||||
int codec_loaded(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "lang.h"
|
||||
#include "keyboard.h"
|
||||
#include "buffering.h"
|
||||
#include "mp3_playback.h"
|
||||
#include "backlight.h"
|
||||
#include "storage.h"
|
||||
#include "talk.h"
|
||||
|
|
@ -49,7 +50,6 @@
|
|||
#include "sound.h"
|
||||
#include "splash.h"
|
||||
#include "general.h"
|
||||
#include "rbpaths.h"
|
||||
|
||||
#define LOGF_ENABLE
|
||||
#include "logf.h"
|
||||
|
|
@ -70,6 +70,15 @@ extern unsigned char codecbuf[];
|
|||
|
||||
static size_t codec_size;
|
||||
|
||||
extern void* plugin_get_audio_buffer(size_t *buffer_size);
|
||||
|
||||
#if (CONFIG_PLATFORM & PLATFORM_NATIVE) && defined(HAVE_RECORDING)
|
||||
#undef open
|
||||
static int open(const char* pathname, int flags, ...)
|
||||
{
|
||||
return file_open(pathname, flags);
|
||||
}
|
||||
#endif
|
||||
struct codec_api ci = {
|
||||
|
||||
0, /* filesize */
|
||||
|
|
@ -88,8 +97,7 @@ struct codec_api ci = {
|
|||
NULL, /* set_offset */
|
||||
NULL, /* configure */
|
||||
NULL, /* get_command */
|
||||
NULL, /* loop_track */
|
||||
|
||||
|
||||
/* kernel/ system */
|
||||
#if defined(CPU_ARM) && CONFIG_PLATFORM & PLATFORM_NATIVE
|
||||
__div0,
|
||||
|
|
@ -106,9 +114,8 @@ struct codec_api ci = {
|
|||
semaphore_release,
|
||||
#endif
|
||||
|
||||
commit_dcache,
|
||||
commit_discard_dcache,
|
||||
commit_discard_idcache,
|
||||
cpucache_flush,
|
||||
cpucache_invalidate,
|
||||
|
||||
/* strings and memory */
|
||||
strcpy,
|
||||
|
|
@ -120,6 +127,7 @@ struct codec_api ci = {
|
|||
memmove,
|
||||
memcmp,
|
||||
memchr,
|
||||
strcasestr,
|
||||
#if defined(DEBUG) || defined(SIMULATOR)
|
||||
debugf,
|
||||
#endif
|
||||
|
|
@ -127,7 +135,8 @@ struct codec_api ci = {
|
|||
logf,
|
||||
#endif
|
||||
|
||||
(void *)qsort,
|
||||
(qsort_func)qsort,
|
||||
&global_settings,
|
||||
|
||||
#ifdef RB_PROFILE
|
||||
profile_thread,
|
||||
|
|
@ -137,19 +146,25 @@ struct codec_api ci = {
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
NULL, /* enc_pcmbuf_read */
|
||||
NULL, /* enc_pcmbuf_advance */
|
||||
NULL, /* enc_encbuf_get_buffer */
|
||||
NULL, /* enc_encbuf_finish_buffer */
|
||||
NULL, /* enc_stream_read */
|
||||
NULL, /* enc_stream_lseek */
|
||||
NULL, /* enc_stream_write */
|
||||
enc_get_inputs,
|
||||
enc_set_parameters,
|
||||
enc_get_chunk,
|
||||
enc_finish_chunk,
|
||||
enc_get_pcm_data,
|
||||
enc_unget_pcm_data,
|
||||
|
||||
/* file */
|
||||
(open_func)PREFIX(open),
|
||||
PREFIX(close),
|
||||
(read_func)PREFIX(read),
|
||||
PREFIX(lseek),
|
||||
(write_func)PREFIX(write),
|
||||
round_value_to_list32,
|
||||
|
||||
#endif /* HAVE_RECORDING */
|
||||
|
||||
/* new stuff at the end, sort into place next time
|
||||
the API gets incompatible */
|
||||
|
||||
};
|
||||
|
||||
void codec_get_full_path(char *path, const char *codec_root_fn)
|
||||
|
|
@ -203,9 +218,8 @@ static int codec_load_ram(struct codec_api *api)
|
|||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
if (hdr->api_version != CODEC_API_VERSION ||
|
||||
c_hdr->api_size > sizeof(struct codec_api))
|
||||
{
|
||||
if (hdr->api_version > CODEC_API_VERSION
|
||||
|| hdr->api_version < CODEC_MIN_API_VERSION) {
|
||||
logf("codec api version error");
|
||||
lc_close(curr_handle);
|
||||
curr_handle = NULL;
|
||||
|
|
@ -283,16 +297,3 @@ int codec_close(void)
|
|||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
enc_callback_t codec_get_enc_callback(void)
|
||||
{
|
||||
if (curr_handle == NULL ||
|
||||
c_hdr->lc_hdr.magic != CODEC_ENC_MAGIC) {
|
||||
logf("Codec: not an encoder");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return c_hdr->rec_extension[0];
|
||||
}
|
||||
#endif /* HAVE_RECORDING */
|
||||
|
|
|
|||
|
|
@ -22,30 +22,33 @@
|
|||
#define _CODECS_H_
|
||||
|
||||
/* instruct simulator code to not redefine any symbols when compiling codecs.
|
||||
(the CODEC macro is defined in codecs.make) */
|
||||
(the CODEC macro is defined in apps/codecs/Makefile) */
|
||||
#ifdef CODEC
|
||||
#define NO_REDEFINES_PLEASE
|
||||
#endif
|
||||
|
||||
#include "rbcodecconfig.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "strlcpy.h"
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "metadata.h"
|
||||
#include "audio.h"
|
||||
#ifdef RB_PROFILE
|
||||
#include "profile.h"
|
||||
#include "thread.h"
|
||||
#endif
|
||||
#if (CONFIG_CODEC == SWCODEC)
|
||||
#ifdef HAVE_RECORDING
|
||||
#include "enc_base.h"
|
||||
#include "pcm_record.h"
|
||||
#endif
|
||||
#include "dsp_core.h"
|
||||
#include "dsp_misc.h"
|
||||
#include "dsp-util.h"
|
||||
#include "dsp.h"
|
||||
#endif
|
||||
#include "settings.h"
|
||||
|
||||
#include "gcc_extensions.h"
|
||||
#include "load_code.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef CODEC
|
||||
#if defined(DEBUG) || defined(SIMULATOR)
|
||||
#undef DEBUGF
|
||||
|
|
@ -71,12 +74,13 @@
|
|||
/* magic for encoder codecs */
|
||||
#define CODEC_ENC_MAGIC 0x52454E43 /* RENC */
|
||||
|
||||
/*
|
||||
* Increment this whenever a change breaks the codec ABI,
|
||||
* when this happens please take the opportunity to sort in
|
||||
* any new functions "waiting" at the end of the list.
|
||||
*/
|
||||
#define CODEC_API_VERSION 50
|
||||
/* increase this every time the api struct changes */
|
||||
#define CODEC_API_VERSION 42
|
||||
|
||||
/* update this to latest version if a change to the api struct breaks
|
||||
backwards compatibility (and please take the opportunity to sort in any
|
||||
new function which are "waiting" at the end of the function table) */
|
||||
#define CODEC_MIN_API_VERSION 42
|
||||
|
||||
/* reasons for calling codec main entrypoint */
|
||||
enum codec_entry_call_reason {
|
||||
|
|
@ -95,11 +99,6 @@ enum codec_command_action {
|
|||
CODEC_ACTION_HALT = -1,
|
||||
CODEC_ACTION_NULL = 0,
|
||||
CODEC_ACTION_SEEK_TIME = 1,
|
||||
#ifdef HAVE_RECORDING
|
||||
CODEC_ACTION_STREAM_FINISH = 2,
|
||||
#endif
|
||||
CODEC_ACTION_MIN = LONG_MIN,
|
||||
CODEC_ACTION_MAX = LONG_MAX,
|
||||
};
|
||||
|
||||
/* NOTE: To support backwards compatibility, only add new functions at
|
||||
|
|
@ -111,13 +110,13 @@ enum codec_command_action {
|
|||
struct codec_api {
|
||||
off_t filesize; /* Total file length */
|
||||
off_t curpos; /* Current buffer position */
|
||||
|
||||
|
||||
struct mp3entry *id3; /* TAG metadata pointer */
|
||||
int audio_hid; /* Current audio handle */
|
||||
|
||||
|
||||
/* The dsp instance to be used for audio output */
|
||||
struct dsp_config *dsp;
|
||||
|
||||
|
||||
/* Returns buffer to malloc array. Only codeclib should need this. */
|
||||
void* (*codec_get_buffer)(size_t *size);
|
||||
/* Insert PCM data into audio buffer for playback. Playback will start
|
||||
|
|
@ -125,7 +124,7 @@ struct codec_api {
|
|||
void (*pcmbuf_insert)(const void *ch1, const void *ch2, int count);
|
||||
/* Set song position in WPS (value in ms). */
|
||||
void (*set_elapsed)(unsigned long value);
|
||||
|
||||
|
||||
/* Read next <size> amount bytes from file buffer to <ptr>.
|
||||
Will return number of bytes read or 0 if end of file. */
|
||||
size_t (*read_filebuf)(void *ptr, size_t size);
|
||||
|
|
@ -145,9 +144,7 @@ struct codec_api {
|
|||
/* Configure different codec buffer parameters. */
|
||||
void (*configure)(int setting, intptr_t value);
|
||||
/* Obtain command action on what to do next */
|
||||
long (*get_command)(intptr_t *param);
|
||||
/* Determine whether the track should be looped, if applicable. */
|
||||
bool (*loop_track)(void);
|
||||
enum codec_command_action (*get_command)(intptr_t *param);
|
||||
|
||||
/* kernel/ system */
|
||||
#if defined(CPU_ARM) && CONFIG_PLATFORM & PLATFORM_NATIVE
|
||||
|
|
@ -170,9 +167,8 @@ struct codec_api {
|
|||
void (*semaphore_release)(struct semaphore *s);
|
||||
#endif /* NUM_CORES */
|
||||
|
||||
void (*commit_dcache)(void);
|
||||
void (*commit_discard_dcache)(void);
|
||||
void (*commit_discard_idcache)(void);
|
||||
void (*cpucache_flush)(void);
|
||||
void (*cpucache_invalidate)(void);
|
||||
|
||||
/* strings and memory */
|
||||
char* (*strcpy)(char *dst, const char *src);
|
||||
|
|
@ -184,6 +180,7 @@ struct codec_api {
|
|||
void* (*memmove)(void *out, const void *in, size_t n);
|
||||
int (*memcmp)(const void *s1, const void *s2, size_t n);
|
||||
void *(*memchr)(const void *s1, int c, size_t n);
|
||||
char *(*strcasestr) (const char* phaystack, const char* pneedle);
|
||||
|
||||
#if defined(DEBUG) || defined(SIMULATOR)
|
||||
void (*debugf)(const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2);
|
||||
|
|
@ -196,26 +193,35 @@ struct codec_api {
|
|||
void (*qsort)(void *base, size_t nmemb, size_t size,
|
||||
int(*compar)(const void *, const void *));
|
||||
|
||||
/* The ADX codec accesses global_settings to test for REPEAT_ONE mode */
|
||||
struct user_settings* global_settings;
|
||||
|
||||
#ifdef RB_PROFILE
|
||||
void (*profile_thread)(void);
|
||||
void (*profstop)(void);
|
||||
void (*profile_func_enter)(void *this_fn, void *call_site);
|
||||
void (*profile_func_exit)(void *this_fn, void *call_site);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
int (*enc_pcmbuf_read)(void *buf, int count);
|
||||
int (*enc_pcmbuf_advance)(int count);
|
||||
struct enc_chunk_data * (*enc_encbuf_get_buffer)(size_t need);
|
||||
void (*enc_encbuf_finish_buffer)(void);
|
||||
ssize_t (*enc_stream_read)(void *buf, size_t count);
|
||||
off_t (*enc_stream_lseek)(off_t offset, int whence);
|
||||
ssize_t (*enc_stream_write)(const void *buf, size_t count);
|
||||
void (*enc_get_inputs)(struct enc_inputs *inputs);
|
||||
void (*enc_set_parameters)(struct enc_parameters *params);
|
||||
struct enc_chunk_hdr * (*enc_get_chunk)(void);
|
||||
void (*enc_finish_chunk)(void);
|
||||
unsigned char * (*enc_get_pcm_data)(size_t size);
|
||||
size_t (*enc_unget_pcm_data)(size_t size);
|
||||
|
||||
/* file */
|
||||
int (*open)(const char* pathname, int flags, ...);
|
||||
int (*close)(int fd);
|
||||
ssize_t (*read)(int fd, void* buf, size_t count);
|
||||
off_t (*lseek)(int fd, off_t offset, int whence);
|
||||
ssize_t (*write)(int fd, const void* buf, size_t count);
|
||||
int (*round_value_to_list32)(unsigned long value,
|
||||
const unsigned long list[],
|
||||
int count,
|
||||
bool signd);
|
||||
#endif /* HAVE_RECORDING */
|
||||
#endif
|
||||
|
||||
/* new stuff at the end, sort into place next time
|
||||
the API gets incompatible */
|
||||
|
|
@ -227,8 +233,6 @@ struct codec_header {
|
|||
enum codec_status(*entry_point)(enum codec_entry_call_reason reason);
|
||||
enum codec_status(*run_proc)(void);
|
||||
struct codec_api **api;
|
||||
size_t api_size;
|
||||
void * rec_extension[]; /* extension for encoders */
|
||||
};
|
||||
|
||||
#ifdef CODEC
|
||||
|
|
@ -241,16 +245,15 @@ extern unsigned char plugin_end_addr[];
|
|||
const struct codec_header __header \
|
||||
__attribute__ ((section (".header")))= { \
|
||||
{ CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
|
||||
plugin_start_addr, plugin_end_addr }, \
|
||||
codec_start, codec_run, &ci, sizeof(struct codec_api) };
|
||||
plugin_start_addr, plugin_end_addr }, codec_start, \
|
||||
codec_run, &ci };
|
||||
/* encoders */
|
||||
#define CODEC_ENC_HEADER \
|
||||
const struct codec_header __header \
|
||||
__attribute__ ((section (".header")))= { \
|
||||
{ CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
|
||||
plugin_start_addr, plugin_end_addr }, \
|
||||
codec_start, codec_run, &ci, sizeof(struct codec_api), \
|
||||
{ enc_callback } };
|
||||
plugin_start_addr, plugin_end_addr }, codec_start, \
|
||||
codec_run, &ci };
|
||||
|
||||
#else /* def SIMULATOR */
|
||||
/* decoders */
|
||||
|
|
@ -258,14 +261,12 @@ extern unsigned char plugin_end_addr[];
|
|||
const struct codec_header __header \
|
||||
__attribute__((visibility("default"))) = { \
|
||||
{ CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, NULL, NULL }, \
|
||||
codec_start, codec_run, &ci, sizeof(struct codec_api) };
|
||||
codec_start, codec_run, &ci };
|
||||
/* encoders */
|
||||
#define CODEC_ENC_HEADER \
|
||||
const struct codec_header __header \
|
||||
__attribute__((visibility("default"))) = { \
|
||||
const struct codec_header __header = { \
|
||||
{ CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, NULL, NULL }, \
|
||||
codec_start, codec_run, &ci, sizeof(struct codec_api), \
|
||||
{ enc_callback } };
|
||||
codec_start, codec_run, &ci };
|
||||
#endif /* SIMULATOR */
|
||||
#endif /* CODEC */
|
||||
|
||||
|
|
@ -280,19 +281,11 @@ void *codec_get_buffer_callback(size_t *size);
|
|||
int codec_load_buf(int hid, struct codec_api *api);
|
||||
int codec_load_file(const char* codec, struct codec_api *api);
|
||||
int codec_run_proc(void);
|
||||
int codec_halt(void);
|
||||
int codec_close(void);
|
||||
#if defined(HAVE_RECORDING)
|
||||
enc_callback_t codec_get_enc_callback(void);
|
||||
#endif
|
||||
|
||||
/* defined by the codec */
|
||||
enum codec_status codec_start(enum codec_entry_call_reason reason);
|
||||
enum codec_status codec_main(enum codec_entry_call_reason reason);
|
||||
enum codec_status codec_run(void);
|
||||
#if defined(HAVE_RECORDING)
|
||||
int enc_callback(enum enc_callback_reason reason, void *params);
|
||||
#else
|
||||
#define codec_get_enc_callback() NULL
|
||||
#endif
|
||||
|
||||
#endif /* _CODECS_H_ */
|
||||
46
apps/codecs/SOURCES
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* decoders */
|
||||
|
||||
vorbis.c
|
||||
mpa.c
|
||||
flac.c
|
||||
wav.c
|
||||
a52.c
|
||||
wavpack.c
|
||||
#ifndef RB_PROFILE
|
||||
alac.c
|
||||
#endif
|
||||
cook.c
|
||||
raac.c
|
||||
a52_rm.c
|
||||
atrac3_rm.c
|
||||
atrac3_oma.c
|
||||
mpc.c
|
||||
wma.c
|
||||
sid.c
|
||||
ape.c
|
||||
nsf.c
|
||||
asap.c
|
||||
aac.c
|
||||
spc.c
|
||||
mod.c
|
||||
shorten.c
|
||||
aiff.c
|
||||
speex.c
|
||||
adx.c
|
||||
smaf.c
|
||||
au.c
|
||||
vox.c
|
||||
wav64.c
|
||||
tta.c
|
||||
wmapro.c
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
|
||||
/* encoders */
|
||||
|
||||
aiff_enc.c
|
||||
mp3_enc.c
|
||||
wav_enc.c
|
||||
wavpack_enc.c
|
||||
|
||||
#endif /* HAVE_RECORDING */
|
||||
190
apps/codecs/a52.c
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Dave Chapman
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "codeclib.h"
|
||||
#include <inttypes.h> /* Needed by a52.h */
|
||||
#include <codecs/liba52/config-a52.h>
|
||||
#include <codecs/liba52/a52.h>
|
||||
|
||||
CODEC_HEADER
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
#define A52_SAMPLESPERFRAME (6*256)
|
||||
|
||||
static a52_state_t *state;
|
||||
static unsigned long samplesdone;
|
||||
static unsigned long frequency;
|
||||
|
||||
/* used outside liba52 */
|
||||
static uint8_t buf[3840] IBSS_ATTR;
|
||||
|
||||
static inline void output_audio(sample_t *samples)
|
||||
{
|
||||
ci->yield();
|
||||
ci->pcmbuf_insert(&samples[0], &samples[256], 256);
|
||||
}
|
||||
|
||||
static void a52_decode_data(uint8_t *start, uint8_t *end)
|
||||
{
|
||||
static uint8_t *bufptr = buf;
|
||||
static uint8_t *bufpos = buf + 7;
|
||||
/*
|
||||
* sample_rate and flags are static because this routine could
|
||||
* exit between the a52_syncinfo() and the ao_setup(), and we want
|
||||
* to have the same values when we get back !
|
||||
*/
|
||||
static int sample_rate;
|
||||
static int flags;
|
||||
int bit_rate;
|
||||
int len;
|
||||
|
||||
while (1) {
|
||||
len = end - start;
|
||||
if (!len)
|
||||
break;
|
||||
if (len > bufpos - bufptr)
|
||||
len = bufpos - bufptr;
|
||||
memcpy(bufptr, start, len);
|
||||
bufptr += len;
|
||||
start += len;
|
||||
if (bufptr == bufpos) {
|
||||
if (bufpos == buf + 7) {
|
||||
int length;
|
||||
|
||||
length = a52_syncinfo(buf, &flags, &sample_rate, &bit_rate);
|
||||
if (!length) {
|
||||
//DEBUGF("skip\n");
|
||||
for (bufptr = buf; bufptr < buf + 6; bufptr++)
|
||||
bufptr[0] = bufptr[1];
|
||||
continue;
|
||||
}
|
||||
bufpos = buf + length;
|
||||
} else {
|
||||
/* Unity gain is 1 << 26, and we want to end up on 28 bits
|
||||
of precision instead of the default 30.
|
||||
*/
|
||||
level_t level = 1 << 24;
|
||||
sample_t bias = 0;
|
||||
int i;
|
||||
|
||||
/* This is the configuration for the downmixing: */
|
||||
flags = A52_STEREO | A52_ADJUST_LEVEL;
|
||||
|
||||
if (a52_frame(state, buf, &flags, &level, bias))
|
||||
goto error;
|
||||
a52_dynrng(state, NULL, NULL);
|
||||
frequency = sample_rate;
|
||||
|
||||
/* An A52 frame consists of 6 blocks of 256 samples
|
||||
So we decode and output them one block at a time */
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (a52_block(state))
|
||||
goto error;
|
||||
output_audio(a52_samples(state));
|
||||
samplesdone += 256;
|
||||
}
|
||||
ci->set_elapsed(samplesdone/(frequency/1000));
|
||||
bufptr = buf;
|
||||
bufpos = buf + 7;
|
||||
continue;
|
||||
error:
|
||||
//logf("Error decoding A52 stream\n");
|
||||
bufptr = buf;
|
||||
bufpos = buf + 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* this is the codec entry point */
|
||||
enum codec_status codec_main(enum codec_entry_call_reason reason)
|
||||
{
|
||||
if (reason == CODEC_LOAD) {
|
||||
/* Generic codec initialisation */
|
||||
ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
|
||||
ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
|
||||
}
|
||||
else if (reason == CODEC_UNLOAD) {
|
||||
if (state)
|
||||
a52_free(state);
|
||||
}
|
||||
|
||||
return CODEC_OK;
|
||||
}
|
||||
|
||||
/* this is called for each file to process */
|
||||
enum codec_status codec_run(void)
|
||||
{
|
||||
size_t n;
|
||||
unsigned char *filebuf;
|
||||
int sample_loc;
|
||||
intptr_t param;
|
||||
|
||||
if (codec_init())
|
||||
return CODEC_ERROR;
|
||||
|
||||
ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
|
||||
codec_set_replaygain(ci->id3);
|
||||
|
||||
/* Intialise the A52 decoder and check for success */
|
||||
state = a52_init(0);
|
||||
|
||||
/* The main decoding loop */
|
||||
if (ci->id3->offset) {
|
||||
if (ci->seek_buffer(ci->id3->offset)) {
|
||||
samplesdone = (ci->id3->offset / ci->id3->bytesperframe) *
|
||||
A52_SAMPLESPERFRAME;
|
||||
ci->set_elapsed(samplesdone/(ci->id3->frequency / 1000));
|
||||
}
|
||||
}
|
||||
else {
|
||||
ci->seek_buffer(ci->id3->first_frame_offset);
|
||||
samplesdone = 0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
enum codec_command_action action = ci->get_command(¶m);
|
||||
|
||||
if (action == CODEC_ACTION_HALT)
|
||||
break;
|
||||
|
||||
if (action == CODEC_ACTION_SEEK_TIME) {
|
||||
sample_loc = param/1000 * ci->id3->frequency;
|
||||
|
||||
if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) {
|
||||
samplesdone = sample_loc;
|
||||
ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
|
||||
}
|
||||
ci->seek_complete();
|
||||
}
|
||||
|
||||
filebuf = ci->request_buffer(&n, BUFFER_SIZE);
|
||||
|
||||
if (n == 0) /* End of Stream */
|
||||
break;
|
||||
|
||||
a52_decode_data(filebuf, filebuf + n);
|
||||
ci->advance_buffer(n);
|
||||
}
|
||||
|
||||
return CODEC_OK;
|
||||
}
|
||||
224
apps/codecs/a52_rm.c
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2009 Mohamed Tarek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "codeclib.h"
|
||||
#include <codecs/librm/rm.h>
|
||||
#include <inttypes.h> /* Needed by a52.h */
|
||||
#include <codecs/liba52/config-a52.h>
|
||||
#include <codecs/liba52/a52.h>
|
||||
|
||||
CODEC_HEADER
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
#define A52_SAMPLESPERFRAME (6*256)
|
||||
|
||||
static a52_state_t *state;
|
||||
static unsigned long samplesdone;
|
||||
static unsigned long frequency;
|
||||
static RMContext rmctx;
|
||||
static RMPacket pkt;
|
||||
|
||||
static void init_rm(RMContext *rmctx)
|
||||
{
|
||||
memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext));
|
||||
}
|
||||
|
||||
/* used outside liba52 */
|
||||
static uint8_t buf[3840] IBSS_ATTR;
|
||||
|
||||
/* The following two functions, a52_decode_data and output_audio are taken from apps/codecs/a52.c */
|
||||
static inline void output_audio(sample_t *samples)
|
||||
{
|
||||
ci->yield();
|
||||
ci->pcmbuf_insert(&samples[0], &samples[256], 256);
|
||||
}
|
||||
|
||||
static void a52_decode_data(uint8_t *start, uint8_t *end)
|
||||
{
|
||||
static uint8_t *bufptr = buf;
|
||||
static uint8_t *bufpos = buf + 7;
|
||||
/*
|
||||
* sample_rate and flags are static because this routine could
|
||||
* exit between the a52_syncinfo() and the ao_setup(), and we want
|
||||
* to have the same values when we get back !
|
||||
*/
|
||||
static int sample_rate;
|
||||
static int flags;
|
||||
int bit_rate;
|
||||
int len;
|
||||
|
||||
while (1) {
|
||||
len = end - start;
|
||||
if (!len)
|
||||
break;
|
||||
if (len > bufpos - bufptr)
|
||||
len = bufpos - bufptr;
|
||||
memcpy(bufptr, start, len);
|
||||
bufptr += len;
|
||||
start += len;
|
||||
if (bufptr == bufpos) {
|
||||
if (bufpos == buf + 7) {
|
||||
int length;
|
||||
|
||||
length = a52_syncinfo(buf, &flags, &sample_rate, &bit_rate);
|
||||
if (!length) {
|
||||
//DEBUGF("skip\n");
|
||||
for (bufptr = buf; bufptr < buf + 6; bufptr++)
|
||||
bufptr[0] = bufptr[1];
|
||||
continue;
|
||||
}
|
||||
bufpos = buf + length;
|
||||
} else {
|
||||
/* Unity gain is 1 << 26, and we want to end up on 28 bits
|
||||
of precision instead of the default 30.
|
||||
*/
|
||||
level_t level = 1 << 24;
|
||||
sample_t bias = 0;
|
||||
int i;
|
||||
|
||||
/* This is the configuration for the downmixing: */
|
||||
flags = A52_STEREO | A52_ADJUST_LEVEL;
|
||||
|
||||
if (a52_frame(state, buf, &flags, &level, bias))
|
||||
goto error;
|
||||
a52_dynrng(state, NULL, NULL);
|
||||
frequency = sample_rate;
|
||||
|
||||
/* An A52 frame consists of 6 blocks of 256 samples
|
||||
So we decode and output them one block at a time */
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (a52_block(state))
|
||||
goto error;
|
||||
output_audio(a52_samples(state));
|
||||
samplesdone += 256;
|
||||
}
|
||||
ci->set_elapsed(samplesdone/(frequency/1000));
|
||||
bufptr = buf;
|
||||
bufpos = buf + 7;
|
||||
continue;
|
||||
error:
|
||||
//logf("Error decoding A52 stream\n");
|
||||
bufptr = buf;
|
||||
bufpos = buf + 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* this is the codec entry point */
|
||||
enum codec_status codec_main(enum codec_entry_call_reason reason)
|
||||
{
|
||||
if (reason == CODEC_LOAD) {
|
||||
/* Generic codec initialisation */
|
||||
ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
|
||||
ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
|
||||
}
|
||||
else if (reason == CODEC_UNLOAD) {
|
||||
if (state)
|
||||
a52_free(state);
|
||||
}
|
||||
|
||||
return CODEC_OK;
|
||||
}
|
||||
|
||||
/* this is called for each file to process */
|
||||
enum codec_status codec_run(void)
|
||||
{
|
||||
size_t n;
|
||||
uint8_t *filebuf;
|
||||
int consumed, packet_offset;
|
||||
int playback_on = -1;
|
||||
size_t resume_offset;
|
||||
intptr_t param;
|
||||
enum codec_command_action action = CODEC_ACTION_NULL;
|
||||
|
||||
if (codec_init()) {
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
resume_offset = ci->id3->offset;
|
||||
|
||||
ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
|
||||
codec_set_replaygain(ci->id3);
|
||||
|
||||
ci->seek_buffer(ci->id3->first_frame_offset);
|
||||
|
||||
/* Intializations */
|
||||
state = a52_init(0);
|
||||
ci->memset(&rmctx,0,sizeof(RMContext));
|
||||
ci->memset(&pkt,0,sizeof(RMPacket));
|
||||
init_rm(&rmctx);
|
||||
|
||||
/* check for a mid-track resume and force a seek time accordingly */
|
||||
if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
|
||||
resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
|
||||
/* put number of subpackets to skip in resume_offset */
|
||||
resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE);
|
||||
param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
|
||||
action = CODEC_ACTION_SEEK_TIME;
|
||||
}
|
||||
else {
|
||||
/* Seek to the first packet */
|
||||
ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE );
|
||||
}
|
||||
|
||||
/* The main decoding loop */
|
||||
while((unsigned)rmctx.audio_pkt_cnt < rmctx.nb_packets) {
|
||||
if (action == CODEC_ACTION_NULL)
|
||||
action = ci->get_command(¶m);
|
||||
|
||||
if (action == CODEC_ACTION_HALT)
|
||||
break;
|
||||
|
||||
if (action == CODEC_ACTION_SEEK_TIME) {
|
||||
packet_offset = param / ((rmctx.block_align*8*1000)/rmctx.bit_rate);
|
||||
ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE +
|
||||
packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE));
|
||||
rmctx.audio_pkt_cnt = packet_offset;
|
||||
samplesdone = (rmctx.sample_rate/1000 * param);
|
||||
ci->set_elapsed(samplesdone/(frequency/1000));
|
||||
ci->seek_complete();
|
||||
}
|
||||
|
||||
action = CODEC_ACTION_NULL;
|
||||
|
||||
filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE);
|
||||
consumed = rm_get_packet(&filebuf, &rmctx, &pkt);
|
||||
|
||||
if(consumed < 0 && playback_on != 0) {
|
||||
if(playback_on == -1) {
|
||||
/* Error only if packet-parsing failed and playback hadn't started */
|
||||
DEBUGF("rm_get_packet failed\n");
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
playback_on = 1;
|
||||
a52_decode_data(filebuf, filebuf + rmctx.block_align);
|
||||
ci->advance_buffer(pkt.length);
|
||||
}
|
||||
|
||||
return CODEC_OK;
|
||||
}
|
||||
295
apps/codecs/aac.c
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Dave Chapman
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "codeclib.h"
|
||||
#include "libm4a/m4a.h"
|
||||
#include "libfaad/common.h"
|
||||
#include "libfaad/structs.h"
|
||||
#include "libfaad/decoder.h"
|
||||
|
||||
CODEC_HEADER
|
||||
|
||||
/* The maximum buffer size handled by faad. 12 bytes are required by libfaad
|
||||
* as headroom (see libfaad/bits.c). FAAD_BYTE_BUFFER_SIZE bytes are buffered
|
||||
* for each frame. */
|
||||
#define FAAD_BYTE_BUFFER_SIZE (2048-12)
|
||||
|
||||
/* this is the codec entry point */
|
||||
enum codec_status codec_main(enum codec_entry_call_reason reason)
|
||||
{
|
||||
if (reason == CODEC_LOAD) {
|
||||
/* Generic codec initialisation */
|
||||
ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
|
||||
ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
|
||||
}
|
||||
|
||||
return CODEC_OK;
|
||||
}
|
||||
|
||||
/* this is called for each file to process */
|
||||
enum codec_status codec_run(void)
|
||||
{
|
||||
/* Note that when dealing with QuickTime/MPEG4 files, terminology is
|
||||
* a bit confusing. Files with sound are split up in chunks, where
|
||||
* each chunk contains one or more samples. Each sample in turn
|
||||
* contains a number of "sound samples" (the kind you refer to with
|
||||
* the sampling frequency).
|
||||
*/
|
||||
size_t n;
|
||||
demux_res_t demux_res;
|
||||
stream_t input_stream;
|
||||
uint32_t sound_samples_done;
|
||||
uint32_t elapsed_time;
|
||||
int file_offset;
|
||||
int framelength;
|
||||
int lead_trim = 0;
|
||||
unsigned int frame_samples;
|
||||
unsigned int i;
|
||||
unsigned char* buffer;
|
||||
NeAACDecFrameInfo frame_info;
|
||||
NeAACDecHandle decoder;
|
||||
int err;
|
||||
uint32_t seek_idx = 0;
|
||||
uint32_t s = 0;
|
||||
uint32_t sbr_fac = 1;
|
||||
unsigned char c = 0;
|
||||
void *ret;
|
||||
intptr_t param;
|
||||
bool empty_first_frame = false;
|
||||
|
||||
/* Clean and initialize decoder structures */
|
||||
memset(&demux_res , 0, sizeof(demux_res));
|
||||
if (codec_init()) {
|
||||
LOGF("FAAD: Codec init error\n");
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
file_offset = ci->id3->offset;
|
||||
|
||||
ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
|
||||
codec_set_replaygain(ci->id3);
|
||||
|
||||
stream_create(&input_stream,ci);
|
||||
|
||||
ci->seek_buffer(ci->id3->first_frame_offset);
|
||||
|
||||
/* if qtmovie_read returns successfully, the stream is up to
|
||||
* the movie data, which can be used directly by the decoder */
|
||||
if (!qtmovie_read(&input_stream, &demux_res)) {
|
||||
LOGF("FAAD: File init error\n");
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
/* initialise the sound converter */
|
||||
decoder = NeAACDecOpen();
|
||||
|
||||
if (!decoder) {
|
||||
LOGF("FAAD: Decode open error\n");
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
|
||||
conf->outputFormat = FAAD_FMT_24BIT; /* irrelevant, we don't convert */
|
||||
NeAACDecSetConfiguration(decoder, conf);
|
||||
|
||||
err = NeAACDecInit2(decoder, demux_res.codecdata, demux_res.codecdata_len, &s, &c);
|
||||
if (err) {
|
||||
LOGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type);
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
#ifdef SBR_DEC
|
||||
/* Check for need of special handling for seek/resume and elapsed time. */
|
||||
if (ci->id3->needs_upsampling_correction) {
|
||||
sbr_fac = 2;
|
||||
} else {
|
||||
sbr_fac = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
i = 0;
|
||||
|
||||
if (file_offset > 0) {
|
||||
/* Resume the desired (byte) position. Important: When resuming SBR
|
||||
* upsampling files the resulting sound_samples_done must be expanded
|
||||
* by a factor of 2. This is done via using sbr_fac. */
|
||||
if (m4a_seek_raw(&demux_res, &input_stream, file_offset,
|
||||
&sound_samples_done, (int*) &i)) {
|
||||
sound_samples_done *= sbr_fac;
|
||||
elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
|
||||
ci->set_elapsed(elapsed_time);
|
||||
} else {
|
||||
sound_samples_done = 0;
|
||||
}
|
||||
NeAACDecPostSeekReset(decoder, i);
|
||||
} else {
|
||||
sound_samples_done = 0;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
lead_trim = ci->id3->lead_trim;
|
||||
}
|
||||
|
||||
/* The main decoding loop */
|
||||
while (i < demux_res.num_sample_byte_sizes) {
|
||||
enum codec_command_action action = ci->get_command(¶m);
|
||||
|
||||
if (action == CODEC_ACTION_HALT)
|
||||
break;
|
||||
|
||||
/* Deal with any pending seek requests */
|
||||
if (action == CODEC_ACTION_SEEK_TIME) {
|
||||
/* Seek to the desired time position. Important: When seeking in SBR
|
||||
* upsampling files the seek_time must be divided by 2 when calling
|
||||
* m4a_seek and the resulting sound_samples_done must be expanded
|
||||
* by a factor 2. This is done via using sbr_fac. */
|
||||
if (m4a_seek(&demux_res, &input_stream,
|
||||
(param/10/sbr_fac)*(ci->id3->frequency/100),
|
||||
&sound_samples_done, (int*) &i)) {
|
||||
sound_samples_done *= sbr_fac;
|
||||
elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
|
||||
ci->set_elapsed(elapsed_time);
|
||||
seek_idx = 0;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
lead_trim = ci->id3->lead_trim;
|
||||
}
|
||||
}
|
||||
NeAACDecPostSeekReset(decoder, i);
|
||||
ci->seek_complete();
|
||||
}
|
||||
|
||||
/* There can be gaps between chunks, so skip ahead if needed. It
|
||||
* doesn't seem to happen much, but it probably means that a
|
||||
* "proper" file can have chunks out of order. Why one would want
|
||||
* that an good question (but files with gaps do exist, so who
|
||||
* knows?), so we don't support that - for now, at least.
|
||||
*/
|
||||
file_offset = m4a_check_sample_offset(&demux_res, i, &seek_idx);
|
||||
|
||||
if (file_offset > ci->curpos)
|
||||
{
|
||||
ci->advance_buffer(file_offset - ci->curpos);
|
||||
}
|
||||
else if (file_offset == 0)
|
||||
{
|
||||
LOGF("AAC: get_sample_offset error\n");
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
/* Request the required number of bytes from the input buffer */
|
||||
buffer=ci->request_buffer(&n, FAAD_BYTE_BUFFER_SIZE);
|
||||
|
||||
/* Decode one block - returned samples will be host-endian */
|
||||
ret = NeAACDecDecode(decoder, &frame_info, buffer, n);
|
||||
|
||||
/* NeAACDecDecode may sometimes return NULL without setting error. */
|
||||
if (ret == NULL || frame_info.error > 0) {
|
||||
LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
/* Advance codec buffer (no need to call set_offset because of this) */
|
||||
ci->advance_buffer(frame_info.bytesconsumed);
|
||||
|
||||
/* Output the audio */
|
||||
ci->yield();
|
||||
|
||||
frame_samples = frame_info.samples >> 1;
|
||||
|
||||
if (empty_first_frame)
|
||||
{
|
||||
/* Remove the first frame from lead_trim, under the assumption
|
||||
* that it had the same size as this frame
|
||||
*/
|
||||
empty_first_frame = false;
|
||||
lead_trim -= frame_samples;
|
||||
|
||||
if (lead_trim < 0)
|
||||
{
|
||||
lead_trim = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Gather number of samples for the decoded frame. */
|
||||
framelength = frame_samples - lead_trim;
|
||||
|
||||
if (i == demux_res.num_sample_byte_sizes - 1)
|
||||
{
|
||||
// Size of the last frame
|
||||
const uint32_t sample_duration = (demux_res.num_time_to_samples > 0) ?
|
||||
demux_res.time_to_sample[demux_res.num_time_to_samples - 1].sample_duration :
|
||||
frame_samples;
|
||||
|
||||
/* Currently limited to at most one frame of tail_trim.
|
||||
* Seems to be enough.
|
||||
*/
|
||||
if (ci->id3->tail_trim == 0 && sample_duration < frame_samples)
|
||||
{
|
||||
/* Subtract lead_trim just in case we decode a file with only
|
||||
* one audio frame with actual data (lead_trim is usually zero
|
||||
* here).
|
||||
*/
|
||||
framelength = sample_duration - lead_trim;
|
||||
}
|
||||
else
|
||||
{
|
||||
framelength -= ci->id3->tail_trim;
|
||||
}
|
||||
}
|
||||
|
||||
if (framelength > 0)
|
||||
{
|
||||
ci->pcmbuf_insert(&decoder->time_out[0][lead_trim],
|
||||
&decoder->time_out[1][lead_trim],
|
||||
framelength);
|
||||
sound_samples_done += framelength;
|
||||
/* Update the elapsed-time indicator */
|
||||
elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
|
||||
ci->set_elapsed(elapsed_time);
|
||||
}
|
||||
|
||||
if (lead_trim > 0)
|
||||
{
|
||||
/* frame_info.samples can be 0 for frame 0. We still want to
|
||||
* remove it from lead_trim, so do that during frame 1.
|
||||
*/
|
||||
if (0 == i && 0 == frame_info.samples)
|
||||
{
|
||||
empty_first_frame = true;
|
||||
}
|
||||
|
||||
lead_trim -= frame_samples;
|
||||
|
||||
if (lead_trim < 0)
|
||||
{
|
||||
lead_trim = 0;
|
||||
}
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
LOGF("AAC: Decoded %lu samples\n", (unsigned long)sound_samples_done);
|
||||
return CODEC_OK;
|
||||
}
|
||||
393
apps/codecs/adx.c
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
*
|
||||
* Copyright (C) 2006-2008 Adam Gashlin (hcs)
|
||||
* Copyright (C) 2006 Jens Arnold
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <limits.h>
|
||||
#include "codeclib.h"
|
||||
#include "inttypes.h"
|
||||
#include "math.h"
|
||||
#include "lib/fixedpoint.h"
|
||||
|
||||
CODEC_HEADER
|
||||
|
||||
/* Maximum number of bytes to process in one iteration */
|
||||
#define WAV_CHUNK_SIZE (1024*2)
|
||||
|
||||
/* Number of times to loop looped tracks when repeat is disabled */
|
||||
#define LOOP_TIMES 2
|
||||
|
||||
/* Length of fade-out for looped tracks (milliseconds) */
|
||||
#define FADE_LENGTH 10000L
|
||||
|
||||
/* Default high pass filter cutoff frequency is 500 Hz.
|
||||
* Others can be set, but the default is nearly always used,
|
||||
* and there is no way to determine if another was used, anyway.
|
||||
*/
|
||||
static const long cutoff = 500;
|
||||
|
||||
static int16_t samples[WAV_CHUNK_SIZE] IBSS_ATTR;
|
||||
|
||||
/* this is the codec entry point */
|
||||
enum codec_status codec_main(enum codec_entry_call_reason reason)
|
||||
{
|
||||
if (reason == CODEC_LOAD) {
|
||||
/* Generic codec initialisation */
|
||||
/* we only render 16 bits */
|
||||
ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
|
||||
}
|
||||
|
||||
return CODEC_OK;
|
||||
}
|
||||
|
||||
/* this is called for each file to process */
|
||||
enum codec_status codec_run(void)
|
||||
{
|
||||
int channels;
|
||||
int sampleswritten, i;
|
||||
uint8_t *buf;
|
||||
int32_t ch1_1, ch1_2, ch2_1, ch2_2; /* ADPCM history */
|
||||
size_t n;
|
||||
int endofstream; /* end of stream flag */
|
||||
uint32_t avgbytespersec;
|
||||
int looping; /* looping flag */
|
||||
int loop_count; /* number of loops done so far */
|
||||
int fade_count; /* countdown for fadeout */
|
||||
int fade_frames; /* length of fade in frames */
|
||||
off_t start_adr, end_adr; /* loop points */
|
||||
off_t chanstart, bufoff;
|
||||
/*long coef1=0x7298L,coef2=-0x3350L;*/
|
||||
long coef1, coef2;
|
||||
intptr_t param;
|
||||
|
||||
DEBUGF("ADX: next_track\n");
|
||||
if (codec_init()) {
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
DEBUGF("ADX: after init\n");
|
||||
|
||||
/* init history */
|
||||
ch1_1=ch1_2=ch2_1=ch2_2=0;
|
||||
|
||||
codec_set_replaygain(ci->id3);
|
||||
|
||||
/* Get header */
|
||||
DEBUGF("ADX: request initial buffer\n");
|
||||
ci->seek_buffer(0);
|
||||
buf = ci->request_buffer(&n, 0x38);
|
||||
if (!buf || n < 0x38) {
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
bufoff = 0;
|
||||
DEBUGF("ADX: read size = %lx\n",(unsigned long)n);
|
||||
|
||||
/* Get file header for starting offset, channel count */
|
||||
|
||||
chanstart = ((buf[2] << 8) | buf[3]) + 4;
|
||||
channels = buf[7];
|
||||
|
||||
/* useful for seeking and reporting current playback position */
|
||||
avgbytespersec = ci->id3->frequency * 18 * channels / 32;
|
||||
DEBUGF("avgbytespersec=%ld\n",(unsigned long)avgbytespersec);
|
||||
|
||||
/* calculate filter coefficients */
|
||||
|
||||
/**
|
||||
* A simple table of these coefficients would be nice, but
|
||||
* some very odd frequencies are used and if I'm going to
|
||||
* interpolate I might as well just go all the way and
|
||||
* calclate them precisely.
|
||||
* Speed is not an issue as this only needs to be done once per file.
|
||||
*/
|
||||
{
|
||||
const int64_t big28 = 0x10000000LL;
|
||||
const int64_t big32 = 0x100000000LL;
|
||||
int64_t frequency = ci->id3->frequency;
|
||||
int64_t phasemultiple = cutoff*big32/frequency;
|
||||
|
||||
long z;
|
||||
int64_t a;
|
||||
const int64_t b = (M_SQRT2*big28)-big28;
|
||||
int64_t c;
|
||||
int64_t d;
|
||||
|
||||
fp_sincos((unsigned long)phasemultiple,&z);
|
||||
|
||||
a = (M_SQRT2*big28) - (z >> 3);
|
||||
|
||||
/**
|
||||
* In the long passed to fsqrt there are only 4 nonfractional bits,
|
||||
* which is sufficient here, but this is the only reason why I don't
|
||||
* use 32 fractional bits everywhere.
|
||||
*/
|
||||
d = fp_sqrt((a+b)*(a-b)/big28,28);
|
||||
c = (a-d)*big28/b;
|
||||
|
||||
coef1 = (c*8192) >> 28;
|
||||
coef2 = (c*c/big28*-4096) >> 28;
|
||||
DEBUGF("ADX: samprate=%ld ",(long)frequency);
|
||||
DEBUGF("coef1 %04x ",(unsigned int)(coef1*4));
|
||||
DEBUGF("coef2 %04x\n",(unsigned int)(coef2*-4));
|
||||
}
|
||||
|
||||
/* Get loop data */
|
||||
|
||||
looping = 0; start_adr = 0; end_adr = 0;
|
||||
if (!memcmp(buf+0x10,"\x01\xF4\x03\x00",4)) {
|
||||
/* Soul Calibur 2 style (type 03) */
|
||||
DEBUGF("ADX: type 03 found\n");
|
||||
/* check if header is too small for loop data */
|
||||
if (chanstart-6 < 0x2c) looping=0;
|
||||
else {
|
||||
looping = (buf[0x18]) ||
|
||||
(buf[0x19]) ||
|
||||
(buf[0x1a]) ||
|
||||
(buf[0x1b]);
|
||||
end_adr = (buf[0x28]<<24) |
|
||||
(buf[0x29]<<16) |
|
||||
(buf[0x2a]<<8) |
|
||||
(buf[0x2b]);
|
||||
|
||||
start_adr = (
|
||||
(buf[0x1c]<<24) |
|
||||
(buf[0x1d]<<16) |
|
||||
(buf[0x1e]<<8) |
|
||||
(buf[0x1f])
|
||||
)/32*channels*18+chanstart;
|
||||
}
|
||||
} else if (!memcmp(buf+0x10,"\x01\xF4\x04\x00",4)) {
|
||||
/* Standard (type 04) */
|
||||
DEBUGF("ADX: type 04 found\n");
|
||||
/* check if header is too small for loop data */
|
||||
if (chanstart-6 < 0x38) looping=0;
|
||||
else {
|
||||
looping = (buf[0x24]) ||
|
||||
(buf[0x25]) ||
|
||||
(buf[0x26]) ||
|
||||
(buf[0x27]);
|
||||
end_adr = (buf[0x34]<<24) |
|
||||
(buf[0x35]<<16) |
|
||||
(buf[0x36]<<8) |
|
||||
buf[0x37];
|
||||
start_adr = (
|
||||
(buf[0x28]<<24) |
|
||||
(buf[0x29]<<16) |
|
||||
(buf[0x2a]<<8) |
|
||||
(buf[0x2b])
|
||||
)/32*channels*18+chanstart;
|
||||
}
|
||||
} else {
|
||||
DEBUGF("ADX: error, couldn't determine ADX type\n");
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
if (looping) {
|
||||
DEBUGF("ADX: looped, start: %lx end: %lx\n",start_adr,end_adr);
|
||||
} else {
|
||||
DEBUGF("ADX: not looped\n");
|
||||
}
|
||||
|
||||
/* advance to first frame */
|
||||
DEBUGF("ADX: first frame at %lx\n",chanstart);
|
||||
bufoff = chanstart;
|
||||
|
||||
/* get in position */
|
||||
ci->seek_buffer(bufoff);
|
||||
|
||||
|
||||
/* setup pcm buffer format */
|
||||
ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
|
||||
if (channels == 2) {
|
||||
ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
|
||||
} else if (channels == 1) {
|
||||
ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
|
||||
} else {
|
||||
DEBUGF("ADX CODEC_ERROR: more than 2 channels\n");
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
endofstream = 0;
|
||||
loop_count = 0;
|
||||
fade_count = -1; /* disable fade */
|
||||
fade_frames = 1;
|
||||
|
||||
/* The main decoder loop */
|
||||
|
||||
while (!endofstream) {
|
||||
enum codec_command_action action = ci->get_command(¶m);
|
||||
|
||||
if (action == CODEC_ACTION_HALT)
|
||||
break;
|
||||
|
||||
/* do we need to loop? */
|
||||
if (bufoff > end_adr-18*channels && looping) {
|
||||
DEBUGF("ADX: loop!\n");
|
||||
/* check for endless looping */
|
||||
if (ci->global_settings->repeat_mode==REPEAT_ONE) {
|
||||
loop_count=0;
|
||||
fade_count = -1; /* disable fade */
|
||||
} else {
|
||||
/* otherwise start fade after LOOP_TIMES loops */
|
||||
loop_count++;
|
||||
if (loop_count >= LOOP_TIMES && fade_count < 0) {
|
||||
/* frames to fade over */
|
||||
fade_frames = FADE_LENGTH*ci->id3->frequency/32/1000;
|
||||
/* volume relative to fade_frames */
|
||||
fade_count = fade_frames;
|
||||
DEBUGF("ADX: fade_frames = %d\n",fade_frames);
|
||||
}
|
||||
}
|
||||
bufoff = start_adr;
|
||||
ci->seek_buffer(bufoff);
|
||||
}
|
||||
|
||||
/* do we need to seek? */
|
||||
if (action == CODEC_ACTION_SEEK_TIME) {
|
||||
uint32_t newpos;
|
||||
|
||||
DEBUGF("ADX: seek to %ldms\n", (long)param);
|
||||
|
||||
endofstream = 0;
|
||||
loop_count = 0;
|
||||
fade_count = -1; /* disable fade */
|
||||
fade_frames = 1;
|
||||
|
||||
newpos = (((uint64_t)avgbytespersec*param)
|
||||
/ (1000LL*18*channels))*(18*channels);
|
||||
bufoff = chanstart + newpos;
|
||||
while (bufoff > end_adr-18*channels) {
|
||||
bufoff-=end_adr-start_adr;
|
||||
loop_count++;
|
||||
}
|
||||
ci->seek_buffer(bufoff);
|
||||
ci->seek_complete();
|
||||
}
|
||||
|
||||
if (bufoff>ci->filesize-channels*18) break; /* End of stream */
|
||||
|
||||
sampleswritten=0;
|
||||
|
||||
while (
|
||||
/* Is there data left in the file? */
|
||||
(bufoff <= ci->filesize-(18*channels)) &&
|
||||
/* Is there space in the output buffer? */
|
||||
(sampleswritten <= WAV_CHUNK_SIZE-(32*channels)) &&
|
||||
/* Should we be looping? */
|
||||
((!looping) || bufoff <= end_adr-18*channels))
|
||||
{
|
||||
/* decode first/only channel */
|
||||
int32_t scale;
|
||||
int32_t ch1_0, d;
|
||||
|
||||
/* fetch a frame */
|
||||
buf = ci->request_buffer(&n, 18);
|
||||
|
||||
if (!buf || n!=18) {
|
||||
DEBUGF("ADX: couldn't get buffer at %lx\n",
|
||||
bufoff);
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
scale = ((buf[0] << 8) | (buf[1])) +1;
|
||||
|
||||
for (i = 2; i < 18; i++)
|
||||
{
|
||||
d = (buf[i] >> 4) & 15;
|
||||
if (d & 8) d-= 16;
|
||||
ch1_0 = d*scale + ((coef1*ch1_1 + coef2*ch1_2) >> 12);
|
||||
if (ch1_0 > 32767) ch1_0 = 32767;
|
||||
else if (ch1_0 < -32768) ch1_0 = -32768;
|
||||
samples[sampleswritten] = ch1_0;
|
||||
sampleswritten+=channels;
|
||||
ch1_2 = ch1_1; ch1_1 = ch1_0;
|
||||
|
||||
d = buf[i] & 15;
|
||||
if (d & 8) d -= 16;
|
||||
ch1_0 = d*scale + ((coef1*ch1_1 + coef2*ch1_2) >> 12);
|
||||
if (ch1_0 > 32767) ch1_0 = 32767;
|
||||
else if (ch1_0 < -32768) ch1_0 = -32768;
|
||||
samples[sampleswritten] = ch1_0;
|
||||
sampleswritten+=channels;
|
||||
ch1_2 = ch1_1; ch1_1 = ch1_0;
|
||||
}
|
||||
bufoff+=18;
|
||||
ci->advance_buffer(18);
|
||||
|
||||
if (channels == 2) {
|
||||
/* decode second channel */
|
||||
int32_t scale;
|
||||
int32_t ch2_0, d;
|
||||
|
||||
buf = ci->request_buffer(&n, 18);
|
||||
|
||||
if (!buf || n!=18) {
|
||||
DEBUGF("ADX: couldn't get buffer at %lx\n",
|
||||
bufoff);
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
scale = ((buf[0] << 8)|(buf[1]))+1;
|
||||
|
||||
sampleswritten-=63;
|
||||
|
||||
for (i = 2; i < 18; i++)
|
||||
{
|
||||
d = (buf[i] >> 4) & 15;
|
||||
if (d & 8) d-= 16;
|
||||
ch2_0 = d*scale + ((coef1*ch2_1 + coef2*ch2_2) >> 12);
|
||||
if (ch2_0 > 32767) ch2_0 = 32767;
|
||||
else if (ch2_0 < -32768) ch2_0 = -32768;
|
||||
samples[sampleswritten] = ch2_0;
|
||||
sampleswritten+=2;
|
||||
ch2_2 = ch2_1; ch2_1 = ch2_0;
|
||||
|
||||
d = buf[i] & 15;
|
||||
if (d & 8) d -= 16;
|
||||
ch2_0 = d*scale + ((coef1*ch2_1 + coef2*ch2_2) >> 12);
|
||||
if (ch2_0 > 32767) ch2_0 = 32767;
|
||||
else if (ch2_0 < -32768) ch2_0 = -32768;
|
||||
samples[sampleswritten] = ch2_0;
|
||||
sampleswritten+=2;
|
||||
ch2_2 = ch2_1; ch2_1 = ch2_0;
|
||||
}
|
||||
bufoff+=18;
|
||||
ci->advance_buffer(18);
|
||||
sampleswritten--; /* go back to first channel's next sample */
|
||||
}
|
||||
|
||||
if (fade_count>0) {
|
||||
fade_count--;
|
||||
for (i=0;i<(channels==1?32:64);i++) samples[sampleswritten-i-1]=
|
||||
((int32_t)samples[sampleswritten-i-1])*fade_count/fade_frames;
|
||||
if (fade_count==0) {endofstream=1; break;}
|
||||
}
|
||||
}
|
||||
|
||||
if (channels == 2)
|
||||
sampleswritten >>= 1; /* make samples/channel */
|
||||
|
||||
ci->pcmbuf_insert(samples, NULL, sampleswritten);
|
||||
|
||||
ci->set_elapsed(
|
||||
((end_adr-start_adr)*loop_count + bufoff-chanstart)*
|
||||
1000LL/avgbytespersec);
|
||||
}
|
||||
|
||||
return CODEC_OK;
|
||||
}
|
||||
348
apps/codecs/aiff.c
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2005 Jvo Studer
|
||||
* Copyright (c) 2009 Yoshihisa Uchida
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "codeclib.h"
|
||||
#include "codecs/libpcm/support_formats.h"
|
||||
|
||||
CODEC_HEADER
|
||||
|
||||
#define FOURCC(c1, c2, c3, c4) \
|
||||
((((uint32_t)c1)<<24)|(((uint32_t)c2)<<16)|(((uint32_t)c3)<<8)|((uint32_t)c4))
|
||||
|
||||
/* This codec supports the following AIFC compressionType formats */
|
||||
enum {
|
||||
AIFC_FORMAT_PCM = FOURCC('N', 'O', 'N', 'E'), /* AIFC PCM Format (big endian) */
|
||||
AIFC_FORMAT_ALAW = FOURCC('a', 'l', 'a', 'w'), /* AIFC ALaw compressed */
|
||||
AIFC_FORMAT_MULAW = FOURCC('u', 'l', 'a', 'w'), /* AIFC uLaw compressed */
|
||||
AIFC_FORMAT_IEEE_FLOAT32 = FOURCC('f', 'l', '3', '2'), /* AIFC IEEE float 32 bit */
|
||||
AIFC_FORMAT_IEEE_FLOAT64 = FOURCC('f', 'l', '6', '4'), /* AIFC IEEE float 64 bit */
|
||||
AIFC_FORMAT_QT_IMA_ADPCM = FOURCC('i', 'm', 'a', '4'), /* AIFC QuickTime IMA ADPCM */
|
||||
};
|
||||
|
||||
static const struct pcm_entry pcm_codecs[] = {
|
||||
{ AIFC_FORMAT_PCM, get_linear_pcm_codec },
|
||||
{ AIFC_FORMAT_ALAW, get_itut_g711_alaw_codec },
|
||||
{ AIFC_FORMAT_MULAW, get_itut_g711_mulaw_codec },
|
||||
{ AIFC_FORMAT_IEEE_FLOAT32, get_ieee_float_codec },
|
||||
{ AIFC_FORMAT_IEEE_FLOAT64, get_ieee_float_codec },
|
||||
{ AIFC_FORMAT_QT_IMA_ADPCM, get_qt_ima_adpcm_codec },
|
||||
};
|
||||
|
||||
#define PCM_SAMPLE_SIZE (1024*2)
|
||||
|
||||
static int32_t samples[PCM_SAMPLE_SIZE] IBSS_ATTR;
|
||||
|
||||
static const struct pcm_codec *get_codec(uint32_t formattag)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < sizeof(pcm_codecs)/sizeof(pcm_codecs[0]); i++)
|
||||
if (pcm_codecs[i].format_tag == formattag)
|
||||
return pcm_codecs[i].get_codec();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* this is the codec entry point */
|
||||
enum codec_status codec_main(enum codec_entry_call_reason reason)
|
||||
{
|
||||
if (reason == CODEC_LOAD) {
|
||||
/* Generic codec initialisation */
|
||||
ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
|
||||
}
|
||||
|
||||
return CODEC_OK;
|
||||
}
|
||||
|
||||
/* this is called for each file to process */
|
||||
enum codec_status codec_run(void)
|
||||
{
|
||||
struct pcm_format format;
|
||||
uint32_t bytesdone, decodedsamples;
|
||||
/* rockbox: comment 'set but unused' variables
|
||||
uint32_t num_sample_frames = 0;
|
||||
*/
|
||||
size_t n;
|
||||
int bufcount;
|
||||
int endofstream;
|
||||
unsigned char *buf;
|
||||
uint8_t *aifbuf;
|
||||
uint32_t offset2snd = 0;
|
||||
off_t firstblockposn; /* position of the first block in file */
|
||||
bool is_aifc = false;
|
||||
const struct pcm_codec *codec;
|
||||
uint32_t size;
|
||||
intptr_t param;
|
||||
|
||||
if (codec_init()) {
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
codec_set_replaygain(ci->id3);
|
||||
|
||||
/* Need to save offset for later use (cleared indirectly by advance_buffer) */
|
||||
bytesdone = ci->id3->offset;
|
||||
|
||||
/* assume the AIFF header is less than 1024 bytes */
|
||||
ci->seek_buffer(0);
|
||||
buf = ci->request_buffer(&n, 1024);
|
||||
if (n < 54) {
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
if (memcmp(buf, "FORM", 4) != 0)
|
||||
{
|
||||
DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]);
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
if (memcmp(&buf[8], "AIFF", 4) == 0)
|
||||
is_aifc = false;
|
||||
else if (memcmp(&buf[8], "AIFC", 4) == 0)
|
||||
is_aifc = true;
|
||||
else
|
||||
{
|
||||
DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]);
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
|
||||
buf += 12;
|
||||
n -= 12;
|
||||
|
||||
ci->memset(&format, 0, sizeof(struct pcm_format));
|
||||
format.is_signed = true;
|
||||
format.is_little_endian = false;
|
||||
|
||||
decodedsamples = 0;
|
||||
codec = 0;
|
||||
|
||||
/* read until 'SSND' chunk, which typically is last */
|
||||
while (format.numbytes == 0 && n >= 8)
|
||||
{
|
||||
/* chunkSize */
|
||||
size = ((buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7]);
|
||||
if (memcmp(buf, "COMM", 4) == 0) {
|
||||
if ((!is_aifc && size < 18) || (is_aifc && size < 22))
|
||||
{
|
||||
DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n",
|
||||
(unsigned long)size, (is_aifc)?22:18);
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
/* num_channels */
|
||||
format.channels = ((buf[8]<<8)|buf[9]);
|
||||
/* num_sample_frames */
|
||||
/*
|
||||
num_sample_frames = ((buf[10]<<24)|(buf[11]<<16)|(buf[12]<<8)
|
||||
|buf[13]);
|
||||
*/
|
||||
|
||||
/* sample_size */
|
||||
format.bitspersample = ((buf[14]<<8)|buf[15]);
|
||||
/* sample_rate (don't use last 4 bytes, only integer fs) */
|
||||
if (buf[16] != 0x40) {
|
||||
DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n");
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1;
|
||||
format.samplespersec >>= (16 + 14 - buf[17]);
|
||||
/* compressionType (AIFC only) */
|
||||
if (is_aifc)
|
||||
{
|
||||
format.formattag = (buf[26]<<24)|(buf[27]<<16)|(buf[28]<<8)|buf[29];
|
||||
|
||||
/*
|
||||
* aiff's sample_size is uncompressed sound data size.
|
||||
* But format.bitspersample is compressed sound data size.
|
||||
*/
|
||||
if (format.formattag == AIFC_FORMAT_ALAW ||
|
||||
format.formattag == AIFC_FORMAT_MULAW)
|
||||
format.bitspersample = 8;
|
||||
else if (format.formattag == AIFC_FORMAT_QT_IMA_ADPCM)
|
||||
format.bitspersample = 4;
|
||||
}
|
||||
else
|
||||
format.formattag = AIFC_FORMAT_PCM;
|
||||
/* calc average bytes per second */
|
||||
format.avgbytespersec = format.samplespersec*format.channels*format.bitspersample/8;
|
||||
} else if (memcmp(buf, "SSND", 4)==0) {
|
||||
if (format.bitspersample == 0) {
|
||||
DEBUGF("CODEC_ERROR: unsupported chunk order\n");
|
||||
return CODEC_ERROR;
|
||||
}
|
||||
/* offset2snd */
|
||||
offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11];
|
||||
/* block_size */
|
||||
format.blockalign = ((buf[12]<<24)|(buf[13]<<16)|(buf[14]<<8)|buf[15]) >> 3;
|
||||
if (format.blockalign == 0)
|
||||
format.blockalign = format.channels * format.bitspersample >> 3;
|
||||
format.numbytes = size - 8 - offset2snd;
|
||||
size = 8 + offset2snd; /* advance to the beginning of data */
|
||||
} else if (is_aifc && (memcmp(buf, "FVER", 4)==0)) {
|
||||
/* Format Version Chunk (AIFC only chunk) */
|
||||
/* skip this chunk */
|
||||
} else {
|
||||
DEBUGF("unsupported AIFF chunk: '%c%c%c%c', size=%lu\n",
|
||||
buf[0], buf[1], buf[2], buf[3], (unsigned long)size);
|
||||
}
|
||||
|
||||