├── .github └── workflows │ ├── backup-to-gitlab.yml │ ├── call-auto-tag.yml │ ├── call-build-distribution.yml │ ├── call-chatOps.yml │ ├── call-clacheck.yml │ ├── call-commitlint.yml │ └── call-license-check.yml ├── .gitignore ├── .gitlab-ci.yml ├── .mailmap ├── .obs └── workflows.yml ├── .packit.yaml ├── .reuse └── dep5 ├── CHANGELOG.md ├── LICENSE ├── LICENSES ├── CC-BY-4.0.txt ├── CC0-1.0.txt ├── GPL-3.0-or-later.txt └── MIT.txt ├── Makefile ├── README.md ├── README.zh_CN.md ├── TODO ├── app ├── app.go └── app_test.go ├── appinfo ├── appinfo.go ├── applaunchcontext.go ├── applaunchcontext_test.go ├── desktopappinfo │ ├── desktopappinfo.go │ ├── desktopappinfo_test.go │ ├── exec.go │ ├── fail_detector_test.go │ ├── get_all.go │ └── testdata │ │ └── applications │ │ └── deepin-screenshot.desktop └── startup_notify_msg.go ├── arch └── arch.go ├── archive ├── archive.go ├── archive_test.go ├── gzip │ ├── gzip.go │ ├── gzip_test.go │ └── tar.go ├── tar.go └── utils │ ├── tar.go │ └── tar_test.go ├── archlinux └── PKGBUILD ├── asound └── asound.go ├── backlight ├── common │ ├── common.go │ └── common_test.go ├── display │ ├── display.go │ ├── display_test.go │ ├── testdata │ │ ├── acpi_video0 │ │ │ ├── actual_brightness │ │ │ ├── bl_power │ │ │ ├── brightness │ │ │ ├── max_brightness │ │ │ └── type │ │ └── intel_backlight │ │ │ ├── actual_brightness │ │ │ ├── bl_power │ │ │ ├── brightness │ │ │ ├── device │ │ │ └── edid │ │ │ ├── max_brightness │ │ │ └── type │ └── type.go └── keyboard │ ├── keyboard.go │ ├── keyboard_test.go │ └── testdata │ ├── input7__capslock │ ├── brightness │ └── max_brightness │ └── xxx__kbd_backlight │ ├── brightness │ └── max_brightness ├── calendar ├── calendar.go ├── calendar_test.go ├── day.go ├── lunar │ ├── day.go │ ├── day_test.go │ ├── elp82.go │ ├── elp82_const.go │ ├── elp82_test.go │ ├── iau1980.go │ ├── iau1980_test.go │ ├── lunar.go │ ├── lunar_test.go │ ├── mathutil.go │ ├── mathutil_test.go │ ├── newmoon.go │ ├── newmoon_test.go │ ├── solarterms.go │ ├── solarterms_test.go │ ├── vsop87earthd.go │ ├── vsop87earthd_const.go │ └── vsop87earthd_test.go └── util │ ├── julianday.go │ ├── julianday_test.go │ ├── util.go │ └── util_test.go ├── cgroup ├── cgroup.go └── cgroup_test.go ├── dbusutil ├── _tool │ └── dbusutil-gen │ │ ├── exported_methods.go │ │ └── main.go ├── dbusutil.go ├── err.go ├── err_test.go ├── gsprop │ ├── gsprop.go │ └── gsprop_test.go ├── implementer_static.go ├── implementor.go ├── introspectable.go ├── match_rule.go ├── match_rule_test.go ├── object.go ├── properties.go ├── proxy │ ├── object.go │ ├── object_mock.go │ ├── prop.go │ └── rule_counter.go ├── service.go ├── service_test.go └── signal.go ├── dbusutilv1 ├── _tool │ └── dbusutilv1-gen │ │ ├── exported_methods.go │ │ └── main.go ├── dbusutilv1.go ├── err.go ├── err_test.go ├── gsprop │ ├── gsprop.go │ └── gsprop_test.go ├── implementer_static.go ├── implementor.go ├── introspectable.go ├── match_rule.go ├── match_rule_test.go ├── object.go ├── properties.go ├── proxy │ ├── object.go │ ├── object_mock.go │ ├── prop.go │ └── rule_counter.go ├── service.go ├── service_test.go └── signal.go ├── debian ├── abi.json ├── changelog ├── compat ├── control ├── copyright ├── rules └── source │ └── format ├── doc └── dbusutil.md ├── encoding └── kv │ ├── reader.go │ ├── reader_test.go │ └── testdata │ ├── a │ ├── b │ └── c ├── event └── event.go ├── gdkpixbuf ├── README.md ├── blur.c ├── blur.go ├── blur.h ├── constants.go ├── gaussianiir2d.c ├── gaussianiir2d.h ├── gdk_pixbuf_utils.c ├── gdk_pixbuf_utils.h ├── gdkpixbuf.go ├── gdkpixbuf_test.go ├── testdata │ ├── origin_1920x1080.jpg │ ├── origin_icon_1_48x48.bmp │ ├── origin_icon_1_48x48.gif │ ├── origin_icon_1_48x48.png │ ├── origin_icon_1_48x48.txt │ ├── origin_icon_2_48x48.png │ ├── origin_not_image │ └── origin_small_200x200.png └── utils.go ├── gen_test_report.sh ├── gettext ├── build_test_locale_data ├── gettext.go ├── gettext_test.go └── testdata │ ├── ar.po │ ├── gen_mo │ ├── locale │ ├── ar │ │ └── LC_MESSAGES │ │ │ └── test.mo │ └── zh_CN │ │ └── LC_MESSAGES │ │ └── test.mo │ ├── locale_def │ └── en_US.UTF-8 │ │ ├── LC_ADDRESS │ │ ├── LC_COLLATE │ │ ├── LC_CTYPE │ │ ├── LC_IDENTIFICATION │ │ ├── LC_MEASUREMENT │ │ ├── LC_MESSAGES │ │ └── SYS_LC_MESSAGES │ │ ├── LC_MONETARY │ │ ├── LC_NAME │ │ ├── LC_NUMERIC │ │ ├── LC_PAPER │ │ ├── LC_TELEPHONE │ │ └── LC_TIME │ ├── plural │ ├── es.po │ ├── gen_mo │ ├── locale │ │ ├── es │ │ │ └── LC_MESSAGES │ │ │ │ └── test.mo │ │ └── zh_CN │ │ │ └── LC_MESSAGES │ │ │ └── test.mo │ ├── plural.pot │ ├── t.go │ ├── update_pot │ └── zh_CN.po │ ├── test.pot │ └── zh_CN.po ├── go.mod ├── go.sum ├── graphic ├── README.md ├── clip.go ├── composite.go ├── convert.go ├── data_uri.go ├── dominant_color.go ├── fill.go ├── flip.go ├── format_sniff.go ├── graphic.go ├── graphic_test.go ├── hsv.go ├── info.go ├── new.go ├── rotate.go ├── save_load.go ├── scale.go ├── testdata │ ├── origin_1920x1080.jpg │ ├── origin_icon_1_48x48.bmp │ ├── origin_icon_1_48x48.gif │ ├── origin_icon_1_48x48.png │ ├── origin_icon_1_48x48.txt │ ├── origin_icon_2_48x48.png │ ├── origin_not_image │ ├── origin_small_200x200.png │ ├── sniff_format.tiff │ ├── test-get_images-noimage │ │ └── icon.txt │ └── test-get_images │ │ ├── 1.png │ │ ├── 2.png │ │ └── 3.png └── utils.go ├── gsettings ├── monitor.go └── monitor_test.go ├── imgutil ├── format_sniff.go ├── imgutil.go ├── imgutil_test.go └── testdata │ ├── deepin-music.bmp │ ├── deepin-music.gif │ ├── deepin-music.jpg │ ├── deepin-music.png │ └── deepin-music.tiff ├── initializer ├── initializer.go ├── initializer_test.go └── v2 │ ├── initializer.go │ └── initializer_test.go ├── iso ├── README.md ├── country.go ├── country_test.go └── iso_test.go ├── keyfile ├── get.go ├── keyfile.go ├── keyfile_test.go ├── read.go ├── set.go ├── testdata │ └── deepin-screenshot.desktop └── write.go ├── libc └── libc.go ├── locale ├── locale.go ├── locale_test.go └── testdata │ └── locale.alias ├── log ├── README.md ├── backend_console.go ├── backend_syslog.go ├── logger.go ├── logger_test.go ├── restart_config.go ├── testdata │ ├── dde_debug │ └── stdout └── utils.go ├── mime ├── mime.go ├── mime_test.go ├── testdata │ ├── Deepin │ │ ├── cursors │ │ │ └── left_ptr │ │ ├── gtk-2.0 │ │ │ └── gtkrc │ │ ├── gtk-3.0 │ │ │ └── settings.ini │ │ ├── index.theme │ │ └── metacity-1 │ │ │ └── metacity-theme-3.xml │ └── data.txt ├── theme.go └── theme_test.go ├── misc.go ├── mobileprovider ├── README.md ├── mobileprovider.go ├── mobileprovider_plan.go ├── mobileprovider_test.go └── mobileprovider_type.go ├── multierr ├── append.go ├── append_test.go ├── format.go ├── format_test.go ├── multierr.go └── multierr_test.go ├── notify ├── const.go ├── dbusnotify │ ├── init.go │ └── notify.go ├── examples │ ├── action.go │ ├── desktop-icon.jpeg │ ├── image.go │ ├── libreoffice-base.png │ ├── simple.go │ └── update.go ├── image.go ├── notification.go ├── notification_test.go └── notify.go ├── pam ├── handler.go ├── pam.go └── transaction.c ├── pinyin ├── datas.go ├── pinyin.go └── pinyin_test.go ├── pinyin_search ├── pinyin_search.go └── t1_test.go ├── procfs ├── procfs.go └── procfs_test.go ├── profile ├── profile.go ├── profile_test.go └── time.go ├── proxy ├── README.md ├── dev_test.go └── proxy.go ├── pulse ├── card.go ├── dde-pulse.c ├── dde-pulse.h ├── info_test.go ├── mainloop_callbacks.go ├── meter.c ├── meter.go ├── misc.go ├── proplist.go ├── pulse.go ├── pulse_test.go ├── server.go ├── simple │ └── simple.go ├── sink.go ├── sink_input.go ├── source.go ├── source_output.go ├── sync.go ├── thread_test.go └── wrap.go ├── rpm └── golang-deepin-go-lib.spec ├── shell ├── shell.go └── shell_test.go ├── sound ├── player.c ├── player.go ├── player.h ├── utils.go └── utils_test.go ├── sound_effect ├── alsa_backend.go ├── ogg.go ├── player.go ├── pulse_backend.go ├── theme │ └── theme.go └── wav.go ├── stb_vorbis ├── stb_vorbis.c ├── stb_vorbis.go └── stb_vorbis.h ├── strv ├── strv.go └── strv_test.go ├── tasker ├── delay_task.go ├── delay_task_manager.go └── tasker_test.go ├── timer ├── time.go ├── timer.go └── timer_test.go ├── users ├── group │ ├── group.go │ └── group_test.go ├── passwd │ ├── passwd.go │ └── passwd_test.go └── shadow │ ├── shadow.go │ └── shadow_test.go ├── utils ├── cache.go ├── config.go ├── config_test.go ├── file.go ├── file_test.go ├── filesystem.go ├── keyfile.go ├── keyfile_test.go ├── md5.go ├── md5_test.go ├── os.go ├── schemas.go ├── schemas_test.go ├── testdata │ ├── copy-dest │ │ ├── file1 │ │ └── test │ │ │ └── file2 │ ├── copy-src │ │ ├── file1 │ │ └── test │ │ │ └── file2 │ ├── test-get_files │ │ ├── file1 │ │ └── file2 │ ├── test1 │ └── testfile ├── uri.go ├── user_special_dir.go ├── utils.go ├── utils_test.go └── watch_proxy.go └── xdg ├── basedir ├── basedir.go └── basedir_test.go └── userdir ├── testdata └── user-dirs.dirs ├── testdata2 └── user-dirs.dirs ├── userdir.go └── userdir_test.go /.github/workflows/backup-to-gitlab.yml: -------------------------------------------------------------------------------- 1 | name: backup to gitlab 2 | on: [push] 3 | 4 | concurrency: 5 | group: ${{ github.workflow }} 6 | cancel-in-progress: true 7 | 8 | jobs: 9 | backup-to-gitlabwh: 10 | uses: linuxdeepin/.github/.github/workflows/backup-to-gitlabwh.yml@master 11 | secrets: inherit 12 | 13 | backup-to-gitee: 14 | uses: linuxdeepin/.github/.github/workflows/backup-to-gitee.yml@master 15 | secrets: inherit 16 | -------------------------------------------------------------------------------- /.github/workflows/call-auto-tag.yml: -------------------------------------------------------------------------------- 1 | name: auto tag 2 | 3 | on: 4 | pull_request_target: 5 | types: [opened, synchronize, closed] 6 | paths: 7 | - "debian/changelog" 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-pull/${{ github.event.number }} 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | auto_tag: 15 | uses: linuxdeepin/.github/.github/workflows/auto-tag.yml@master 16 | secrets: inherit 17 | -------------------------------------------------------------------------------- /.github/workflows/call-build-distribution.yml: -------------------------------------------------------------------------------- 1 | name: Call build-distribution 2 | on: 3 | push: 4 | paths-ignore: 5 | - ".github/workflows/**" 6 | pull_request_target: 7 | paths-ignore: 8 | - ".github/workflows/**" 9 | 10 | jobs: 11 | check_job: 12 | uses: linuxdeepin/.github/.github/workflows/build-distribution.yml@master 13 | secrets: inherit 14 | -------------------------------------------------------------------------------- /.github/workflows/call-chatOps.yml: -------------------------------------------------------------------------------- 1 | name: chatOps 2 | on: 3 | issue_comment: 4 | types: [created] 5 | 6 | jobs: 7 | chatopt: 8 | uses: linuxdeepin/.github/.github/workflows/chatOps.yml@master 9 | secrets: inherit 10 | -------------------------------------------------------------------------------- /.github/workflows/call-clacheck.yml: -------------------------------------------------------------------------------- 1 | name: Call CLA check 2 | on: 3 | issue_comment: 4 | types: [created] 5 | pull_request_target: 6 | types: [opened, closed, synchronize] 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-pull/${{ github.event.number }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | clacheck: 14 | uses: linuxdeepin/.github/.github/workflows/cla-check.yml@master 15 | secrets: inherit 16 | -------------------------------------------------------------------------------- /.github/workflows/call-commitlint.yml: -------------------------------------------------------------------------------- 1 | name: Call commitlint 2 | on: 3 | pull_request_target: 4 | 5 | concurrency: 6 | group: ${{ github.workflow }}-pull/${{ github.event.number }} 7 | cancel-in-progress: true 8 | 9 | jobs: 10 | check_job: 11 | uses: linuxdeepin/.github/.github/workflows/commitlint.yml@master 12 | -------------------------------------------------------------------------------- /.github/workflows/call-license-check.yml: -------------------------------------------------------------------------------- 1 | name: Call License and README Check 2 | on: 3 | pull_request_target: 4 | types: [opened, synchronize, reopened] 5 | 6 | permissions: 7 | pull-requests: write 8 | contents: read 9 | 10 | concurrency: 11 | group: ${{ github.workflow }}-pull/${{ github.event.number }} 12 | cancel-in-progress: true 13 | 14 | jobs: 15 | license-check: 16 | uses: linuxdeepin/.github/.github/workflows/license-check.yml@master 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | */*.test 2 | _tmp 3 | graphic/testdata/test_* 4 | gdkpixbuf/testdata/test* 5 | *.bak 6 | _* 7 | !dbusutil/_tool 8 | !dbusutilv1/_tool 9 | **/*.test 10 | coverage.csv -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | include: 2 | - remote: 'https://gitlab.deepin.io/dev-tools/letmeci/raw/master/gitlab-ci/dde.yml' 3 | 4 | variables: 5 | CPPCHECK_DISABLED: "true" 6 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Xu Fasheng 2 | -------------------------------------------------------------------------------- /.obs/workflows.yml: -------------------------------------------------------------------------------- 1 | test_build: 2 | steps: 3 | - link_package: 4 | source_project: deepin:Develop:dde 5 | source_package: %{SCM_REPOSITORY_NAME} 6 | target_project: deepin:CI 7 | 8 | - configure_repositories: 9 | project: deepin:CI 10 | repositories: 11 | - name: deepin_develop 12 | paths: 13 | - target_project: deepin:CI 14 | target_repository: deepin_develop 15 | architectures: 16 | - x86_64 17 | - aarch64 18 | 19 | - name: debian 20 | paths: 21 | - target_project: deepin:CI 22 | target_repository: debian_sid 23 | architectures: 24 | - x86_64 25 | 26 | filters: 27 | event: pull_request 28 | 29 | tag_build: 30 | steps: 31 | - trigger_services: 32 | project: deepin:Unstable:dde 33 | package: %{SCM_REPOSITORY_NAME} 34 | filters: 35 | event: tag_push 36 | 37 | commit_build: 38 | steps: 39 | - trigger_services: 40 | project: deepin:Develop:dde 41 | package: %{SCM_REPOSITORY_NAME} 42 | filters: 43 | event: push 44 | -------------------------------------------------------------------------------- /.packit.yaml: -------------------------------------------------------------------------------- 1 | # See the documentation for more information: 2 | # https://packit.dev/docs/configuration/ 3 | 4 | specfile_path: rpm/golang-deepin-go-lib.spec 5 | 6 | # add or remove files that should be synced 7 | synced_files: 8 | - rpm/golang-deepin-go-lib.spec 9 | - .packit.yaml 10 | 11 | upstream_package_name: go-lib 12 | # downstream (Fedora) RPM package name 13 | downstream_package_name: golang-deepin-go-lib 14 | 15 | actions: 16 | fix-spec-file: | 17 | bash -c "sed -i -r \"0,/Version:/ s/Version:(\s*)\S*/Version:\1${PACKIT_PROJECT_VERSION}/\" rpm/golang-deepin-go-lib.spec" 18 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GOPATH_DIR = gopath 2 | GOPKG_PREFIX = github.com/linuxdeepin/go-lib 3 | 4 | prepare: 5 | @mkdir -p ${GOPATH_DIR}/src/$(dir ${GOPKG_PREFIX}); 6 | @ln -sf ../../.. ${GOPATH_DIR}/src/${GOPKG_PREFIX}; 7 | 8 | print_gopath: prepare 9 | GOPATH="${CURDIR}/${GOPATH_DIR}:${GOPATH}" 10 | 11 | clean: 12 | rm -rf ${GOPATH_DIR} 13 | 14 | check_code_quality: prepare 15 | env GOPATH="${CURDIR}/${GOPATH_DIR}:${GOPATH}" go vet ./... 16 | 17 | test: prepare 18 | env GOPATH="${CURDIR}/${GOBUILD_DIR}:${GOPATH}" go test -v ./... 19 | 20 | test-coverage: prepare 21 | env GOPATH="${CURDIR}/${GOBUILD_DIR}:${GOPATH}" go test -cover -v ./... | awk '$$1 ~ "^(ok|\\?)" {print $$2","$$5}' | sed "s:${CURDIR}::g" | sed 's/files\]/0\.0%/g' > coverage.csv 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Deepin GoLang Library 2 | 3 | Deepin GoLang Library is a library containing many useful go routines for things such as glib, gettext, archive, graphic,etc. 4 | 5 | ## Dependencies 6 | 7 | 8 | ### Build dependencies 9 | 10 | * gio-2.0 11 | * glib-2.0 12 | * x11 13 | * gdk-pixbuf-2.0 14 | * libpulse 15 | * mobile-broadband-provider-info 16 | 17 | ## Installation 18 | 19 | Install prerequisites 20 | 21 | ``` 22 | $ go get github.com/smartystreets/goconvey 23 | $ go get github.com/howeyc/fsnotify 24 | $ go get gopkg.in/check.v1 25 | $ go get github.com/linuxdeepin/go-x11-client 26 | ``` 27 | 28 | Install 29 | 30 | ``` 31 | mkdir -p $GOPATH/src/github.com/linuxdeepin/ 32 | cp -r go-lib $GOPATH/src/github.com/linuxdeepin/go-lib 33 | ``` 34 | 35 | ## Getting help 36 | 37 | Any usage issues can ask for help via 38 | 39 | * [Gitter](https://gitter.im/orgs/linuxdeepin/rooms) 40 | * [IRC channel](https://webchat.freenode.net/?channels=deepin) 41 | * [Forum](https://bbs.deepin.org/) 42 | * [WiKi](http://wiki.deepin.org/) 43 | 44 | ## Getting involved 45 | 46 | We encourage you to report issues and contribute changes. 47 | 48 | * [Contribution guide for users](http://wiki.deepin.org/index.php?title=Contribution_Guidelines_for_Users) 49 | * [Contribution guide for developers](http://wiki.deepin.org/index.php?title=Contribution_Guidelines_for_Developers) 50 | 51 | ## License 52 | 53 | Deepin GoLang Library is licensed under [GPL-3.0-or-later](LICENSE). 54 | -------------------------------------------------------------------------------- /README.zh_CN.md: -------------------------------------------------------------------------------- 1 | ## Deepin GoLang Library 2 | 3 | Deepin GoLang 库是一个包含许多有用的 go 例程的库,用于 glib、gettext、存档、图形等。 4 | 5 | ## 依赖 6 | 7 | 8 | ### 编译依赖 9 | 10 | * gio-2.0 11 | * glib-2.0 12 | * x11 13 | * gdk-pixbuf-2.0 14 | * libpulse 15 | * mobile-broadband-provider-info 16 | 17 | ## 安装 18 | 19 | go-lib需要预安装以下包 20 | 21 | ``` 22 | $ go get github.com/smartystreets/goconvey 23 | $ go get github.com/howeyc/fsnotify 24 | $ go get gopkg.in/check.v1 25 | $ go get github.com/linuxdeepin/go-x11-client 26 | ``` 27 | 28 | 安装 29 | 30 | ``` 31 | mkdir -p $GOPATH/src/github.com/linuxdeepin/ 32 | cp -r go-lib $GOPATH/src/github.com/linuxdeepin/go-lib 33 | ``` 34 | 35 | ## 获得帮助 36 | 37 | 如果您遇到任何其他问题,您可能还会发现这些渠道很有用: 38 | 39 | * [Gitter](https://gitter.im/orgs/linuxdeepin/rooms) 40 | * [IRC channel](https://webchat.freenode.net/?channels=deepin) 41 | * [Forum](https://bbs.deepin.org/) 42 | * [WiKi](http://wiki.deepin.org/) 43 | 44 | ## 贡献指南 45 | 46 | 我们鼓励您报告问题并做出更改。 47 | 48 | * [Contribution guide for users](http://wiki.deepin.org/index.php?title=Contribution_Guidelines_for_Users) 49 | * [Contribution guide for developers](http://wiki.deepin.org/index.php?title=Contribution_Guidelines_for_Developers) 50 | 51 | ## 开源协议 52 | 53 | go-lib项目在 [GPL-3.0-or-later](LICENSE)开源协议下发布。 54 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | [ ] compact utils directory, separate it into different packages. 2 | 3 | 更新rmp目录 4 | -------------------------------------------------------------------------------- /app/app_test.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 4 | // 5 | // SPDX-License-Identifier: GPL-3.0-or-later 6 | 7 | package app 8 | 9 | import ( 10 | "os" 11 | ) 12 | 13 | func ExampleApp() { 14 | app := New("test app", "this is a test app", "version 0.0.0") 15 | subcmd := app.ParseCommandLine(os.Args[1:]) 16 | if app.StartProfile() != nil { 17 | // error handle 18 | return 19 | } 20 | switch subcmd { 21 | // deal with subcmd 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /appinfo/appinfo.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package appinfo 6 | 7 | type AppInfo interface { 8 | GetId() string 9 | GetName() string 10 | GetIcon() string 11 | GetExecutable() string 12 | GetFileName() string 13 | GetCommandline() string 14 | Launch(files []string, launchContext *AppLaunchContext) error 15 | GetStartupWMClass() string 16 | } 17 | -------------------------------------------------------------------------------- /appinfo/applaunchcontext_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package appinfo 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func Test_AppLaunchContext(t *testing.T) { 14 | // 仅用于测试, 没有实际意义 15 | testTimeStamp := (uint32)(20210622) 16 | testCmdFixes := []string{"uos", "deepin"} 17 | 18 | appLaunchTest := &AppLaunchContext{ 19 | timestamp: testTimeStamp, 20 | cmdPrefixes: testCmdFixes, 21 | cmdSuffixes: testCmdFixes, 22 | } 23 | 24 | appLaunchTest.SetTimestamp(testTimeStamp) 25 | assert.Equal(t, appLaunchTest.timestamp, testTimeStamp) 26 | 27 | appLaunchTest.SetCmdPrefixes(testCmdFixes) 28 | assert.Equal(t, appLaunchTest.cmdPrefixes[0], "uos") 29 | assert.NotEqual(t, appLaunchTest.cmdPrefixes[1], "uos") 30 | 31 | appLaunchTest.SetCmdSuffixes(testCmdFixes) 32 | assert.Equal(t, appLaunchTest.cmdSuffixes[0], "uos") 33 | assert.NotEqual(t, appLaunchTest.cmdSuffixes[1], "uos") 34 | 35 | assert.Equal(t, appLaunchTest.GetTimestamp(), testTimeStamp) 36 | assert.Equal(t, appLaunchTest.GetCmdPrefixes()[0], "uos") 37 | assert.Equal(t, appLaunchTest.GetCmdSuffixes()[0], "uos") 38 | } 39 | -------------------------------------------------------------------------------- /appinfo/desktopappinfo/fail_detector_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package desktopappinfo 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | // 测试简单的情况 15 | func TestFailDetectorSimple(t *testing.T) { 16 | ch := make(chan struct{}, 2) 17 | fd := newFailDetector(ch) 18 | _, err := fd.Write([]byte("Failed to invoke: Booster: abcdef")) 19 | require.NoError(t, err) 20 | assert.True(t, fd.done) 21 | 22 | fd = newFailDetector(ch) 23 | _, err = fd.Write([]byte("deepin-turbo-invoker: error: xxxx not a file\n")) 24 | require.NoError(t, err) 25 | assert.True(t, fd.done) 26 | } 27 | 28 | // 测试多次写入,\n 后有其他字符的情况 29 | func TestFailDetectorWrite(t *testing.T) { 30 | ch := make(chan struct{}, 2) 31 | fd := newFailDetector(ch) 32 | _, err := fd.Write([]byte("line1\n")) 33 | require.NoError(t, err) 34 | assert.False(t, fd.done) 35 | assert.Len(t, fd.buf.Bytes(), 0) 36 | 37 | _, err = fd.Write([]byte("line2\nabc")) 38 | require.NoError(t, err) 39 | assert.False(t, fd.done) 40 | assert.Equal(t, []byte("abc"), fd.buf.Bytes()) 41 | 42 | _, err = fd.Write(nil) 43 | require.NoError(t, err) 44 | assert.False(t, fd.done) 45 | assert.Equal(t, []byte("abc"), fd.buf.Bytes()) 46 | 47 | _, err = fd.Write([]byte("abc-abc\nFailed to invoke: Booster: abcdef\nline 3")) 48 | require.NoError(t, err) 49 | assert.True(t, fd.done) 50 | assert.Zero(t, fd.buf.Bytes()) 51 | } 52 | -------------------------------------------------------------------------------- /appinfo/desktopappinfo/testdata/applications/deepin-screenshot.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Categories=Graphics;GTK; 3 | Comment=Screen capturing application 4 | Exec=deepin-screenshot --icon 5 | GenericName=Screen capturing application 6 | Icon=deepin-screenshot 7 | Name=Deepin Screenshot 8 | Name[xy_XY.UTF-8@abc123]=test 9 | StartupNotify=false 10 | Type=Application 11 | 12 | 13 | [Full_Screenshot Shortcut Group] 14 | Exec=deepin-screenshot -f 15 | Name=Full Screenshot 16 | Name[zh_CN]=全屏截图 17 | 18 | [Delay_Screenshot Shortcut Group] 19 | Exec=deepin-screenshot -d 5 20 | Name=Delay Screenshot 21 | Name[zh_CN]=延时截图 22 | -------------------------------------------------------------------------------- /arch/arch.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package arch 6 | 7 | import ( 8 | "runtime" 9 | ) 10 | 11 | type ArchFamilyType int 12 | 13 | const ( 14 | Unknown ArchFamilyType = iota 15 | AMD64 16 | Sunway 17 | ) 18 | 19 | func Get() ArchFamilyType { 20 | switch runtime.GOARCH { 21 | case "sw_64","sw64": 22 | return Sunway 23 | case "amd64": 24 | return AMD64 25 | default: 26 | return Unknown 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /archive/archive.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package archive 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | 11 | "github.com/linuxdeepin/go-lib/archive/gzip" 12 | ) 13 | 14 | const ( 15 | CompressTypeUnkown int32 = iota 16 | CompressTypeTar 17 | CompressTypeTarGz 18 | CompressTypeTarBz2 19 | CompressTypeZip 20 | ) 21 | 22 | func CompressDir(src, dest string) error { 23 | switch getCompressType(dest) { 24 | case CompressTypeTar: 25 | return tarCompressFiles([]string{src}, dest) 26 | case CompressTypeTarGz: 27 | return gzip.CompressDir(src, dest, gzip.ArchiveTypeTar) 28 | case CompressTypeTarBz2: 29 | return nil 30 | case CompressTypeZip: 31 | return nil 32 | default: 33 | return fmt.Errorf("Invalid archive compress type") 34 | } 35 | } 36 | 37 | func CompressFiles(files []string, dest string) error { 38 | switch getCompressType(dest) { 39 | case CompressTypeTar: 40 | return tarCompressFiles(files, dest) 41 | case CompressTypeTarGz: 42 | return gzip.CompressFiles(files, dest, gzip.ArchiveTypeTar) 43 | case CompressTypeTarBz2: 44 | return nil 45 | case CompressTypeZip: 46 | return nil 47 | default: 48 | return fmt.Errorf("Invalid archive compress type") 49 | } 50 | } 51 | 52 | func Extracte(src, dest string) ([]string, error) { 53 | switch getCompressType(src) { 54 | case CompressTypeTar: 55 | return tarExtracteFile(src, dest) 56 | case CompressTypeTarGz: 57 | return gzip.Extracte(src, dest, gzip.ArchiveTypeTar) 58 | case CompressTypeTarBz2: 59 | return nil, nil 60 | case CompressTypeZip: 61 | return nil, nil 62 | default: 63 | return nil, fmt.Errorf("Invalid archive compress type") 64 | } 65 | } 66 | 67 | func getCompressType(file string) int32 { 68 | switch { 69 | case strings.HasSuffix(file, "tar"): 70 | return CompressTypeTar 71 | case strings.HasSuffix(file, "tar.gz"): 72 | return CompressTypeTarGz 73 | case strings.HasSuffix(file, "tar.bz2"): 74 | return CompressTypeTarBz2 75 | case strings.HasSuffix(file, "zip"): 76 | return CompressTypeZip 77 | } 78 | 79 | return CompressTypeUnkown 80 | } 81 | -------------------------------------------------------------------------------- /archive/gzip/gzip.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package gzip 6 | 7 | import ( 8 | "fmt" 9 | ) 10 | 11 | const ( 12 | ArchiveTypeTar int32 = iota + 1 13 | ArchiveTypeZip 14 | ArchiveTypeRar 15 | ) 16 | 17 | func CompressDir(src, dest string, t int32) error { 18 | switch t { 19 | case ArchiveTypeTar: 20 | return tarCompressFiles([]string{src}, dest) 21 | case ArchiveTypeZip: 22 | return nil 23 | case ArchiveTypeRar: 24 | return nil 25 | default: 26 | return fmt.Errorf("Invalid archive type: %q", t) 27 | } 28 | } 29 | 30 | func CompressFiles(files []string, dest string, t int32) error { 31 | switch t { 32 | case ArchiveTypeTar: 33 | return tarCompressFiles(files, dest) 34 | case ArchiveTypeZip: 35 | return nil 36 | case ArchiveTypeRar: 37 | return nil 38 | default: 39 | return fmt.Errorf("Invalid archive type: %q", t) 40 | } 41 | } 42 | 43 | func Extracte(src, destDir string, t int32) ([]string, error) { 44 | switch t { 45 | case ArchiveTypeTar: 46 | return tarExtracte(src, destDir) 47 | case ArchiveTypeZip: 48 | return nil, nil 49 | case ArchiveTypeRar: 50 | return nil, nil 51 | default: 52 | return nil, fmt.Errorf("Invalid archive type: %q", t) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /archive/gzip/tar.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package gzip 6 | 7 | import ( 8 | "archive/tar" 9 | "compress/gzip" 10 | "os" 11 | "github.com/linuxdeepin/go-lib/archive/utils" 12 | ) 13 | 14 | func tarCompressFiles(files []string, dest string) error { 15 | dw, err := os.Create(dest) 16 | if err != nil { 17 | return err 18 | } 19 | defer dw.Close() 20 | 21 | gw := gzip.NewWriter(dw) 22 | defer gw.Close() 23 | tw := tar.NewWriter(gw) 24 | defer tw.Close() 25 | 26 | return utils.TarWriterCompressFiles(tw, files) 27 | } 28 | 29 | func tarExtracte(src, dest string) ([]string, error) { 30 | sr, err := os.Open(src) 31 | if err != nil { 32 | return nil, err 33 | } 34 | defer sr.Close() 35 | 36 | gr, err := gzip.NewReader(sr) 37 | if err != nil { 38 | return nil, err 39 | } 40 | defer gr.Close() 41 | 42 | return utils.TarReaderExtracte(tar.NewReader(gr), dest) 43 | } 44 | -------------------------------------------------------------------------------- /archive/tar.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package archive 6 | 7 | import ( 8 | "archive/tar" 9 | "os" 10 | "github.com/linuxdeepin/go-lib/archive/utils" 11 | ) 12 | 13 | func tarCompressFiles(files []string, dest string) error { 14 | dw, err := os.Create(dest) 15 | if err != nil { 16 | return err 17 | } 18 | defer dw.Close() 19 | 20 | tw := tar.NewWriter(dw) 21 | defer tw.Close() 22 | 23 | return utils.TarWriterCompressFiles(tw, files) 24 | } 25 | 26 | func tarExtracteFile(src, dest string) ([]string, error) { 27 | sr, err := os.Open(src) 28 | if err != nil { 29 | return nil, err 30 | } 31 | defer sr.Close() 32 | 33 | return utils.TarReaderExtracte(tar.NewReader(sr), dest) 34 | } 35 | -------------------------------------------------------------------------------- /archive/utils/tar_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestTarWriterCompressFiles(t *testing.T) { 14 | var testFiles []string 15 | err := TarWriterCompressFiles(nil, testFiles) 16 | assert.NotEqual(t, nil, err) 17 | } 18 | 19 | func TestTarReaderExtracte(t *testing.T) { 20 | _, err := TarReaderExtracte(nil, "") 21 | assert.NotEqual(t, nil, err) 22 | } 23 | 24 | func TestTarWriterCompressDir(t *testing.T) { 25 | err := tarWriterCompressDir(nil, "", "") 26 | assert.NotEqual(t, nil, err) 27 | } 28 | 29 | func TestTarWriterCompressFile(t *testing.T) { 30 | err := tarWriterCompressFile(nil, "", "") 31 | assert.NotEqual(t, nil, err) 32 | } 33 | -------------------------------------------------------------------------------- /archlinux/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: justforlxz 2 | pkgname=golang-deepin-lib-git 3 | pkgver=6.0.0.r7.g0e8fa1d 4 | pkgrel=1 5 | pkgdesc='A library containing many useful go routines for things such as glib, gettext, archive, graphic,etc.' 6 | arch=('any') 7 | url="https://github.com/linuxdeepin/go-lib" 8 | license=('GPL3') 9 | depends=( 10 | 'dbus' 11 | 'libpulse' 12 | 'gdk-pixbuf2' 13 | 'gdk-pixbuf-xlib' 14 | 'mobile-broadband-provider-info' 15 | 'libx11' 16 | 'libcanberra' 17 | 'golang-gopkg-alecthomas-kingpin.v2' 18 | 'golang-deepin-gir-git' 19 | 'golang-github-linuxdeepin-go-x11-client-git' 20 | 'golang-golang-x-net' 21 | 'golang-golang-x-image' 22 | ) 23 | checkdepends=( 24 | 'iso-codes' 25 | 'golang-gopkg-check.v1' 26 | 'golang-gopkg-yaml.v3' 27 | 'golang-github-fsnotify-fsnotify' 28 | 'golang-github-stretchr-testify' 29 | 'git' 30 | 'dash' 31 | ) # git needed only for go get 32 | conflicts=('golang-deepin-lib') 33 | provides=('golang-deepin-lib') 34 | groups=('deepin-git') 35 | source=('source.tar.gz') 36 | sha512sums=('SKIP') 37 | 38 | prepare() { 39 | cd $deepin_source_name 40 | sed -i 's|"sh"|"dash"|' shell/shell_test.go 41 | } 42 | 43 | check() { 44 | export GO111MODULE=off 45 | export GOPATH="$srcdir/build:/usr/share/gocode" 46 | mkdir -p "$srcdir"/build/src/github.com/linuxdeepin 47 | cp -a "$srcdir"/$deepin_source_name "$srcdir"/build/src/github.com/linuxdeepin/go-lib 48 | cd "$srcdir"/build/src/github.com/linuxdeepin/go-lib 49 | # TODO: make packages for them 50 | go get github.com/cryptix/wav \ 51 | github.com/smartystreets/goconvey/convey \ 52 | github.com/mozillazg/go-pinyin \ 53 | github.com/godbus/dbus \ 54 | github.com/youpy/go-wav 55 | # passwd: test needs to access /etc/passwd 56 | # gm: needs gmssl 57 | go test -v $(go list ./... | grep -v -e lib/users/passwd -e lib/gm) 58 | } 59 | 60 | package() { 61 | mkdir -p "$pkgdir"/usr/share/gocode/src/github.com/linuxdeepin 62 | cp -a "$srcdir/$deepin_source_name" "$pkgdir"/usr/share/gocode/src/github.com/linuxdeepin/go-lib 63 | rm -r "$pkgdir"/usr/share/gocode/src/github.com/linuxdeepin/go-lib/debian 64 | } 65 | -------------------------------------------------------------------------------- /backlight/common/common.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package common 6 | 7 | import ( 8 | "errors" 9 | "io/ioutil" 10 | "path/filepath" 11 | "strconv" 12 | "strings" 13 | ) 14 | 15 | type Controller struct { 16 | Path string 17 | Name string 18 | MaxBrightness int 19 | } 20 | 21 | var errMaxBrightnessIsZero = errors.New("max brightness of controller is zero") 22 | 23 | func NewController(path string) (*Controller, error) { 24 | c := &Controller{ 25 | Path: path, 26 | Name: filepath.Base(path), 27 | } 28 | 29 | var err error 30 | c.MaxBrightness, err = c.GetPropInt("max_brightness") 31 | if err != nil { 32 | return nil, err 33 | } 34 | if c.MaxBrightness == 0 { 35 | return nil, errMaxBrightnessIsZero 36 | } 37 | 38 | return c, nil 39 | } 40 | 41 | func (c *Controller) GetBrightness() (int, error) { 42 | brightness, err := c.GetPropInt("brightness") 43 | if err != nil { 44 | return 0, err 45 | } 46 | return brightness, nil 47 | } 48 | 49 | func (c *Controller) GetPropBytes(name string) ([]byte, error) { 50 | filename := filepath.Join(c.Path, name) 51 | contents, err := ioutil.ReadFile(filename) 52 | if err != nil { 53 | return nil, err 54 | } 55 | return contents, nil 56 | } 57 | 58 | func (c *Controller) GetPropString(name string) (string, error) { 59 | bytes, err := c.GetPropBytes(name) 60 | if err != nil { 61 | return "", err 62 | } 63 | return string(bytes), nil 64 | } 65 | 66 | func (c *Controller) GetPropInt(name string) (int, error) { 67 | str, err := c.GetPropString(name) 68 | if err != nil { 69 | return 0, err 70 | } 71 | num, err := strconv.Atoi(strings.TrimSpace(str)) 72 | if err != nil { 73 | return 0, err 74 | } 75 | return num, nil 76 | } 77 | 78 | func ListControllerPaths(dir string) ([]string, error) { 79 | fileInfos, err := ioutil.ReadDir(dir) 80 | if err != nil { 81 | return nil, err 82 | } 83 | paths := make([]string, len(fileInfos)) 84 | 85 | for i, fileInfo := range fileInfos { 86 | paths[i] = filepath.Join(dir, fileInfo.Name()) 87 | } 88 | return paths, nil 89 | } 90 | -------------------------------------------------------------------------------- /backlight/common/common_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package common 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func Test_Controller(t *testing.T) { 15 | c, err := NewController("../display/testdata/acpi_video0") 16 | require.NoError(t, err) 17 | brightness, err := c.GetBrightness() 18 | require.NoError(t, err) 19 | assert.Equal(t, brightness, 1) 20 | list, err := ListControllerPaths("../display/testdata") 21 | require.NoError(t, err) 22 | assert.Equal(t, list, []string{"../display/testdata/acpi_video0", "../display/testdata/intel_backlight"}) 23 | } 24 | -------------------------------------------------------------------------------- /backlight/display/testdata/acpi_video0/actual_brightness: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /backlight/display/testdata/acpi_video0/bl_power: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /backlight/display/testdata/acpi_video0/brightness: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /backlight/display/testdata/acpi_video0/max_brightness: -------------------------------------------------------------------------------- 1 | 15 2 | -------------------------------------------------------------------------------- /backlight/display/testdata/acpi_video0/type: -------------------------------------------------------------------------------- 1 | firmware 2 | -------------------------------------------------------------------------------- /backlight/display/testdata/intel_backlight/actual_brightness: -------------------------------------------------------------------------------- 1 | 100 2 | -------------------------------------------------------------------------------- /backlight/display/testdata/intel_backlight/bl_power: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /backlight/display/testdata/intel_backlight/brightness: -------------------------------------------------------------------------------- 1 | 100 2 | -------------------------------------------------------------------------------- /backlight/display/testdata/intel_backlight/device/edid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/backlight/display/testdata/intel_backlight/device/edid -------------------------------------------------------------------------------- /backlight/display/testdata/intel_backlight/max_brightness: -------------------------------------------------------------------------------- 1 | 937 2 | -------------------------------------------------------------------------------- /backlight/display/testdata/intel_backlight/type: -------------------------------------------------------------------------------- 1 | raw 2 | -------------------------------------------------------------------------------- /backlight/display/type.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package display 6 | 7 | type ControllerType uint 8 | 9 | const ( 10 | ControllerTypeUnknown ControllerType = iota 11 | ControllerTypeFirmware 12 | ControllerTypePlatform 13 | ControllerTypeRaw 14 | ) 15 | 16 | func (t ControllerType) String() string { 17 | switch t { 18 | case ControllerTypeFirmware: 19 | return "firmware" 20 | case ControllerTypePlatform: 21 | return "platform" 22 | case ControllerTypeRaw: 23 | return "raw" 24 | } 25 | return "unknown" 26 | } 27 | 28 | func ControllerTypeFromString(str string) ControllerType { 29 | switch str { 30 | case "firmware": 31 | return ControllerTypeFirmware 32 | case "platform": 33 | return ControllerTypePlatform 34 | case "raw": 35 | return ControllerTypeRaw 36 | } 37 | return ControllerTypeUnknown 38 | } 39 | -------------------------------------------------------------------------------- /backlight/keyboard/keyboard.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package keyboard 6 | 7 | import ( 8 | "path/filepath" 9 | . "github.com/linuxdeepin/go-lib/backlight/common" 10 | "strings" 11 | ) 12 | 13 | const controllersDir = "/sys/class/leds" 14 | 15 | func List() ([]*Controller, error) { 16 | return list(controllersDir) 17 | } 18 | 19 | func list(dir string) ([]*Controller, error) { 20 | paths, err := ListControllerPaths(dir) 21 | if err != nil { 22 | return nil, err 23 | } 24 | controllers := make([]*Controller, 0, 1) 25 | for _, path := range paths { 26 | base := filepath.Base(path) 27 | if !strings.Contains(base, "kbd_backlight") { 28 | continue 29 | } 30 | c, err := NewController(path) 31 | if err != nil { 32 | continue 33 | } 34 | controllers = append(controllers, c) 35 | } 36 | return controllers, nil 37 | } 38 | -------------------------------------------------------------------------------- /backlight/keyboard/keyboard_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package keyboard 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestList(t *testing.T) { 15 | controllers, err := List() 16 | t.Log(err) 17 | if len(controllers) == 0 { 18 | t.Log("not found") 19 | return 20 | } 21 | for _, c := range controllers { 22 | t.Logf("%+v\n", c) 23 | br, _ := c.GetBrightness() 24 | t.Log("brightness", br) 25 | } 26 | } 27 | 28 | func Test_list(t *testing.T) { 29 | controllers, err := list("./testdata") 30 | require.NoError(t, err) 31 | assert.Len(t, controllers, 1) 32 | 33 | controller := controllers[0] 34 | assert.Equal(t, controller.Name, "xxx__kbd_backlight") 35 | assert.Equal(t, controller.MaxBrightness, 3) 36 | 37 | br, err := controller.GetBrightness() 38 | require.NoError(t, err) 39 | assert.Equal(t, br, 1) 40 | } 41 | -------------------------------------------------------------------------------- /backlight/keyboard/testdata/input7__capslock/brightness: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /backlight/keyboard/testdata/input7__capslock/max_brightness: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /backlight/keyboard/testdata/xxx__kbd_backlight/brightness: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /backlight/keyboard/testdata/xxx__kbd_backlight/max_brightness: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /calendar/calendar.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package calendar 6 | 7 | import ( 8 | "github.com/linuxdeepin/go-lib/calendar/lunar" 9 | ) 10 | 11 | /* 12 | 13 | 参考资料: 14 | 算法系列之十七:日历生成算法-中国公历(格里历)(上) 15 | https://blog.csdn.net/orbit/article/details/7749723 16 | 17 | 算法系列之十七:日历生成算法-中国公历(格里历)(下) 18 | https://blog.csdn.net/orbit/article/details/7825004 19 | 20 | 算法系列之十八:用天文方法计算二十四节气(上) 21 | https://blog.csdn.net/orbit/article/details/7910220 22 | 23 | 算法系列之十八:用天文方法计算二十四节气(下) 24 | https://blog.csdn.net/orbit/article/details/7944248 25 | 26 | 算法系列之十九:用天文方法计算日月合朔(新月) 27 | https://blog.csdn.net/orbit/article/details/8223751 28 | 29 | 30 | 算法系列之二十:计算中国农历(一) 31 | https://blog.csdn.net/orbit/article/details/9210413 32 | 33 | 算法系列之二十:计算中国农历(二) 34 | https://blog.csdn.net/orbit/article/details/9337377 35 | 36 | 参考项目:github.com/oyyq99999/ChineseLunarCalendar 37 | 38 | */ 39 | 40 | type LunarDayInfo struct { 41 | GanZhiYear string // 农历年的干支 42 | GanZhiMonth string // 农历月的干支 43 | GanZhiDay string // 农历日的干支 44 | LunarMonthName string // 农历月名 45 | LunarDayName string // 农历日名 46 | LunarLeapMonth int32 // 未使用 47 | Zodiac string // 农历年的生肖 48 | Term string // 农历节气 49 | SolarFestival string // 公历节日 50 | LunarFestival string // 农历节日 51 | Worktime int32 // 未使用 52 | } 53 | 54 | func SolarToLunar(year, month, day int) (LunarDayInfo, bool) { 55 | solarDay := Day{ 56 | Year: year, 57 | Month: month, 58 | Day: day, 59 | } 60 | cc := lunar.New(year) 61 | lunarDay := cc.SolarDayToLunarDay(month, day) 62 | 63 | dayInfo := LunarDayInfo{ 64 | GanZhiYear: lunarDay.GanZhiYear(), 65 | GanZhiMonth: lunarDay.GanZhiMonth(), 66 | GanZhiDay: lunarDay.GanZhiDay(), 67 | LunarMonthName: lunarDay.MonthName(), 68 | LunarDayName: lunarDay.DayName(), 69 | Term: lunarDay.SolarTermName(), 70 | SolarFestival: solarDay.Festival(), 71 | LunarFestival: lunarDay.Festival(), 72 | Zodiac: lunarDay.YearZodiac(), 73 | } 74 | return dayInfo, true 75 | } 76 | -------------------------------------------------------------------------------- /calendar/calendar_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package calendar 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func Test_SolarToLunar(t *testing.T) { 14 | dayInfo, _ := SolarToLunar(2016, 2, 19) 15 | assert.Equal(t, dayInfo.LunarMonthName, "正月") 16 | assert.Equal(t, dayInfo.LunarDayName, "十二") 17 | assert.Equal(t, dayInfo.Term, "雨水") 18 | assert.Equal(t, dayInfo.Zodiac, "猴") 19 | assert.Equal(t, dayInfo.GanZhiYear, "丙申") 20 | assert.Equal(t, dayInfo.GanZhiMonth, "庚寅") 21 | assert.Equal(t, dayInfo.GanZhiDay, "辛未") 22 | 23 | dayInfo, _ = SolarToLunar(2012, 1, 23) 24 | assert.Equal(t, dayInfo.LunarMonthName, "正月") 25 | assert.Equal(t, dayInfo.LunarDayName, "初一") 26 | assert.Equal(t, dayInfo.Term, "") 27 | assert.Equal(t, dayInfo.LunarFestival, "春节") 28 | assert.Equal(t, dayInfo.Zodiac, "龙") 29 | assert.Equal(t, dayInfo.GanZhiYear, "壬辰") 30 | assert.Equal(t, dayInfo.GanZhiMonth, "辛丑") 31 | assert.Equal(t, dayInfo.GanZhiDay, "癸未") 32 | 33 | dayInfo, _ = SolarToLunar(2014, 6, 1) 34 | assert.Equal(t, dayInfo.LunarMonthName, "五月") 35 | assert.Equal(t, dayInfo.LunarDayName, "初四") 36 | assert.Equal(t, dayInfo.Term, "") 37 | assert.Equal(t, dayInfo.LunarFestival, "") 38 | assert.Equal(t, dayInfo.SolarFestival, "儿童节") 39 | assert.Equal(t, dayInfo.Zodiac, "马") 40 | assert.Equal(t, dayInfo.GanZhiYear, "甲午") 41 | assert.Equal(t, dayInfo.GanZhiMonth, "己巳") 42 | assert.Equal(t, dayInfo.GanZhiDay, "癸卯") 43 | 44 | dayInfo, _ = SolarToLunar(2057, 10, 27) 45 | assert.Equal(t, dayInfo.LunarMonthName, "九月") 46 | assert.Equal(t, dayInfo.LunarDayName, "三十") 47 | assert.Equal(t, dayInfo.Term, "") 48 | assert.Equal(t, dayInfo.LunarFestival, "") 49 | assert.Equal(t, dayInfo.Zodiac, "牛") 50 | assert.Equal(t, dayInfo.GanZhiYear, "丁丑") 51 | assert.Equal(t, dayInfo.GanZhiMonth, "庚戌") 52 | assert.Equal(t, dayInfo.GanZhiDay, "丁巳") 53 | } 54 | -------------------------------------------------------------------------------- /calendar/lunar/elp82_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package lunar 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func Test_GetMoonEclipticParameter(t *testing.T) { 12 | Lp, D, M, Mp, F, E := GetMoonEclipticParameter(1.2345) 13 | t.Log(Lp) 14 | t.Log(D) 15 | t.Log(M) 16 | t.Log(Mp) 17 | t.Log(F) 18 | t.Log(E) 19 | } 20 | 21 | func Test_CalcMoonECLongitudePeriodic(t *testing.T) { 22 | Lp, D, M, Mp, F, E := GetMoonEclipticParameter(1.2345) 23 | EI := CalcMoonECLongitudePeriodic(D, M, Mp, F, E) 24 | t.Log(Lp) 25 | t.Log(EI) 26 | } 27 | 28 | func Test_GetMoonEclipticLongitudeEC(t *testing.T) { 29 | rad := GetMoonEclipticLongitudeEC(2448724.5) 30 | t.Log(rad) 31 | // 目标 2.3242072713306796 32 | deg := ToDegrees(rad) 33 | t.Log(deg) 34 | } 35 | -------------------------------------------------------------------------------- /calendar/lunar/iau1980_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package lunar 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func Test_CalcEarthLongitudeNutation(t *testing.T) { 12 | n := CalcEarthLongitudeNutation(1.2345) 13 | t.Log(n) 14 | } 15 | 16 | func Test_CalcEarthObliquityNutation(t *testing.T) { 17 | n := CalcEarthObliquityNutation(1.2345) 18 | t.Log(n) 19 | } 20 | -------------------------------------------------------------------------------- /calendar/lunar/mathutil.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package lunar 6 | 7 | import ( 8 | "math" 9 | ) 10 | 11 | // ToRadians 角度转换为弧度 12 | func ToRadians(degrees float64) float64 { 13 | return degrees * math.Pi / 180 14 | } 15 | 16 | // ToDegrees 弧度转换为角度 17 | func ToDegrees(rad float64) float64 { 18 | return rad * 180 / math.Pi 19 | } 20 | 21 | // SecondsToRadians 把角秒换算成弧度 22 | func SecondsToRadians(seconds float64) float64 { 23 | return ToRadians(SecondsToDegrees(seconds)) 24 | } 25 | 26 | // Mod2Pi 把角度限制在[0, 2π]之间 27 | func Mod2Pi(r float64) float64 { 28 | for r < 0 { 29 | r += math.Pi * 2 30 | } 31 | for r > 2*math.Pi { 32 | r -= math.Pi * 2 33 | } 34 | return r 35 | } 36 | 37 | // ModPi 把角度限制在[-π, π]之间 38 | func ModPi(r float64) float64 { 39 | for r < -math.Pi { 40 | r += math.Pi * 2 41 | } 42 | for r > math.Pi { 43 | r -= math.Pi * 2 44 | } 45 | return r 46 | } 47 | 48 | // SecondsToDegrees 把角秒换算成角度 49 | func SecondsToDegrees(seconds float64) float64 { 50 | return seconds / 3600 51 | } 52 | 53 | // DmsToDegrees 把度分秒表示的角度换算成度 54 | func DmsToDegrees(degrees int, mintues int, seconds float64) float64 { 55 | return float64(degrees) + float64(mintues)/60 + seconds/3600 56 | } 57 | 58 | // DmsToSeconds 把度分秒表示的角度换算成角秒(arcsecond) 59 | func DmsToSeconds(d int, m int, s float64) float64 { 60 | return float64(d)*3600 + float64(m)*60 + s 61 | } 62 | 63 | // DmsToRadians 把度分秒表示的角度换算成弧度(rad) 64 | func DmsToRadians(d int, m int, s float64) float64 { 65 | return ToRadians(DmsToDegrees(d, m, s)) 66 | } 67 | 68 | // NewtonIteration 牛顿迭代法求解方程的根 69 | func NewtonIteration(f func(float64) float64, x0 float64) float64 { 70 | const Epsilon = 1e-7 71 | const Delta = 5e-6 72 | var x float64 73 | 74 | for { 75 | x = x0 76 | fx := f(x) 77 | // 导数 78 | fpx := (f(x+Delta) - f(x-Delta)) / Delta / 2 79 | x0 = x - fx/fpx 80 | if math.Abs(x0-x) <= Epsilon { 81 | break 82 | } 83 | } 84 | return x 85 | } 86 | -------------------------------------------------------------------------------- /calendar/lunar/mathutil_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package lunar 6 | 7 | import ( 8 | "math" 9 | "testing" 10 | 11 | "github.com/stretchr/testify/assert" 12 | ) 13 | 14 | func TestMathUtil(t *testing.T) { 15 | 16 | assert.Equal(t, ToRadians(90), math.Pi/2) 17 | assert.Equal(t, SecondsToRadians(648000), math.Pi) 18 | assert.Equal(t, SecondsToDegrees(648000), float64(180)) 19 | assert.Equal(t, DmsToDegrees(40, 11, 15), 40.1875) 20 | assert.Equal(t, DmsToSeconds(40, 11, 15), float64(144675)) 21 | assert.Equal(t, DmsToRadians(40, 11, 15), float64(0.7014041931452212)) 22 | 23 | rad := Mod2Pi(3 * math.Pi) 24 | assert.Equal(t, rad, math.Pi) 25 | rad = Mod2Pi(-math.Pi) 26 | assert.Equal(t, rad, math.Pi) 27 | rad = ModPi(2 * math.Pi) 28 | assert.Equal(t, rad, float64(0)) 29 | rad = ModPi(-2 * math.Pi) 30 | assert.Equal(t, rad, float64(0)) 31 | } 32 | -------------------------------------------------------------------------------- /calendar/lunar/newmoon.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package lunar 6 | 7 | func getNewMoonJD(jd0 float64) float64 { 8 | jd := NewtonIteration( 9 | func(x float64) float64 { 10 | return ModPi(GetEarthEclipticLongitudeForSun(x) - GetMoonEclipticLongitudeEC(x)) 11 | }, jd0) 12 | return jd 13 | } 14 | -------------------------------------------------------------------------------- /calendar/lunar/newmoon_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package lunar 6 | 7 | import ( 8 | "github.com/linuxdeepin/go-lib/calendar/util" 9 | "testing" 10 | ) 11 | 12 | func Test_getNewMoonJD(t *testing.T) { 13 | jd0 := float64(util.ToJulianDate(2012, 1, 10)) 14 | t.Logf("jd0: %f", jd0) 15 | jd := getNewMoonJD(jd0) 16 | dt := util.GetDateTimeFromJulianDay(jd) 17 | t.Log(dt) 18 | } 19 | -------------------------------------------------------------------------------- /calendar/lunar/solarterms.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package lunar 6 | 7 | import ( 8 | "math" 9 | "github.com/linuxdeepin/go-lib/calendar/util" 10 | ) 11 | 12 | var SolarTermNames = []string{ 13 | "春分", 14 | "清明", 15 | "谷雨", 16 | "立夏", 17 | "小满", 18 | "芒种", 19 | "夏至", 20 | "小暑", 21 | "大暑", 22 | "立秋", 23 | "处暑", 24 | "白露", 25 | "秋分", 26 | "寒露", 27 | "霜降", 28 | "立冬", 29 | "小雪", 30 | "大雪", 31 | "冬至", 32 | "小寒", 33 | "大寒", 34 | "立春", 35 | "雨水", 36 | "惊蛰", 37 | } 38 | 39 | const ( 40 | ChunFen int = iota 41 | QingMing 42 | GuYu 43 | LiXia 44 | XiaoMan 45 | MangZhong 46 | XiaZhi 47 | XiaoShu 48 | DaShu 49 | LiQiu 50 | ChuShu 51 | BaiLu 52 | QiuFen 53 | HanLu 54 | ShuangJiang 55 | LiDong 56 | XiaoXue 57 | DaXue 58 | DongZhi 59 | XiaoHan 60 | DaHan 61 | LiChun 62 | YuShui 63 | JingZhe 64 | ) 65 | 66 | // GetSolarTermName 获取二十四节气名 67 | func GetSolarTermName(order int) string { 68 | if 0 <= order && order <= 23 { 69 | return SolarTermNames[order] 70 | } 71 | return "" 72 | } 73 | 74 | // GetSolarTermJD 使用牛顿迭代法计算24节气的时间 75 | // f(x) = Vsop87dEarthUtil.getEarthEclipticLongitudeForSun(x) - angle = 0 76 | // year 年 77 | // order 节气序号 78 | // 返回 节气的儒略日力学时间 TD 79 | func GetSolarTermJD(year, order int) float64 { 80 | const RADIANS_PER_TERM = math.Pi / 12.0 81 | angle := float64(order) * RADIANS_PER_TERM 82 | month := ((order+1)/2+2)%12 + 1 83 | // 春分 order 0 84 | // 3 月 20 号 85 | var day int = 6 86 | if order%2 == 0 { 87 | day = 20 88 | } 89 | 90 | jd0 := util.ToJulianDateHMS(year, month, day, 12, 0, 0.0) 91 | jd := NewtonIteration(func(x float64) float64 { 92 | return ModPi(GetEarthEclipticLongitudeForSun(x) - angle) 93 | }, jd0) 94 | 95 | return jd 96 | } 97 | -------------------------------------------------------------------------------- /calendar/lunar/solarterms_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package lunar 6 | 7 | import ( 8 | "strings" 9 | "testing" 10 | 11 | "github.com/stretchr/testify/assert" 12 | "github.com/linuxdeepin/go-lib/calendar/util" 13 | ) 14 | 15 | func TestSolarTerms(t *testing.T) { 16 | 17 | assert.Equal(t, GetSolarTermName(DongZhi), "冬至") 18 | 19 | var stNameList []string 20 | for i := -1; i < 25; i++ { 21 | name := GetSolarTermName(i) 22 | stNameList = append(stNameList, name) 23 | } 24 | stNameListStr := strings.Join(stNameList, ",") 25 | const testStNameListStr = ",春分,清明,谷雨,立夏,小满,芒种,夏至,小暑,大暑,立秋,处暑,白露,秋分,寒露,霜降,立冬,小雪,大雪,冬至,小寒,大寒,立春,雨水,惊蛰," 26 | assert.Equal(t, stNameListStr, testStNameListStr) 27 | 28 | dongZhiJD := GetSolarTermJD(2016, DongZhi) 29 | dt := util.GetDateTimeFromJulianDay(dongZhiJD) 30 | assert.Equal(t, dt.String(), "2016-12-21 10:44:08 +0000 UTC") 31 | } 32 | -------------------------------------------------------------------------------- /calendar/lunar/vsop87earthd_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package lunar 6 | 7 | import ( 8 | "github.com/linuxdeepin/go-lib/calendar/util" 9 | "testing" 10 | ) 11 | 12 | //行星日心黄经(L)、日心黄纬(B)和到太阳的距离(R) 13 | // L0~5 B0~4 14 | // func GetEarthL0 (t float64) float64 { 15 | // func GetEarthL1 (t float64) float64 { 16 | // func GetEarthL2 (t float64) float64 { 17 | // func GetEarthL3 (t float64) float64 { 18 | // func GetEarthL4 (t float64) float64 { 19 | // func GetEarthL5 (t float64) float64 { 20 | // func GetEarthB0 (t float64) float64 { 21 | // func GetEarthB1 (t float64) float64 { 22 | // func GetEarthB2 (t float64) float64 { 23 | // func GetEarthB3 (t float64) float64 { 24 | // func GetEarthB4 (t float64) float64 { 25 | 26 | func Test_GetEarthXX(te *testing.T) { 27 | const t = 1.2345 28 | L0 := GetEarthL0(t) 29 | L1 := GetEarthL1(t) 30 | L2 := GetEarthL2(t) 31 | L3 := GetEarthL3(t) 32 | L4 := GetEarthL4(t) 33 | L5 := GetEarthL5(t) 34 | te.Log(L0) 35 | te.Log(L1) 36 | te.Log(L2) 37 | te.Log(L3) 38 | te.Log(L4) 39 | te.Log(L5) 40 | 41 | B0 := GetEarthB0(t) 42 | B1 := GetEarthB1(t) 43 | B2 := GetEarthB2(t) 44 | B3 := GetEarthB3(t) 45 | B4 := GetEarthB4(t) 46 | te.Log(B0) 47 | te.Log(B1) 48 | te.Log(B2) 49 | te.Log(B3) 50 | te.Log(B4) 51 | 52 | R0 := GetEarthR0(t) 53 | R1 := GetEarthR1(t) 54 | R2 := GetEarthR2(t) 55 | R3 := GetEarthR3(t) 56 | R4 := GetEarthR4(t) 57 | R5 := GetEarthR5(t) 58 | te.Log(R0) 59 | te.Log(R1) 60 | te.Log(R2) 61 | te.Log(R3) 62 | te.Log(R4) 63 | te.Log("R5 = ", R5) 64 | 65 | } 66 | 67 | func Test_GetSunEclipticLongitudeForEarth(t *testing.T) { 68 | jd := util.ToJulianDateHMS(2016, 2, 16, 6, 6, 6.0) 69 | L := GetSunEclipticLongitudeForEarth(jd) 70 | t.Log(L) 71 | } 72 | 73 | func Test_GetSunEclipticLatitudeForEarth(t *testing.T) { 74 | jd := util.ToJulianDateHMS(2016, 2, 16, 6, 6, 6.0) 75 | B := GetSunEclipticLatitudeForEarth(jd) 76 | t.Log(B) 77 | } 78 | 79 | func Test_GetSunRadiusForEarth(t *testing.T) { 80 | jd := util.ToJulianDateHMS(2016, 2, 16, 6, 6, 6.0) 81 | R := GetSunRadiusForEarth(jd) 82 | t.Log(R) 83 | } 84 | -------------------------------------------------------------------------------- /calendar/util/julianday_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package util 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func Test_GetDateFromJulianDay(t *testing.T) { 12 | y, m, d := GetDateFromJulianDay(2457438.0) 13 | t.Log(y, m, d) 14 | if y == 2016 && m == 2 && d == 19 { 15 | t.Log("ok") 16 | } else { 17 | t.Error("fail") 18 | } 19 | 20 | y, m, d = GetDateFromJulianDay(2248528.0) 21 | t.Log(y, m, d) 22 | if y == 1444 && m == 2 && d == 19 { 23 | t.Log("ok") 24 | } else { 25 | t.Error("fail") 26 | } 27 | } 28 | 29 | func Test_GetTimeFromJulianDay(t *testing.T) { 30 | h, m, s := GetTimeFromJulianDay(2457438.09546) 31 | t.Log(h, m, s) 32 | if h == 14 && m == 17 && s == 27 { 33 | t.Log("ok") 34 | } else { 35 | t.Error("fail") 36 | } 37 | 38 | h, m, s = GetTimeFromJulianDay(2457438.09851) 39 | t.Log(h, m, s) 40 | if h == 14 && m == 21 && s == 51 { 41 | t.Log("ok") 42 | } else { 43 | t.Error("fail") 44 | } 45 | } 46 | 47 | func Test_GetDateTimeFromJulianDay(t *testing.T) { 48 | dt := GetDateTimeFromJulianDay(2457438.10454) 49 | t.Log(dt) 50 | if dt.String() == "2016-02-19 14:29:22 +0000 UTC" { 51 | t.Log("ok") 52 | } else { 53 | t.Error("fail") 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /calendar/util/util_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package util 6 | 7 | import ( 8 | "testing" 9 | // "time" 10 | ) 11 | 12 | func Test_IsLeapYear(t *testing.T) { 13 | if IsLeapYear(1996) && IsLeapYear(2000) && !IsLeapYear(2001) { 14 | t.Log("ok") 15 | } else { 16 | t.Error("fail") 17 | } 18 | } 19 | 20 | func Test_GetSolarMonthDays(t *testing.T) { 21 | if 31 == GetSolarMonthDays(2001, 1) { 22 | t.Log("ok") 23 | } else { 24 | t.Error("fail") 25 | } 26 | if 29 == GetSolarMonthDays(2016, 2) { 27 | t.Log("ok") 28 | } else { 29 | t.Error("fail") 30 | } 31 | if 28 == GetSolarMonthDays(2015, 2) { 32 | t.Log("ok") 33 | } else { 34 | t.Error("fail") 35 | } 36 | } 37 | 38 | func Test_ToJulianDate(t *testing.T) { 39 | if 2443230 == ToJulianDate(1977, 3, 27) && 40 | 2453522 == ToJulianDate(2005, 5, 31) { 41 | t.Log("ok") 42 | } else { 43 | t.Error("fail") 44 | } 45 | } 46 | 47 | func Test_ToJulianDateHMS(t *testing.T) { 48 | t.Log(ToJulianDateHMS(1977, 3, 27, 6, 6, 6)) 49 | if 2.4432297542361114e+06 == ToJulianDateHMS(1977, 3, 27, 6, 6, 6) { 50 | t.Log("ok") 51 | } else { 52 | t.Error("fail") 53 | } 54 | } 55 | 56 | func Test_GetJulianThousandYears(t *testing.T) { 57 | t.Log(GetJulianThousandYears(2.2324937542361114e+06)) 58 | if -0.5997296256369298 == GetJulianThousandYears(2.2324937542361114e+06) { 59 | t.Log("ok") 60 | } else { 61 | t.Error("fail") 62 | } 63 | } 64 | 65 | func Test_GetJulianCentury(t *testing.T) { 66 | t.Log(GetJulianCentury(2.2324937542361114e+06)) 67 | if -5.997296256369297 == GetJulianCentury(2.2324937542361114e+06) { 68 | t.Log("ok") 69 | } else { 70 | t.Error("fail") 71 | } 72 | } 73 | 74 | func Test_GetWeekday(t *testing.T) { 75 | if 4 == GetWeekday(2015, 1, 1) { 76 | t.Log("ok") 77 | } else { 78 | t.Error("fail") 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /dbusutil/err.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package dbusutil 6 | 7 | import ( 8 | "encoding/json" 9 | "fmt" 10 | 11 | "github.com/godbus/dbus/v5" 12 | ) 13 | 14 | func MakeError(v Implementer, name string, args ...interface{}) *dbus.Error { 15 | interfaceName := "" 16 | if implV20, ok := v.(ImplementerV20); ok { 17 | interfaceName = implV20.GetInterfaceName() + "." 18 | } 19 | errName := interfaceName + "Error." + name 20 | msg := fmt.Sprint(args...) 21 | return &dbus.Error{ 22 | Name: errName, 23 | Body: []interface{}{msg}, 24 | } 25 | } 26 | 27 | func MakeErrorf(v Implementer, name, format string, args ...interface{}) *dbus.Error { 28 | interfaceName := "" 29 | if implV20, ok := v.(ImplementerV20); ok { 30 | interfaceName = implV20.GetInterfaceName() + "." 31 | } 32 | errName := interfaceName + "Error." + name 33 | msg := fmt.Sprintf(format, args...) 34 | return &dbus.Error{ 35 | Name: errName, 36 | Body: []interface{}{msg}, 37 | } 38 | } 39 | 40 | func MakeErrorJSON(v Implementer, name string, detail interface{}) *dbus.Error { 41 | var msg string 42 | interfaceName := "" 43 | if implV20, ok := v.(ImplementerV20); ok { 44 | interfaceName = implV20.GetInterfaceName() + "." 45 | } 46 | errName := interfaceName + "Error." + name 47 | data, err := json.Marshal(detail) 48 | if err != nil { 49 | msg = "failed to marshal json" 50 | } else { 51 | msg = string(data) 52 | } 53 | return &dbus.Error{ 54 | Name: errName, 55 | Body: []interface{}{msg}, 56 | } 57 | } 58 | 59 | type DBusError interface { 60 | Error() string 61 | Name() string 62 | } 63 | 64 | func ToError(err error) *dbus.Error { 65 | if err == nil { 66 | return nil 67 | } 68 | err0, ok := err.(DBusError) 69 | var name, msg string 70 | if ok { 71 | name = err0.Name() 72 | msg = err0.Error() 73 | } else { 74 | name = "org.deepin.dde.DBus.Error.Unnamed" 75 | msg = err.Error() 76 | } 77 | return &dbus.Error{ 78 | Name: name, 79 | Body: []interface{}{msg}, 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /dbusutil/implementer_static.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package dbusutil 6 | 7 | import ( 8 | "errors" 9 | "reflect" 10 | 11 | "github.com/godbus/dbus/v5" 12 | "github.com/godbus/dbus/v5/introspect" 13 | ) 14 | 15 | func newImplementerStatic(impl Implementer, interfaceName string, structValue reflect.Value) *implementerStatic { 16 | s := &implementerStatic{} 17 | structType := structValue.Type() 18 | s.props = getFieldPropStaticMap(structType, structValue) 19 | 20 | // 对旧代码实现兼容 21 | var methods []introspect.Method 22 | if implExt, ok := impl.(ImplementerExt); ok { 23 | methods = getMethods(implExt, implExt.GetExportedMethods()) 24 | } else { 25 | methods = getMethodsOld(impl, getMethodDetailMap(structType)) 26 | } 27 | 28 | s.introspectInterface = introspect.Interface{ 29 | Name: interfaceName, 30 | Signals: getSignals(structType), 31 | Properties: getPropsIntrospection(s.props), 32 | Methods: methods, 33 | } 34 | return s 35 | } 36 | 37 | type implementerStatic struct { 38 | props map[string]*fieldPropStatic 39 | introspectInterface introspect.Interface 40 | } 41 | 42 | func (is *implementerStatic) checkProperty(propName string) error { 43 | _, ok := is.props[propName] 44 | if ok { 45 | return nil 46 | } 47 | return errors.New("property not found") 48 | } 49 | 50 | func (is *implementerStatic) checkPropertyValue(propName string, value interface{}) error { 51 | p := is.props[propName] 52 | if p == nil { 53 | return errors.New("property not found") 54 | } 55 | 56 | if p.signature != dbus.SignatureOf(value) { 57 | return errors.New("property signature not equal") 58 | } 59 | 60 | return nil 61 | } 62 | -------------------------------------------------------------------------------- /dbusutil/match_rule_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package dbusutil 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func TestMatchRuleBuilder(t *testing.T) { 12 | ruleStr := NewMatchRuleBuilder(). 13 | Type("t1"). 14 | Path("p1"). 15 | Sender("s1"). 16 | Interface("i1"). 17 | Member("m1"). 18 | PathNamespace("pns1"). 19 | Destination("d1"). 20 | Eavesdrop(false). 21 | Arg(1, "a1"). 22 | ArgPath(2, "a2path"). 23 | ArgNamespace(3, "a3ns").BuildStr() 24 | 25 | ruleExpected := "type='t1',path='p1',sender='s1',interface='i1',member='m1',path_namespace='pns1',destination='d1',eavesdrop='false',arg1='a1',arg2path='a2path',arg3namespace='a3ns'" 26 | if ruleStr != ruleExpected { 27 | t.Errorf("ruleStr expected %q got %q", ruleExpected, ruleStr) 28 | } 29 | 30 | ruleStr = NewMatchRuleBuilder().ExtSignal("/a/b/c", "a.b.c", "Sig1").BuildStr() 31 | 32 | ruleExpected = "type='signal',path='/a/b/c',interface='a.b.c',member='Sig1'" 33 | if ruleStr != ruleExpected { 34 | t.Errorf("ruleStr expected %q got %q", ruleExpected, ruleStr) 35 | } 36 | 37 | ruleStr = NewMatchRuleBuilder().ExtPropertiesChanged("/a/b/c", 38 | "a.b.c").BuildStr() 39 | 40 | ruleExpected = "type='signal',path='/a/b/c',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',arg0namespace='a.b.c'" 41 | if ruleStr != ruleExpected { 42 | t.Errorf("ruleStr expected %q got %q", ruleExpected, ruleStr) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /dbusutil/proxy/object_mock.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package proxy 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/godbus/dbus/v5" 11 | "github.com/stretchr/testify/mock" 12 | "github.com/linuxdeepin/go-lib/dbusutil" 13 | ) 14 | 15 | type MockObject struct { 16 | mock.Mock 17 | } 18 | 19 | func (o *MockObject) Path_() dbus.ObjectPath { 20 | mockArgs := o.Called() 21 | 22 | ret, ok := mockArgs.Get(0).(dbus.ObjectPath) 23 | if !ok { 24 | panic(fmt.Sprintf("assert: arguments: 0 failed because object wasn't correct type: %v", mockArgs.Get(0))) 25 | } 26 | 27 | return ret 28 | } 29 | 30 | func (o *MockObject) ServiceName_() string { 31 | mockArgs := o.Called() 32 | 33 | return mockArgs.String(0) 34 | } 35 | 36 | func (o *MockObject) InitSignalExt(sigLoop *dbusutil.SignalLoop, ruleAuto bool) { 37 | o.Called(sigLoop, ruleAuto) 38 | } 39 | 40 | func (o *MockObject) RemoveAllHandlers() { 41 | o.Called() 42 | } 43 | 44 | func (o *MockObject) RemoveHandler(handlerId dbusutil.SignalHandlerId) { 45 | o.Called(handlerId) 46 | } 47 | 48 | func (o *MockObject) ConnectPropertiesChanged( 49 | cb func(interfaceName string, changedProperties map[string]dbus.Variant, 50 | invalidatedProperties []string)) (dbusutil.SignalHandlerId, error) { 51 | mockArgs := o.Called(cb) 52 | 53 | ret0, ok := mockArgs.Get(0).(dbusutil.SignalHandlerId) 54 | if !ok { 55 | panic(fmt.Sprintf("assert: arguments: 0 failed because object wasn't correct type: %v", mockArgs.Get(0))) 56 | } 57 | 58 | return ret0, mockArgs.Error(1) 59 | } 60 | -------------------------------------------------------------------------------- /dbusutil/proxy/rule_counter.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package proxy 6 | 7 | import ( 8 | "errors" 9 | "sync" 10 | 11 | "github.com/godbus/dbus/v5" 12 | ) 13 | 14 | var globalRuleCounter = &ruleCounter{ 15 | connRuleCount: make(map[string]map[string]uint), 16 | } 17 | 18 | type ruleCounter struct { 19 | connRuleCount map[string]map[string]uint 20 | // ^unique name ^rule 21 | mu sync.Mutex 22 | } 23 | 24 | func getConnName(conn *dbus.Conn) string { 25 | return conn.Names()[0] 26 | } 27 | 28 | func (rc *ruleCounter) addMatch(conn *dbus.Conn, rule string) error { 29 | name := getConnName(conn) 30 | if name == "" { 31 | return errors.New("conn name is empty") 32 | } 33 | rc.mu.Lock() 34 | defer rc.mu.Unlock() 35 | 36 | var count uint 37 | ruleCount, ok := rc.connRuleCount[name] 38 | if ok { 39 | count = ruleCount[rule] 40 | } else { 41 | ruleCount = make(map[string]uint) 42 | rc.connRuleCount[name] = ruleCount 43 | } 44 | if count == 0 { 45 | err := conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rule).Err 46 | if err != nil { 47 | return err 48 | } 49 | } 50 | ruleCount[rule] = count + 1 51 | return nil 52 | } 53 | 54 | func (rc *ruleCounter) removeMatch(conn *dbus.Conn, rule string) error { 55 | name := getConnName(conn) 56 | if name == "" { 57 | return errors.New("conn name is empty") 58 | } 59 | 60 | rc.mu.Lock() 61 | defer rc.mu.Unlock() 62 | 63 | var count uint 64 | ruleCount, ok := rc.connRuleCount[name] 65 | if !ok { 66 | return nil 67 | } 68 | 69 | count = ruleCount[rule] 70 | if count == 1 { 71 | err := conn.BusObject().Call("org.freedesktop.DBus.RemoveMatch", 0, rule).Err 72 | if err != nil { 73 | return err 74 | } 75 | } 76 | ruleCount[rule] = count - 1 77 | return nil 78 | } 79 | 80 | func (rc *ruleCounter) deleteConn(conn *dbus.Conn) { 81 | rc.mu.Lock() 82 | delete(rc.connRuleCount, getConnName(conn)) 83 | rc.mu.Unlock() 84 | } 85 | 86 | // DeleteConn 删除连接相关的数据,可以在你关闭这个连接之后调用。 87 | func DeleteConn(conn *dbus.Conn) { 88 | globalRuleCounter.deleteConn(conn) 89 | } 90 | -------------------------------------------------------------------------------- /dbusutilv1/err.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | package dbusutilv1 5 | 6 | import ( 7 | "encoding/json" 8 | "fmt" 9 | 10 | "github.com/godbus/dbus/v5" 11 | ) 12 | 13 | func MakeError(v Implementer, name string, args ...interface{}) *dbus.Error { 14 | errName := "Error." + name 15 | msg := fmt.Sprint(args...) 16 | return &dbus.Error{ 17 | Name: errName, 18 | Body: []interface{}{msg}, 19 | } 20 | } 21 | 22 | func MakeErrorf(v Implementer, name, format string, args ...interface{}) *dbus.Error { 23 | errName := "Error." + name 24 | msg := fmt.Sprintf(format, args...) 25 | return &dbus.Error{ 26 | Name: errName, 27 | Body: []interface{}{msg}, 28 | } 29 | } 30 | 31 | func MakeErrorJSON(v Implementer, name string, detail interface{}) *dbus.Error { 32 | var msg string 33 | errName := "Error." + name 34 | data, err := json.Marshal(detail) 35 | if err != nil { 36 | msg = "failed to marshal json" 37 | } else { 38 | msg = string(data) 39 | } 40 | return &dbus.Error{ 41 | Name: errName, 42 | Body: []interface{}{msg}, 43 | } 44 | } 45 | 46 | type DBusError interface { 47 | Error() string 48 | Name() string 49 | } 50 | 51 | func ToError(err error) *dbus.Error { 52 | if err == nil { 53 | return nil 54 | } 55 | err0, ok := err.(DBusError) 56 | var name, msg string 57 | if ok { 58 | name = err0.Name() 59 | msg = err0.Error() 60 | } else { 61 | name = "org.deepin.dde.DBus.Error.Unnamed" 62 | msg = err.Error() 63 | } 64 | return &dbus.Error{ 65 | Name: name, 66 | Body: []interface{}{msg}, 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /dbusutilv1/implementer_static.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | package dbusutilv1 5 | 6 | import ( 7 | "errors" 8 | "reflect" 9 | 10 | "github.com/godbus/dbus/v5" 11 | "github.com/godbus/dbus/v5/introspect" 12 | ) 13 | 14 | func newImplementerStatic(impl Implementer, interfaceName string, structValue reflect.Value) *implementerStatic { 15 | s := &implementerStatic{} 16 | structType := structValue.Type() 17 | s.props = getFieldPropStaticMap(structType, structValue) 18 | 19 | // 对旧代码实现兼容 20 | var methods []introspect.Method 21 | if implExt, ok := impl.(ImplementerExt); ok { 22 | methods = getMethods(implExt, implExt.GetExportedMethods()) 23 | } else { 24 | methods = getMethodsOld(impl, getMethodDetailMap(structType)) 25 | } 26 | 27 | s.introspectInterface = introspect.Interface{ 28 | Name: interfaceName, 29 | Signals: getSignals(structType), 30 | Properties: getPropsIntrospection(s.props), 31 | Methods: methods, 32 | } 33 | return s 34 | } 35 | 36 | type implementerStatic struct { 37 | props map[string]*fieldPropStatic 38 | introspectInterface introspect.Interface 39 | } 40 | 41 | func (is *implementerStatic) checkProperty(propName string) error { 42 | _, ok := is.props[propName] 43 | if ok { 44 | return nil 45 | } 46 | return errors.New("property not found") 47 | } 48 | 49 | func (is *implementerStatic) checkPropertyValue(propName string, value interface{}) error { 50 | p := is.props[propName] 51 | if p == nil { 52 | return errors.New("property not found") 53 | } 54 | 55 | if p.signature != dbus.SignatureOf(value) { 56 | return errors.New("property signature not equal") 57 | } 58 | 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /dbusutilv1/match_rule_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | package dbusutilv1 5 | 6 | import ( 7 | "testing" 8 | ) 9 | 10 | func TestMatchRuleBuilder(t *testing.T) { 11 | ruleStr := NewMatchRuleBuilder(). 12 | Type("t1"). 13 | Path("p1"). 14 | Sender("s1"). 15 | Interface("i1"). 16 | Member("m1"). 17 | PathNamespace("pns1"). 18 | Destination("d1"). 19 | Eavesdrop(false). 20 | Arg(1, "a1"). 21 | ArgPath(2, "a2path"). 22 | ArgNamespace(3, "a3ns").BuildStr() 23 | 24 | ruleExpected := "type='t1',path='p1',sender='s1',interface='i1',member='m1',path_namespace='pns1',destination='d1',eavesdrop='false',arg1='a1',arg2path='a2path',arg3namespace='a3ns'" 25 | if ruleStr != ruleExpected { 26 | t.Errorf("ruleStr expected %q got %q", ruleExpected, ruleStr) 27 | } 28 | 29 | ruleStr = NewMatchRuleBuilder().ExtSignal("/a/b/c", "a.b.c", "Sig1").BuildStr() 30 | 31 | ruleExpected = "type='signal',path='/a/b/c',interface='a.b.c',member='Sig1'" 32 | if ruleStr != ruleExpected { 33 | t.Errorf("ruleStr expected %q got %q", ruleExpected, ruleStr) 34 | } 35 | 36 | ruleStr = NewMatchRuleBuilder().ExtPropertiesChanged("/a/b/c", 37 | "a.b.c").BuildStr() 38 | 39 | ruleExpected = "type='signal',path='/a/b/c',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',arg0namespace='a.b.c'" 40 | if ruleStr != ruleExpected { 41 | t.Errorf("ruleStr expected %q got %q", ruleExpected, ruleStr) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /dbusutilv1/proxy/object_mock.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | package proxy 5 | 6 | import ( 7 | "fmt" 8 | 9 | "github.com/godbus/dbus/v5" 10 | "github.com/linuxdeepin/go-lib/dbusutilv1" 11 | "github.com/stretchr/testify/mock" 12 | ) 13 | 14 | type MockObject struct { 15 | mock.Mock 16 | } 17 | 18 | func (o *MockObject) Path_() dbus.ObjectPath { 19 | mockArgs := o.Called() 20 | 21 | ret, ok := mockArgs.Get(0).(dbus.ObjectPath) 22 | if !ok { 23 | panic(fmt.Sprintf("assert: arguments: 0 failed because object wasn't correct type: %v", mockArgs.Get(0))) 24 | } 25 | 26 | return ret 27 | } 28 | 29 | func (o *MockObject) ServiceName_() string { 30 | mockArgs := o.Called() 31 | 32 | return mockArgs.String(0) 33 | } 34 | 35 | func (o *MockObject) InitSignalExt(sigLoop *dbusutilv1.SignalLoop, ruleAuto bool) { 36 | o.Called(sigLoop, ruleAuto) 37 | } 38 | 39 | func (o *MockObject) RemoveAllHandlers() { 40 | o.Called() 41 | } 42 | 43 | func (o *MockObject) RemoveHandler(handlerId dbusutilv1.SignalHandlerId) { 44 | o.Called(handlerId) 45 | } 46 | 47 | func (o *MockObject) ConnectPropertiesChanged( 48 | cb func(interfaceName string, changedProperties map[string]dbus.Variant, 49 | invalidatedProperties []string)) (dbusutilv1.SignalHandlerId, error) { 50 | mockArgs := o.Called(cb) 51 | 52 | ret0, ok := mockArgs.Get(0).(dbusutilv1.SignalHandlerId) 53 | if !ok { 54 | panic(fmt.Sprintf("assert: arguments: 0 failed because object wasn't correct type: %v", mockArgs.Get(0))) 55 | } 56 | 57 | return ret0, mockArgs.Error(1) 58 | } 59 | -------------------------------------------------------------------------------- /dbusutilv1/proxy/rule_counter.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | package proxy 5 | 6 | import ( 7 | "errors" 8 | "sync" 9 | 10 | "github.com/godbus/dbus/v5" 11 | ) 12 | 13 | var globalRuleCounter = &ruleCounter{ 14 | connRuleCount: make(map[string]map[string]uint), 15 | } 16 | 17 | type ruleCounter struct { 18 | connRuleCount map[string]map[string]uint 19 | // ^unique name ^rule 20 | mu sync.Mutex 21 | } 22 | 23 | func getConnName(conn *dbus.Conn) string { 24 | return conn.Names()[0] 25 | } 26 | 27 | func (rc *ruleCounter) addMatch(conn *dbus.Conn, rule string) error { 28 | name := getConnName(conn) 29 | if name == "" { 30 | return errors.New("conn name is empty") 31 | } 32 | rc.mu.Lock() 33 | defer rc.mu.Unlock() 34 | 35 | var count uint 36 | ruleCount, ok := rc.connRuleCount[name] 37 | if ok { 38 | count = ruleCount[rule] 39 | } else { 40 | ruleCount = make(map[string]uint) 41 | rc.connRuleCount[name] = ruleCount 42 | } 43 | if count == 0 { 44 | err := conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rule).Err 45 | if err != nil { 46 | return err 47 | } 48 | } 49 | ruleCount[rule] = count + 1 50 | return nil 51 | } 52 | 53 | func (rc *ruleCounter) removeMatch(conn *dbus.Conn, rule string) error { 54 | name := getConnName(conn) 55 | if name == "" { 56 | return errors.New("conn name is empty") 57 | } 58 | 59 | rc.mu.Lock() 60 | defer rc.mu.Unlock() 61 | 62 | var count uint 63 | ruleCount, ok := rc.connRuleCount[name] 64 | if !ok { 65 | return nil 66 | } 67 | 68 | count = ruleCount[rule] 69 | if count == 1 { 70 | err := conn.BusObject().Call("org.freedesktop.DBus.RemoveMatch", 0, rule).Err 71 | if err != nil { 72 | return err 73 | } 74 | } 75 | ruleCount[rule] = count - 1 76 | return nil 77 | } 78 | 79 | func (rc *ruleCounter) deleteConn(conn *dbus.Conn) { 80 | rc.mu.Lock() 81 | delete(rc.connRuleCount, getConnName(conn)) 82 | rc.mu.Unlock() 83 | } 84 | 85 | // DeleteConn 删除连接相关的数据,可以在你关闭这个连接之后调用。 86 | func DeleteConn(conn *dbus.Conn) { 87 | globalRuleCounter.deleteConn(conn) 88 | } 89 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: golang-github-linuxdeepin-go-lib 2 | Section: devel 3 | Priority: extra 4 | Maintainer: Deepin Packages Builder 5 | Build-Depends: debhelper (>= 9), dh-golang, golang-go, 6 | golang-github-linuxdeepin-go-x11-client-dev, 7 | golang-gopkg-check.v1-dev, golang-github-smartystreets-goconvey-dev, golang-golang-x-image-dev, 8 | golang-gir-gobject-2.0-dev (>> 1.2.0+), golang-gir-gio-2.0-dev (>> 1.2.0+), 9 | golang-gir-glib-2.0-dev (>> 1.2.0+), golang-github-youpy-go-wav-dev, 10 | golang-github-fsnotify-fsnotify-dev, 11 | golang-github-mozillazg-go-pinyin-dev, 12 | golang-dbus-dev, 13 | libgdk-pixbuf2.0-dev, 14 | libpulse-dev, libgtk-3-dev, libcanberra-dev, golang-gopkg-alecthomas-kingpin.v2-dev, mobile-broadband-provider-info, 15 | iso-codes, dbus-x11, libasound2-dev, libpam0g-dev, golang-golang-x-net-dev, golang-github-stretchr-testify-dev, 16 | golang-golang-x-crypto-dev, libssl-dev 17 | Standards-Version: 3.9.8 18 | Homepage: https://github.com/linuxdeepin/go-lib 19 | 20 | Package: golang-github-linuxdeepin-go-lib-dev 21 | Architecture: all 22 | Depends: ${misc:Depends}, 23 | golang-github-linuxdeepin-go-x11-client-dev, 24 | golang-github-youpy-go-wav-dev, 25 | golang-github-fsnotify-fsnotify-dev, 26 | golang-github-mozillazg-go-pinyin-dev, 27 | golang-golang-x-image-dev, golang-gir-gobject-2.0-dev (>> 1.2.0+), golang-gir-gio-2.0-dev (>> 1.2.0+), 28 | golang-gir-glib-2.0-dev (>> 1.2.0+), 29 | golang-dbus-dev, 30 | libpulse-dev, libgtk-3-dev, libasound2-dev, libpam0g-dev, golang-golang-x-net-dev, 31 | golang-golang-x-crypto-dev, libssl-dev 32 | Replaces: 33 | golang-dlib-dev 34 | Conflicts: 35 | golang-dlib-dev 36 | Built-Using: ${misc:Built-Using} 37 | Description: Go bindings for Deepin Desktop Environment development 38 | DLib is a set of Go bindings/libraries for DDE development. 39 | Containing dbus (forking from guelfey), glib, gdkpixbuf, pulse and more. 40 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: go-dlib 3 | Source: https://gitcafe.com/Deepin/go-lib.git 4 | 5 | Files: debian/* 6 | Copyright: 2017 Deepin Sysdev 7 | License: GPL-2+ 8 | This package is free software; you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation; either version 2 of the License, or 11 | (at your option) any later version. 12 | . 13 | This package is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | . 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see 20 | . 21 | On Debian systems, the complete text of the GNU General 22 | Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". 23 | 24 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | 4 | export GOCACHE := /tmp/gocache 5 | 6 | export DH_GOPKG := github.com/linuxdeepin/go-lib 7 | export DH_GOLANG_INSTALL_ALL := 1 8 | 9 | %: 10 | dh $@ --buildsystem=golang --with=golang 11 | 12 | override_dh_auto_install: 13 | dh_auto_install 14 | find ${CURDIR}/debian/golang-github-linuxdeepin-go-lib-dev -regex '.*\.git\|.*testdata\|.*LICENSE\|.*\.gitignore' | xargs rm -rf 15 | 16 | override_dh_fixperms: 17 | dh_fixperms 18 | find debian -name 'build_test_locale_data' -exec chmod 755 {} \; 19 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /encoding/kv/reader_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package kv 6 | 7 | import ( 8 | "io" 9 | "os" 10 | "testing" 11 | 12 | "github.com/stretchr/testify/assert" 13 | "github.com/stretchr/testify/require" 14 | ) 15 | 16 | func TestReader(t *testing.T) { 17 | f, err := os.Open("./testdata/a") 18 | require.NoError(t, err) 19 | assert.NotNil(t, f) 20 | defer f.Close() 21 | 22 | r := NewReader(f) 23 | r.Delim = ':' 24 | r.TrimSpace = TrimDelimRightSpace | TrimTailingSpace 25 | 26 | var resultPair *Pair 27 | for { 28 | pair, err := r.Read() 29 | if err != nil { 30 | break 31 | } 32 | if pair.Key == "Pid" { 33 | resultPair = pair 34 | break 35 | } 36 | } 37 | assert.NotNil(t, resultPair) 38 | assert.Equal(t, resultPair.Value, "21722") 39 | 40 | pairs, err := r.ReadAll() 41 | require.NoError(t, err) 42 | assert.Equal(t, len(pairs), 43) 43 | 44 | f, err = os.Open("./testdata/b") 45 | require.NoError(t, err) 46 | assert.NotNil(t, f) 47 | defer f.Close() 48 | 49 | r = NewReader(f) 50 | pairs, err = r.ReadAll() 51 | require.Nil(t, pairs) 52 | assert.Equal(t, err, ErrBadLine) 53 | 54 | f, err = os.Open("./testdata/c") 55 | require.NoError(t, err) 56 | assert.NotNil(t, f) 57 | defer f.Close() 58 | 59 | r = NewReader(f) 60 | r.TrimSpace = TrimLeadingTailingSpace 61 | r.Comment = '#' 62 | 63 | pair, err := r.Read() 64 | require.NoError(t, err) 65 | assert.Equal(t, pair, &Pair{"LANG", "zh_CN.UTF-8"}) 66 | 67 | pair, err = r.Read() 68 | require.NoError(t, err) 69 | assert.Equal(t, pair, &Pair{"LANGUAGE", "zh_CN"}) 70 | 71 | pair, err = r.Read() 72 | require.Nil(t, pair) 73 | assert.Equal(t, err, io.EOF) 74 | } 75 | -------------------------------------------------------------------------------- /encoding/kv/testdata/a: -------------------------------------------------------------------------------- 1 | Name: cat 2 | State: R (running) 3 | Tgid: 21722 4 | Ngid: 0 5 | Pid: 21722 6 | PPid: 20960 7 | TracerPid: 0 8 | Uid: 1000 1000 1000 1000 9 | Gid: 1000 1000 1000 1000 10 | FDSize: 64 11 | Groups: 4 7 27 100 107 111 120 130 134 999 1000 12 | NStgid: 21722 13 | NSpid: 21722 14 | NSpgid: 21722 15 | NSsid: 20960 16 | VmPeak: 8048 kB 17 | VmSize: 8048 kB 18 | VmLck: 0 kB 19 | VmPin: 0 kB 20 | VmHWM: 788 kB 21 | VmRSS: 788 kB 22 | VmData: 324 kB 23 | VmStk: 136 kB 24 | VmExe: 48 kB 25 | VmLib: 1772 kB 26 | VmPTE: 40 kB 27 | VmPMD: 12 kB 28 | VmSwap: 0 kB 29 | HugetlbPages: 0 kB 30 | Threads: 1 31 | SigQ: 0/30759 32 | SigPnd: 0000000000000000 33 | ShdPnd: 0000000000000000 34 | SigBlk: 0000000000000000 35 | SigIgn: 0000000000000000 36 | SigCgt: 0000000000000000 37 | CapInh: 0000000000000000 38 | CapPrm: 0000000000000000 39 | CapEff: 0000000000000000 40 | CapBnd: 0000003fffffffff 41 | CapAmb: 0000000000000000 42 | Seccomp: 0 43 | Cpus_allowed: ff 44 | Cpus_allowed_list: 0-7 45 | Mems_allowed: 00000000,00000001 46 | Mems_allowed_list: 0 47 | voluntary_ctxt_switches: 0 48 | nonvoluntary_ctxt_switches: 1 49 | -------------------------------------------------------------------------------- /encoding/kv/testdata/b: -------------------------------------------------------------------------------- 1 | LANG=zh_CN.UTF-8 2 | LANGUAGE=zh_CN 3 | X 4 | -------------------------------------------------------------------------------- /encoding/kv/testdata/c: -------------------------------------------------------------------------------- 1 | # comment 2 | # comment 3 | LANG=zh_CN.UTF-8 4 | LANGUAGE=zh_CN 5 | -------------------------------------------------------------------------------- /gdkpixbuf/README.md: -------------------------------------------------------------------------------- 1 | Go 图形处理库, 主要围绕 GdkPixbuf 库进行增强开发. 支持对图片进行 2 | 剪切, 翻转, 缩放, 混合, 模糊处理等操作. 3 | 4 | API 的命名风格与 github.com/linuxdeepin/go-lib/graphic 库相同, 以 Blur 操作为例: 5 | - **Blur** 对 C.GdkPixbuf 对象进行模糊处理 6 | 7 | - **BlurImage** 对目标文件进行模糊处理 8 | 9 | - **BlurImageCache** 对目标文件进行模糊处理, 同时将处理后的文件放到缓 10 | 存目录, 下次对同一文件进行相同操作时可以大大提高速度 11 | -------------------------------------------------------------------------------- /gdkpixbuf/blur.c: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | #include 6 | #include 7 | #include 8 | #include "gaussianiir2d.h" 9 | 10 | int blur(GdkPixbuf *pixbuf, double sigma, double numsteps) { 11 | int width = gdk_pixbuf_get_width(pixbuf); 12 | int height = gdk_pixbuf_get_height(pixbuf); 13 | int rowstride = gdk_pixbuf_get_rowstride(pixbuf); 14 | int n_channels = gdk_pixbuf_get_n_channels(pixbuf); 15 | guchar *image_data = gdk_pixbuf_get_pixels(pixbuf); 16 | gaussianiir2d_pixbuf_c(image_data, width, height, 17 | rowstride, n_channels, sigma, numsteps); 18 | return TRUE; 19 | } 20 | -------------------------------------------------------------------------------- /gdkpixbuf/blur.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package gdkpixbuf 6 | 7 | // #cgo pkg-config: gdk-pixbuf-2.0 8 | // #cgo LDFLAGS: -lm 9 | // #include 10 | // #include "blur.h" 11 | import "C" 12 | 13 | import ( 14 | "fmt" 15 | "github.com/linuxdeepin/go-lib/utils" 16 | ) 17 | 18 | // BlurImage generate blur effect to an image file. 19 | func BlurImage(srcFile, dstFile string, sigma, numSteps float64, f Format) (err error) { 20 | srcPixbuf, err := NewPixbufFromFile(srcFile) 21 | defer FreePixbuf(srcPixbuf) 22 | if err != nil { 23 | return 24 | } 25 | err = Blur(srcPixbuf, sigma, numSteps) 26 | if err != nil { 27 | return 28 | } 29 | err = Save(srcPixbuf, dstFile, f) 30 | return 31 | } 32 | 33 | // BlurImageCache generate and save the blurred image file to cache 34 | // directory, if target file already exists, just return it. 35 | func BlurImageCache(srcFile string, sigma, numSteps float64, f Format) (dstFile string, useCache bool, err error) { 36 | dstFile = generateCacheFilePath(fmt.Sprintf("BlurImageCache%s%f%f%s", srcFile, sigma, numSteps, f)) 37 | if utils.IsFileExist(dstFile) { 38 | // return cache file 39 | useCache = true 40 | return 41 | } 42 | err = BlurImage(srcFile, dstFile, sigma, numSteps, f) 43 | return 44 | } 45 | 46 | // Blur generate blur effect to pixbuf object. 47 | func Blur(pixbuf *C.GdkPixbuf, sigma, numSteps float64) (err error) { 48 | defaultError := fmt.Errorf("blur gdkpixbuf failed, pixbuf=%v, sigma=%v, numSteps=%v", pixbuf, sigma, numSteps) 49 | ret := C.blur(pixbuf, C.double(sigma), C.double(numSteps)) 50 | if ret == 0 { 51 | err = defaultError 52 | return 53 | } 54 | return 55 | } 56 | -------------------------------------------------------------------------------- /gdkpixbuf/blur.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | #ifndef _BLUR_H 6 | #define _BLUR_H 1 7 | 8 | #include 9 | 10 | int blur(GdkPixbuf *src_pixbuf, double sigma, double numsteps); 11 | 12 | #endif /* _BLUR_H */ 13 | -------------------------------------------------------------------------------- /gdkpixbuf/gaussianiir2d.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | #ifndef _GAUSSIANIIR2D_H_ 6 | #define _GAUSSIANIIR2D_H_ 7 | 8 | #include 9 | 10 | void gaussianiir2d_f(double* image_f, 11 | long width, long height, 12 | double sigma, long numsteps); 13 | /* 14 | * image data format 15 | * 16 | * 1. _pixbuf_c: use GdkPixbuf format. 17 | * p = pixels + y * rowstride + x* n_channels 18 | * 19 | * 2. gaussianiir2d_c: use cairo image data 20 | */ 21 | void gaussianiir2d_pixbuf_c(unsigned char* image_data, 22 | int width, int height, 23 | int rowstride, int n_channels, 24 | double sigma, double numsteps); 25 | #if 0 26 | void gaussianiir2d_c(unsigned char* image_c, 27 | long width, long height, 28 | double sigma, long numsteps); 29 | 30 | #endif 31 | #endif /* _GAUSSIANIIR2D_H_ */ 32 | -------------------------------------------------------------------------------- /gdkpixbuf/gdk_pixbuf_utils.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | #ifndef _GDK_PIXBUF_UTILS_H 6 | #define _GDK_PIXBUF_UTILS_H 1 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | int init_gdk_xlib(); 13 | int init_gdk(); 14 | const char *get_image_format(const char *img_file); 15 | int get_image_size(const char *img_file, int *width, int *height); 16 | int get_dominant_color(const GdkPixbuf *pixbuf, double *r, double *g, double *b); 17 | int save(GdkPixbuf *pixbuf, const char *dest_file, const char *format); 18 | GdkPixbuf *new_pixbuf_from_file(const char *img_file); 19 | Pixmap convert_pixbuf_to_xpixmap(GdkPixbuf *pixbuf); 20 | GdkPixbuf *convert_xpixmap_to_pixbuf(const Pixmap xpixmap, int width, int height); 21 | GdkPixbuf *copy_area_simple(const GdkPixbuf *src_pixbuf, int src_x, int src_y, int width, int height); 22 | GdkPixbuf *screenshot(); 23 | 24 | #endif /* _GDK_PIXBUF_UTILS_H */ 25 | -------------------------------------------------------------------------------- /gdkpixbuf/testdata/origin_1920x1080.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gdkpixbuf/testdata/origin_1920x1080.jpg -------------------------------------------------------------------------------- /gdkpixbuf/testdata/origin_icon_1_48x48.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gdkpixbuf/testdata/origin_icon_1_48x48.bmp -------------------------------------------------------------------------------- /gdkpixbuf/testdata/origin_icon_1_48x48.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gdkpixbuf/testdata/origin_icon_1_48x48.gif -------------------------------------------------------------------------------- /gdkpixbuf/testdata/origin_icon_1_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gdkpixbuf/testdata/origin_icon_1_48x48.png -------------------------------------------------------------------------------- /gdkpixbuf/testdata/origin_icon_1_48x48.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | .',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'. 4 | ..'''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'''.. 5 | .','..'',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''..','. 6 | .'''.'';lxxxkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkxxdl;''''',. 7 | .''',';:dKXXXXXXKXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK0d:;'''''. 8 | '''''ck0XXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKOxc''''' 9 | '''''o0KKKXXXXXKKXXKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK00l''''. 10 | .''''o0KXXXXXXXK00KKKKKKKKKKKKKKKKKKKKK000KKKKKKKK0Ol''''. 11 | .''''l0KXXXK0OOkxxkOOOOO0K0OOOO00OOOOO0OkkOOOOKKKK0Ol''''. 12 | .''''l0KKKKOkOOOxxdxxkkxxkxxkkxxkkkOOkxkxdxOOxkKKK0Ol''''. 13 | .''''l00KKKOxkkkxxddxxxkkxddxxxkkxxOkxxxxox00xkKKK0Ol''''. 14 | ....'l0KKKKK0OOOO00OOOO000OOOOOOkxkOOO00OO0KK00KKK0Ol'.... 15 | .'l00KKKKKKKKKKKKKKKKKKKKKKKK000KKKKKKKKKKKKKKK0Ol'. 16 | ..l00KKKKK000000KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK0Ol'. 17 | ...'l00KKKK0OOOOOO00000000000KKKKKKKKKKKKKKKKKKKK0Ol'... 18 | ..''''l00KKKK0OOOOOOOOOOOOOOOOOOOOOOOOOOOO00O000KKK0Ol''''.. 19 | .'.''lO0KKKK0OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0KKK0Ol''''. 20 | .'.'.l00KKKK0OOOOOOOOOOOOOOOOOOOOOOOOOOOOO00000KKK0Ol'.... 21 | .'''.l00KKKK0OOOOOOOOOOO000000000000000000KKKKKKKK0Ol..'.. 22 | .....l00KKKK0OOOOOOOOOOO00000KKKKKKKKKKKKKKKKKKKKK0Ol..... 23 | .....lO0KKKK00000000000000000KKKKKKKKKKKKKKKKKKK0K0Ol..... 24 | .....ckOKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK00KOxc..... 25 | .....,:d0KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK0Oo:,..... 26 | .......,lkOO000000000000000000000000000000000OOOxl,....... 27 | .......',;;:::::::::::::::::::::::::::::::::;;;,'....... 28 | ........................................................ 29 | .................................................. 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /gdkpixbuf/testdata/origin_icon_2_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gdkpixbuf/testdata/origin_icon_2_48x48.png -------------------------------------------------------------------------------- /gdkpixbuf/testdata/origin_not_image: -------------------------------------------------------------------------------- 1 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 2 | -------------------------------------------------------------------------------- /gdkpixbuf/testdata/origin_small_200x200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gdkpixbuf/testdata/origin_small_200x200.png -------------------------------------------------------------------------------- /gdkpixbuf/utils.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package gdkpixbuf 6 | 7 | import ( 8 | "github.com/linuxdeepin/go-lib/graphic" 9 | "github.com/linuxdeepin/go-lib/utils" 10 | ) 11 | 12 | // function links to lib/graphic 13 | 14 | func generateCacheFilePath(keyword string) string { 15 | return utils.GenerateCacheFilePathWithPrefix("graphic", keyword) 16 | } 17 | 18 | // Rgb2Hsv convert color format from RGB(r, g, b=[0..255]) to HSV(h=[0..360), s,v=[0..1]). 19 | func Rgb2Hsv(r, g, b uint8) (h, s, v float64) { 20 | return graphic.Rgb2Hsv(r, g, b) 21 | } 22 | 23 | // Hsv2Rgb convert color format from HSV(h=[0..360), s,v=[0..1]) to RGB(r, g, b=[0..255]). 24 | func Hsv2Rgb(h, s, v float64) (r, g, b uint8) { 25 | return graphic.Hsv2Rgb(h, s, v) 26 | } 27 | 28 | // GetPreferScaleClipRect get the maximum rectangle in center of 29 | // image which with the same scale to reference width/heigh. 30 | func GetPreferScaleClipRect(refWidth, refHeight, imgWidth, imgHeight int) (x, y, w, h int, err error) { 31 | x, y, w, h, err = graphic.GetPreferScaleClipRect(refWidth, refHeight, imgWidth, imgHeight) 32 | return 33 | } 34 | -------------------------------------------------------------------------------- /gettext/testdata/gen_mo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for p in *.po ;do 4 | name=${p%.po} 5 | mkdir -p locale/$name/LC_MESSAGES 6 | msgfmt $p -o locale/$name/LC_MESSAGES/test.mo 7 | done 8 | -------------------------------------------------------------------------------- /gettext/testdata/locale/ar/LC_MESSAGES/test.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gettext/testdata/locale/ar/LC_MESSAGES/test.mo -------------------------------------------------------------------------------- /gettext/testdata/locale/zh_CN/LC_MESSAGES/test.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gettext/testdata/locale/zh_CN/LC_MESSAGES/test.mo -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_ADDRESS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gettext/testdata/locale_def/en_US.UTF-8/LC_ADDRESS -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_COLLATE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gettext/testdata/locale_def/en_US.UTF-8/LC_COLLATE -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_CTYPE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gettext/testdata/locale_def/en_US.UTF-8/LC_CTYPE -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_IDENTIFICATION: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gettext/testdata/locale_def/en_US.UTF-8/LC_IDENTIFICATION -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_MEASUREMENT: -------------------------------------------------------------------------------- 1 |  UTF-8 -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_MESSAGES/SYS_LC_MESSAGES: -------------------------------------------------------------------------------- 1 |  $,03^[+1yY]^[-0nN]yesnoUTF-8 -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_MONETARY: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gettext/testdata/locale_def/en_US.UTF-8/LC_MONETARY -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_NAME: -------------------------------------------------------------------------------- 1 |  $348=CG%d%t%g%t%m%t%fMr.Mrs.Miss.Ms.UTF-8 -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_NUMERIC: -------------------------------------------------------------------------------- 1 |   "$(,0.,.,UTF-8 -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_PAPER: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gettext/testdata/locale_def/en_US.UTF-8/LC_PAPER -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_TELEPHONE: -------------------------------------------------------------------------------- 1 |  (035+%c (%a) %l(%a) %l111UTF-8 -------------------------------------------------------------------------------- /gettext/testdata/locale_def/en_US.UTF-8/LC_TIME: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gettext/testdata/locale_def/en_US.UTF-8/LC_TIME -------------------------------------------------------------------------------- /gettext/testdata/plural/es.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2015-06-30 17:51+0800\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=utf-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=n>1;\n" 20 | 21 | #: t.go:4 22 | #, c-format 23 | msgid "%d apple" 24 | msgid_plural "%d apples" 25 | msgstr[0] "%d manzana" 26 | msgstr[1] "%d manzanas" 27 | 28 | #: t.go:5 29 | #, c-format 30 | msgid "%d person" 31 | msgid_plural "%d persons" 32 | msgstr[0] "%d persona" 33 | msgstr[1] "%d personas" 34 | -------------------------------------------------------------------------------- /gettext/testdata/plural/gen_mo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for p in *.po ;do 4 | name=${p%.po} 5 | mkdir -p locale/$name/LC_MESSAGES 6 | msgfmt $p -o locale/$name/LC_MESSAGES/test.mo 7 | done 8 | -------------------------------------------------------------------------------- /gettext/testdata/plural/locale/es/LC_MESSAGES/test.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gettext/testdata/plural/locale/es/LC_MESSAGES/test.mo -------------------------------------------------------------------------------- /gettext/testdata/plural/locale/zh_CN/LC_MESSAGES/test.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/gettext/testdata/plural/locale/zh_CN/LC_MESSAGES/test.mo -------------------------------------------------------------------------------- /gettext/testdata/plural/plural.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2015-06-30 17:51+0800\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" 20 | 21 | #: t.go:4 22 | #, c-format 23 | msgid "%d apple" 24 | msgid_plural "%d apples" 25 | msgstr[0] "" 26 | msgstr[1] "" 27 | 28 | #: t.go:5 29 | #, c-format 30 | msgid "%d person" 31 | msgid_plural "%d persons" 32 | msgstr[0] "" 33 | msgstr[1] "" 34 | -------------------------------------------------------------------------------- /gettext/testdata/plural/t.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package main 6 | 7 | func main() { 8 | NTr("%d apple", "%d apples", 0) 9 | DNGettext("domain", "%d person", "%d persons", 0) 10 | } 11 | -------------------------------------------------------------------------------- /gettext/testdata/plural/update_pot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | xgettext -L c --keyword=NTr:1,2 --keyword=DNGettext:2,3 -o plural.pot t.go 5 | -------------------------------------------------------------------------------- /gettext/testdata/plural/zh_CN.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2015-06-30 17:51+0800\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=utf-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=1; plural=0;\n" 20 | 21 | #: t.go:4 22 | #, c-format 23 | msgid "%d apple" 24 | msgid_plural "%d apples" 25 | msgstr[0] "%d苹果" 26 | 27 | #: t.go:5 28 | #, c-format 29 | msgid "%d person" 30 | msgid_plural "%d persons" 31 | msgstr[0] "%d人" 32 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/linuxdeepin/go-lib 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/fsnotify/fsnotify v1.5.4 7 | github.com/linuxdeepin/go-x11-client v0.0.0-20220830090948-78fe92b727bb 8 | github.com/mozillazg/go-pinyin v0.19.0 9 | github.com/smartystreets/goconvey v1.7.2 10 | github.com/stretchr/testify v1.8.0 11 | github.com/youpy/go-wav v0.3.2 12 | golang.org/x/image v0.10.0 13 | gopkg.in/alecthomas/kingpin.v2 v2.2.6 14 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c 15 | ) 16 | 17 | require ( 18 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect 19 | github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect 20 | github.com/godbus/dbus/v5 v5.1.0 21 | github.com/linuxdeepin/go-gir v0.0.0-20230331033513-a8d7a9e89f9b 22 | ) 23 | -------------------------------------------------------------------------------- /graphic/README.md: -------------------------------------------------------------------------------- 1 | Go 图形处理库, 主要围绕 Go 自身的 image 库进行增强开发. 支持对图片进行 2 | 剪切, 翻转, 缩放, 混合等操作. 3 | 4 | 关于 API 的命名风格, 以 Clip 操作为例: 5 | - **Clip** 对 image.Image 对象进行剪切操作 6 | 7 | - **ClipImage** 对目标文件进行剪切操作 8 | 9 | - **ClipImageCache** 对目标文件进行剪切操作, 同时将处理后的文件放到缓 10 | 存目录, 下次对同一文件进行相同操作时可以大大提高速度 11 | -------------------------------------------------------------------------------- /graphic/clip.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "fmt" 9 | "image" 10 | "image/draw" 11 | ) 12 | 13 | // ClipImage clip image file that format is recognized and save it with target format. 14 | func ClipImage(srcfile, dstfile string, x, y, w, h int, f Format) (err error) { 15 | srcimg, err := LoadImage(srcfile) 16 | if err != nil { 17 | return 18 | } 19 | dstimg := Clip(srcimg, x, y, w, h) 20 | err = SaveImage(dstfile, dstimg, f) 21 | dstimg.Pix = nil 22 | return 23 | } 24 | 25 | // ClipImageCache clip any recognized format image and save to cache 26 | // directory, if already exists, just return it. 27 | func ClipImageCache(srcfile string, x, y, w, h int, f Format) (dstfile string, useCache bool, err error) { 28 | dstfile = generateCacheFilePath(fmt.Sprintf("ClipImageCache%s%d%d%d%d%s", srcfile, x, y, w, h, f)) 29 | if isFileExists(dstfile) { 30 | useCache = true 31 | return 32 | } 33 | err = ClipImage(srcfile, dstfile, x, y, w, h, f) 34 | return 35 | } 36 | 37 | // ClipImage clip image object. 38 | func Clip(srcimg image.Image, x, y, w, h int) (dstimg *image.RGBA) { 39 | dstimg = image.NewRGBA(image.Rect(0, 0, w, h)) 40 | draw.Draw(dstimg, dstimg.Bounds(), srcimg, image.Point{x, y}, draw.Src) 41 | return 42 | } 43 | -------------------------------------------------------------------------------- /graphic/convert.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "fmt" 9 | ) 10 | 11 | // ConvertImage converts from any recognized format to target format image. 12 | func ConvertImage(srcfile, dstfile string, f Format) (err error) { 13 | srcimg, err := LoadImage(srcfile) 14 | if err != nil { 15 | return 16 | } 17 | return SaveImage(dstfile, srcimg, f) 18 | } 19 | 20 | // ConvertImageCache converts from any recognized format to cache 21 | // directory, if already exists, just return it. 22 | func ConvertImageCache(srcfile string, f Format) (dstfile string, useCache bool, err error) { 23 | dstfile = generateCacheFilePath(fmt.Sprintf("ConvertImageCache%s%s", srcfile, f)) 24 | if isFileExists(dstfile) { 25 | useCache = true 26 | return 27 | } 28 | err = ConvertImage(srcfile, dstfile, f) 29 | return 30 | } 31 | -------------------------------------------------------------------------------- /graphic/data_uri.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "bytes" 9 | "encoding/base64" 10 | "fmt" 11 | "image" 12 | "io/ioutil" 13 | "strings" 14 | ) 15 | 16 | // ConvertImageToDataUri convert image file to data uri. 17 | func ConvertImageToDataUri(imgfile string) (dataUri string, err error) { 18 | data, err := ioutil.ReadFile(imgfile) 19 | if err != nil { 20 | return 21 | } 22 | f, err := GetImageFormat(imgfile) 23 | if err != nil { 24 | return 25 | } 26 | contentType := imageFormatToDataUriContentType(f) 27 | dataUri = fmt.Sprintf("data:%s;base64,%s", contentType, base64.StdEncoding.EncodeToString(data)) 28 | return 29 | } 30 | 31 | // ConvertImageToDataUri convert image.Image object to data uri. 32 | func ConvertImageObjectToDataUri(img image.Image, f Format) (dataUri string, err error) { 33 | byteBuf := new(bytes.Buffer) 34 | err = doSaveImage(byteBuf, img, f) 35 | if err != nil { 36 | return 37 | } 38 | data := byteBuf.Bytes() 39 | contentType := imageFormatToDataUriContentType(f) 40 | dataUri = fmt.Sprintf("data:%s;base64,%s", contentType, base64.StdEncoding.EncodeToString(data)) 41 | byteBuf.Reset() 42 | return 43 | } 44 | 45 | // ConvertDataUriToImage convert data uri to image file. 46 | func ConvertDataUriToImage(dataUri string, dstfile string, f Format) (err error) { 47 | img, err := LoadImageFromDataUri(dataUri) 48 | if err != nil { 49 | return 50 | } 51 | return SaveImage(dstfile, img, f) 52 | } 53 | 54 | // LoadImageFromDataUri convert data uri to image object. 55 | func LoadImageFromDataUri(dataUri string) (img image.Image, err error) { 56 | strs := strings.Split(dataUri, ",") // ;base64, 57 | if len(strs) != 2 { 58 | err = fmt.Errorf("invalid data uri: %s", dataUri) 59 | return 60 | } 61 | data, err := base64.StdEncoding.DecodeString(strs[1]) 62 | if err != nil { 63 | return 64 | } 65 | r := bytes.NewReader(data) 66 | img, _, err = image.Decode(r) 67 | return 68 | } 69 | 70 | func imageFormatToDataUriContentType(f Format) (contentType string) { 71 | contentType = fmt.Sprintf("image/%s", f) 72 | return 73 | } 74 | -------------------------------------------------------------------------------- /graphic/dominant_color.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "fmt" 9 | "image" 10 | ) 11 | 12 | // GetDominantColorOfImage return the dominant hsv color of an image. 13 | func GetDominantColorOfImage(imgfile string) (h, s, v float64, err error) { 14 | img, err := LoadImage(imgfile) 15 | if err != nil { 16 | return 17 | } 18 | return doGetDominantColorOfImage(img) 19 | } 20 | 21 | func doGetDominantColorOfImage(img image.Image) (h, s, v float64, err error) { 22 | // loop all points in image 23 | var sumR, sumG, sumB, count uint64 24 | mx := img.Bounds().Max.X 25 | my := img.Bounds().Max.Y 26 | count = uint64(mx * my) 27 | if count == 0 { 28 | err = fmt.Errorf("image is empty") 29 | return 30 | } 31 | for x := 0; x < mx; x++ { 32 | for y := 0; y < my; y++ { 33 | c := img.At(x, y) 34 | rr, gg, bb, _ := c.RGBA() 35 | r, g, b := rr>>8, gg>>8, bb>>8 36 | sumR += uint64(r) 37 | sumG += uint64(g) 38 | sumB += uint64(b) 39 | } 40 | } 41 | 42 | h, s, v = Rgb2Hsv(uint8(sumR/count), uint8(sumG/count), uint8(sumB/count)) 43 | return 44 | } 45 | -------------------------------------------------------------------------------- /graphic/flip.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "image" 9 | ) 10 | 11 | // FlipImageHorizontal flip image in horizontal direction, and save as 12 | // target format. 13 | func FlipImageHorizontal(srcfile, dstfile string, f Format) (err error) { 14 | srcimg, err := LoadImage(srcfile) 15 | if err != nil { 16 | return err 17 | } 18 | dstimg := doFlipImageHorizontal(srcimg) 19 | err = SaveImage(dstfile, dstimg, f) 20 | dstimg.Pix = nil 21 | return 22 | } 23 | 24 | // FlipImageVertical flip image in vertical direction, and save as 25 | // target format. 26 | func FlipImageVertical(srcfile, dstfile string, f Format) (err error) { 27 | srcimg, err := LoadImage(srcfile) 28 | if err != nil { 29 | return err 30 | } 31 | dstimg := doFlipImageVertical(srcimg) 32 | err = SaveImage(dstfile, dstimg, f) 33 | dstimg.Pix = nil 34 | return 35 | } 36 | 37 | func doFlipImageHorizontal(srcimg image.Image) (dstimg *image.RGBA) { 38 | w, h := GetSize(srcimg) 39 | dstimg = image.NewRGBA(image.Rect(0, 0, w, h)) 40 | 41 | for x := 0; x < w; x++ { 42 | for y := 0; y < h; y++ { 43 | dstimg.Set(w-x-1, y, srcimg.At(x, y)) 44 | } 45 | } 46 | 47 | return 48 | } 49 | 50 | func doFlipImageVertical(srcimg image.Image) (dstimg *image.RGBA) { 51 | w, h := GetSize(srcimg) 52 | dstimg = image.NewRGBA(image.Rect(0, 0, w, h)) 53 | 54 | for x := 0; x < w; x++ { 55 | for y := 0; y < h; y++ { 56 | dstimg.Set(x, h-y-1, srcimg.At(x, y)) 57 | } 58 | } 59 | 60 | return 61 | } 62 | -------------------------------------------------------------------------------- /graphic/format_sniff.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "bufio" 9 | "os" 10 | ) 11 | 12 | type format struct { 13 | name, magic string 14 | } 15 | 16 | // image formats: 17 | var formats = []format{ 18 | {"jpeg", "\xff\xd8"}, 19 | {"bmp", "BM????\x00\x00\x00\x00"}, 20 | {"png", "\x89PNG\r\n\x1a\n"}, 21 | {"tiff", "MM\x00\x2A"}, // little-endian 22 | {"tiff", "II\x2A\x00"}, // big-endian 23 | {"gif", "GIF8?a"}, 24 | } 25 | 26 | // Sniff determines the format of r's data. 27 | func sniff(r *bufio.Reader) format { 28 | for _, f := range formats { 29 | b, err := r.Peek(len(f.magic)) 30 | if err == nil && match(f.magic, b) { 31 | return f 32 | } 33 | } 34 | return format{} 35 | } 36 | 37 | // Match reports whether magic matches b. Magic may contain "?" wildcards. 38 | func match(magic string, b []byte) bool { 39 | if len(magic) != len(b) { 40 | return false 41 | } 42 | for i, c := range b { 43 | if magic[i] != c && magic[i] != '?' { 44 | return false 45 | } 46 | } 47 | return true 48 | } 49 | 50 | func SniffImageFormat(file string) (string, error) { 51 | fh, err := os.Open(file) 52 | if err != nil { 53 | return "", err 54 | } 55 | defer fh.Close() 56 | 57 | reader := bufio.NewReader(fh) 58 | format := sniff(reader) 59 | return format.name, nil 60 | } 61 | -------------------------------------------------------------------------------- /graphic/graphic.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | // Format defines the type of image format. 8 | type Format string 9 | 10 | // Registered image format. 11 | const ( 12 | FormatPng Format = "png" 13 | FormatJpeg Format = "jpeg" 14 | FormatBmp Format = "bmp" 15 | FormatTiff Format = "tiff" 16 | ) 17 | -------------------------------------------------------------------------------- /graphic/hsv.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "math" 9 | ) 10 | 11 | // Rgb2Hsv convert color format from RGB(r, g, b=[0..255]) to HSV(h=[0..360), s,v=[0..1]). 12 | func Rgb2Hsv(r, g, b uint8) (h, s, v float64) { 13 | fr := float64(r) / 255 14 | fg := float64(g) / 255 15 | fb := float64(b) / 255 16 | max := math.Max(math.Max(fr, fg), fb) 17 | min := math.Min(math.Min(fr, fg), fb) 18 | d := max - min 19 | 20 | if max == 0 { 21 | s = 0 22 | } else { 23 | s = d / max 24 | } 25 | 26 | v = max 27 | 28 | if max == min { 29 | h = 0 30 | } else { 31 | switch max { 32 | case fr: 33 | if fg >= fb { 34 | h = 60 * (fg - fb) / d 35 | } else { 36 | h = 60*(fg-fb)/d + 360 37 | } 38 | case fg: 39 | h = 60*(fb-fr)/d + 120 40 | case fb: 41 | h = 60*(fr-fg)/d + 240 42 | } 43 | } 44 | return 45 | } 46 | 47 | // Hsv2Rgb convert color format from HSV(h=[0..360), s,v=[0..1]) to RGB(r, g, b=[0..255]). 48 | func Hsv2Rgb(h, s, v float64) (r, g, b uint8) { 49 | var fr, fg, fb float64 50 | hi := int(math.Floor(h/60)) % 6 51 | f := h/60 - float64(hi) 52 | p := v * (1 - s) 53 | q := v * (1 - f*s) 54 | t := v * (1 - (1-f)*s) 55 | switch hi { 56 | case 0: 57 | fr, fg, fb = v, t, p 58 | case 1: 59 | fr, fg, fb = q, v, p 60 | case 2: 61 | fr, fg, fb = p, v, t 62 | case 3: 63 | fr, fg, fb = p, q, v 64 | case 4: 65 | fr, fg, fb = t, p, v 66 | case 5: 67 | fr, fg, fb = v, p, q 68 | } 69 | r = uint8((fr * 255) + 0.5) 70 | g = uint8((fg * 255) + 0.5) 71 | b = uint8((fb * 255) + 0.5) 72 | return 73 | } 74 | -------------------------------------------------------------------------------- /graphic/info.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "image" 9 | "os" 10 | dutils "github.com/linuxdeepin/go-lib/utils" 11 | ) 12 | 13 | // GetImageSize return image's width and height. 14 | func GetImageSize(imgfile string) (w, h int, err error) { 15 | f, err := os.Open(imgfile) 16 | if err != nil { 17 | return 18 | } 19 | defer f.Close() 20 | config, _, err := image.DecodeConfig(f) 21 | return config.Width, config.Height, err 22 | } 23 | 24 | func GetSize(img image.Image) (w, h int) { 25 | w = img.Bounds().Dx() 26 | h = img.Bounds().Dy() 27 | return 28 | } 29 | 30 | // GetImageFormat return image format, such as "png", "jpeg". 31 | func GetImageFormat(imgfile string) (format Format, err error) { 32 | f, err := os.Open(imgfile) 33 | if err != nil { 34 | return 35 | } 36 | defer f.Close() 37 | _, name, err := image.DecodeConfig(f) 38 | format = Format(name) 39 | return 40 | } 41 | 42 | // IsSupportedImage check if image file is supported. 43 | func IsSupportedImage(imgfile string) bool { 44 | f, err := os.Open(imgfile) 45 | if err != nil { 46 | return false 47 | } 48 | defer f.Close() 49 | _, _, err = image.DecodeConfig(f) 50 | return err == nil 51 | } 52 | 53 | func GetImagesInDir(dir string) ([]string, error) { 54 | files, err := dutils.GetFilesInDir(dir) 55 | if err != nil { 56 | return nil, err 57 | } 58 | 59 | var images []string 60 | for _, file := range files { 61 | if !IsSupportedImage(file) { 62 | continue 63 | } 64 | 65 | images = append(images, file) 66 | } 67 | 68 | return images, nil 69 | } 70 | -------------------------------------------------------------------------------- /graphic/new.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "image" 9 | "image/color" 10 | ) 11 | 12 | // NewImageWithColor create a new image file with target size and rgba. 13 | func NewImageWithColor(dstfile string, width, height int, r, g, b, a uint8, f Format) (err error) { 14 | dstimg, err := NewWithColor(width, height, r, g, b, a) 15 | if err != nil { 16 | return 17 | } 18 | err = SaveImage(dstfile, dstimg, f) 19 | dstimg.Pix = nil 20 | return 21 | } 22 | 23 | // NewWithColor create a new image object with target size and rgba. 24 | func NewWithColor(width, height int, r, g, b, a uint8) (dstimg *image.RGBA, err error) { 25 | dstimg = image.NewRGBA(image.Rect(0, 0, int(width), int(height))) 26 | color := color.RGBA{R: r, G: g, B: b, A: a} 27 | w, h := GetSize(dstimg) 28 | for i := 0; i < w; i++ { 29 | for j := 0; j < h; j++ { 30 | dstimg.SetRGBA(i, j, color) 31 | } 32 | } 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /graphic/rotate.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "image" 9 | ) 10 | 11 | // RotateImageLeft rotate image to left side. 12 | func RotateImageLeft(srcfile, dstfile string, f Format) (err error) { 13 | srcimg, err := LoadImage(srcfile) 14 | if err != nil { 15 | return err 16 | } 17 | dstimg := doRotateImageLeft(srcimg) 18 | err = SaveImage(dstfile, dstimg, f) 19 | dstimg.Pix = nil 20 | return 21 | } 22 | 23 | // RotateImageLeft rotate image to right side. 24 | func RotateImageRight(srcfile, dstfile string, f Format) (err error) { 25 | srcimg, err := LoadImage(srcfile) 26 | if err != nil { 27 | return err 28 | } 29 | dstimg := doRotateImageRight(srcimg) 30 | err = SaveImage(dstfile, dstimg, f) 31 | dstimg.Pix = nil 32 | return 33 | } 34 | 35 | func doRotateImageLeft(srcimg image.Image) (dstimg *image.RGBA) { 36 | w, h := GetSize(srcimg) 37 | dstimg = image.NewRGBA(image.Rect(0, 0, h, w)) 38 | 39 | for x := 0; x < w; x++ { 40 | for y := 0; y < h; y++ { 41 | dstimg.Set(y, w-x-1, srcimg.At(x, y)) 42 | } 43 | } 44 | 45 | return 46 | } 47 | 48 | func doRotateImageRight(srcimg image.Image) (dstimg *image.RGBA) { 49 | w, h := GetSize(srcimg) 50 | dstimg = image.NewRGBA(image.Rect(0, 0, h, w)) 51 | 52 | for x := 0; x < w; x++ { 53 | for y := 0; y < h; y++ { 54 | dstimg.Set(h-y-1, x, srcimg.At(x, y)) 55 | } 56 | } 57 | 58 | return 59 | } 60 | -------------------------------------------------------------------------------- /graphic/save_load.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "golang.org/x/image/bmp" 9 | "golang.org/x/image/tiff" 10 | "image" 11 | "image/jpeg" 12 | "image/png" 13 | "io" 14 | "os" 15 | ) 16 | 17 | // LoadImage load image file and return image.Image object. 18 | func LoadImage(imgfile string) (img image.Image, err error) { 19 | f, err := os.Open(imgfile) 20 | if err != nil { 21 | return 22 | } 23 | defer f.Close() 24 | img, _, err = image.Decode(f) 25 | return 26 | } 27 | 28 | // SaveImage save image.Image object to target file. 29 | func SaveImage(dstfile string, m image.Image, f Format) (err error) { 30 | df, err := openFileOrCreate(dstfile) 31 | if err != nil { 32 | return 33 | } 34 | defer df.Close() 35 | return doSaveImage(df, m, f) 36 | } 37 | 38 | func doSaveImage(w io.Writer, m image.Image, f Format) (err error) { 39 | switch f { 40 | case FormatPng: 41 | err = png.Encode(w, m) 42 | case FormatJpeg: 43 | err = jpeg.Encode(w, m, nil) 44 | case FormatBmp: 45 | err = bmp.Encode(w, m) 46 | case FormatTiff: 47 | err = tiff.Encode(w, m, nil) 48 | default: 49 | err = png.Encode(w, m) 50 | } 51 | return 52 | } 53 | -------------------------------------------------------------------------------- /graphic/testdata/origin_1920x1080.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/graphic/testdata/origin_1920x1080.jpg -------------------------------------------------------------------------------- /graphic/testdata/origin_icon_1_48x48.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/graphic/testdata/origin_icon_1_48x48.bmp -------------------------------------------------------------------------------- /graphic/testdata/origin_icon_1_48x48.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/graphic/testdata/origin_icon_1_48x48.gif -------------------------------------------------------------------------------- /graphic/testdata/origin_icon_1_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/graphic/testdata/origin_icon_1_48x48.png -------------------------------------------------------------------------------- /graphic/testdata/origin_icon_1_48x48.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | .',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'. 4 | ..'''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'''.. 5 | .','..'',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,''..','. 6 | .'''.'';lxxxkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkxxdl;''''',. 7 | .''',';:dKXXXXXXKXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK0d:;'''''. 8 | '''''ck0XXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKOxc''''' 9 | '''''o0KKKXXXXXKKXXKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK00l''''. 10 | .''''o0KXXXXXXXK00KKKKKKKKKKKKKKKKKKKKK000KKKKKKKK0Ol''''. 11 | .''''l0KXXXK0OOkxxkOOOOO0K0OOOO00OOOOO0OkkOOOOKKKK0Ol''''. 12 | .''''l0KKKKOkOOOxxdxxkkxxkxxkkxxkkkOOkxkxdxOOxkKKK0Ol''''. 13 | .''''l00KKKOxkkkxxddxxxkkxddxxxkkxxOkxxxxox00xkKKK0Ol''''. 14 | ....'l0KKKKK0OOOO00OOOO000OOOOOOkxkOOO00OO0KK00KKK0Ol'.... 15 | .'l00KKKKKKKKKKKKKKKKKKKKKKKK000KKKKKKKKKKKKKKK0Ol'. 16 | ..l00KKKKK000000KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK0Ol'. 17 | ...'l00KKKK0OOOOOO00000000000KKKKKKKKKKKKKKKKKKKK0Ol'... 18 | ..''''l00KKKK0OOOOOOOOOOOOOOOOOOOOOOOOOOOO00O000KKK0Ol''''.. 19 | .'.''lO0KKKK0OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0KKK0Ol''''. 20 | .'.'.l00KKKK0OOOOOOOOOOOOOOOOOOOOOOOOOOOOO00000KKK0Ol'.... 21 | .'''.l00KKKK0OOOOOOOOOOO000000000000000000KKKKKKKK0Ol..'.. 22 | .....l00KKKK0OOOOOOOOOOO00000KKKKKKKKKKKKKKKKKKKKK0Ol..... 23 | .....lO0KKKK00000000000000000KKKKKKKKKKKKKKKKKKK0K0Ol..... 24 | .....ckOKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK00KOxc..... 25 | .....,:d0KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK0Oo:,..... 26 | .......,lkOO000000000000000000000000000000000OOOxl,....... 27 | .......',;;:::::::::::::::::::::::::::::::::;;;,'....... 28 | ........................................................ 29 | .................................................. 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /graphic/testdata/origin_icon_2_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/graphic/testdata/origin_icon_2_48x48.png -------------------------------------------------------------------------------- /graphic/testdata/origin_not_image: -------------------------------------------------------------------------------- 1 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 2 | -------------------------------------------------------------------------------- /graphic/testdata/origin_small_200x200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/graphic/testdata/origin_small_200x200.png -------------------------------------------------------------------------------- /graphic/testdata/sniff_format.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/graphic/testdata/sniff_format.tiff -------------------------------------------------------------------------------- /graphic/testdata/test-get_images-noimage/icon.txt: -------------------------------------------------------------------------------- 1 | ../origin_icon.txt -------------------------------------------------------------------------------- /graphic/testdata/test-get_images/1.png: -------------------------------------------------------------------------------- 1 | ../origin_small_200x200.png -------------------------------------------------------------------------------- /graphic/testdata/test-get_images/2.png: -------------------------------------------------------------------------------- 1 | ../origin_icon_1_48x48.png -------------------------------------------------------------------------------- /graphic/testdata/test-get_images/3.png: -------------------------------------------------------------------------------- 1 | ../origin_icon_2_48x48.png -------------------------------------------------------------------------------- /graphic/utils.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package graphic 6 | 7 | import ( 8 | "image" 9 | "image/draw" 10 | "os" 11 | "github.com/linuxdeepin/go-lib/utils" 12 | ) 13 | 14 | func generateCacheFilePath(keyword string) (dstfile string) { 15 | return utils.GenerateCacheFilePathWithPrefix("graphic", keyword) 16 | } 17 | 18 | func openFileOrCreate(file string) (*os.File, error) { 19 | return os.OpenFile(file, os.O_WRONLY|os.O_CREATE, 0644) 20 | } 21 | 22 | func isFileExists(file string) bool { 23 | if _, err := os.Stat(file); err == nil { 24 | return true 25 | } else { 26 | return false 27 | } 28 | } 29 | 30 | // convert image.Image to *image.RGBA 31 | func convertToRGBA(img image.Image) (rgba *image.RGBA) { 32 | b := img.Bounds() 33 | r := image.Rect(0, 0, b.Dx(), b.Dy()) 34 | rgba = image.NewRGBA(r) 35 | draw.Draw(rgba, rgba.Bounds(), img, b.Min, draw.Src) 36 | return 37 | } 38 | -------------------------------------------------------------------------------- /gsettings/monitor_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package gsettings 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func Test_StartMonitor(t *testing.T) { 12 | // 依赖环境的测试 13 | err := StartMonitor() 14 | if err != nil { 15 | t.Skip("failed:" + err.Error()) 16 | return 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /imgutil/format_sniff.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package imgutil 6 | 7 | import ( 8 | "bufio" 9 | "os" 10 | ) 11 | 12 | type format struct { 13 | name, magic string 14 | } 15 | 16 | // image formats: 17 | var formats = []format{ 18 | {"jpeg", "\xff\xd8"}, 19 | {"bmp", "BM????\x00\x00\x00\x00"}, 20 | {"png", "\x89PNG\r\n\x1a\n"}, 21 | {"tiff", "MM\x00\x2A"}, // little-endian 22 | {"tiff", "II\x2A\x00"}, // big-endian 23 | {"gif", "GIF8?a"}, 24 | } 25 | 26 | // Sniff determines the format of r's data. 27 | func sniff(r *bufio.Reader) format { 28 | for _, f := range formats { 29 | b, err := r.Peek(len(f.magic)) 30 | if err == nil && match(f.magic, b) { 31 | return f 32 | } 33 | } 34 | return format{} 35 | } 36 | 37 | // Match reports whether magic matches b. Magic may contain "?" wildcards. 38 | func match(magic string, b []byte) bool { 39 | if len(magic) != len(b) { 40 | return false 41 | } 42 | for i, c := range b { 43 | if magic[i] != c && magic[i] != '?' { 44 | return false 45 | } 46 | } 47 | return true 48 | } 49 | 50 | func SniffFormat(file string) (string, error) { 51 | fh, err := os.Open(file) 52 | if err != nil { 53 | return "", err 54 | } 55 | defer fh.Close() 56 | 57 | reader := bufio.NewReader(fh) 58 | format := sniff(reader) 59 | return format.name, nil 60 | } 61 | -------------------------------------------------------------------------------- /imgutil/testdata/deepin-music.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/imgutil/testdata/deepin-music.bmp -------------------------------------------------------------------------------- /imgutil/testdata/deepin-music.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/imgutil/testdata/deepin-music.gif -------------------------------------------------------------------------------- /imgutil/testdata/deepin-music.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/imgutil/testdata/deepin-music.jpg -------------------------------------------------------------------------------- /imgutil/testdata/deepin-music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/imgutil/testdata/deepin-music.png -------------------------------------------------------------------------------- /imgutil/testdata/deepin-music.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/imgutil/testdata/deepin-music.tiff -------------------------------------------------------------------------------- /initializer/initializer.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package initializer 6 | 7 | // TODO: 8 | // 1. a Promise like initializer might be better. 9 | // 2. using reflect to support different initializer. 10 | 11 | // Initializer is a chainable initializer. Init/InitOnSystemBus/InitOnSystemBus will accept a initializer, 12 | // and then pass the successful return value to the next initializer. If error occurs, the rest initializers 13 | // won't be executed any more. GetError is used to access the error. 14 | type Initializer struct { 15 | v interface{} 16 | e error 17 | } 18 | 19 | // NewInitializer creates a new Initializer. 20 | func NewInitializer() *Initializer { 21 | return new(Initializer) 22 | } 23 | 24 | func noop(v interface{}) (interface{}, error) { 25 | return v, nil 26 | } 27 | 28 | func (i *Initializer) initWithHandler(fn func(interface{}) (interface{}, error), handler func(interface{}) (interface{}, error)) *Initializer { 29 | if i.e != nil { 30 | return i 31 | } 32 | 33 | var err error 34 | var v interface{} 35 | 36 | v, err = fn(i.v) 37 | if err != nil { 38 | i.e = err 39 | return i 40 | } 41 | 42 | v, err = handler(v) 43 | if err != nil { 44 | i.e = err 45 | } 46 | 47 | i.v = v 48 | 49 | return i 50 | } 51 | 52 | // Init accepts a initializer function, and pass the successful return value to next initializer. 53 | func (i *Initializer) Init(fn func(interface{}) (interface{}, error)) *Initializer { 54 | return i.initWithHandler(fn, noop) 55 | } 56 | 57 | // GetError returns the first error of initializers. 58 | func (i *Initializer) GetError() error { 59 | return i.e 60 | } 61 | -------------------------------------------------------------------------------- /initializer/initializer_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package initializer_test 6 | 7 | import ( 8 | "errors" 9 | "testing" 10 | 11 | . "github.com/smartystreets/goconvey/convey" 12 | . "github.com/linuxdeepin/go-lib/initializer" 13 | ) 14 | 15 | func TestInitializer(t *testing.T) { 16 | Convey("test initializer with success", t, func(c C) { 17 | err := NewInitializer().Init(func(interface{}) (interface{}, error) { 18 | return 1, nil 19 | }).Init(func(v interface{}) (interface{}, error) { 20 | c.So(v, ShouldEqual, 1) 21 | return nil, nil 22 | }).GetError() 23 | 24 | c.So(err, ShouldBeNil) 25 | }) 26 | } 27 | 28 | func TestInitializerError(t *testing.T) { 29 | Convey("test initializer with error", t, func(c C) { 30 | var err error 31 | c.So(func() { 32 | err = NewInitializer().Init(func(interface{}) (interface{}, error) { 33 | return 1, nil 34 | }).Init(func(v interface{}) (interface{}, error) { 35 | c.So(v, ShouldEqual, 1) 36 | return nil, nil 37 | }).Init(func(interface{}) (interface{}, error) { 38 | return nil, errors.New("initialize error") 39 | }).Init(func(interface{}) (interface{}, error) { 40 | panic("should not be executed") 41 | }).GetError() 42 | 43 | }, ShouldNotPanic) 44 | 45 | c.So(err, ShouldNotBeNil) 46 | }) 47 | } 48 | -------------------------------------------------------------------------------- /initializer/v2/initializer.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package initializer 6 | 7 | // Initializer is a chainable initializer. Init/InitOnSystemBus/InitOnSystemBus will accept a initializer, 8 | // and then pass the successful return value to the next initializer. If error occurs, the rest initializers 9 | // won't be executed any more. GetError is used to access the error. 10 | type Initializer struct { 11 | e error 12 | } 13 | 14 | func (i *Initializer) init(fn func() error) *Initializer { 15 | if i.e != nil { 16 | return i 17 | } 18 | 19 | if err := fn(); err != nil { 20 | i.e = err 21 | } 22 | 23 | return i 24 | } 25 | 26 | // Do accepts a initializer function, stop other Do if any error occurs. 27 | func (i *Initializer) Do(fn func() error) *Initializer { 28 | return i.init(func() error { 29 | err := fn() 30 | if err != nil { 31 | return err 32 | } 33 | return nil 34 | }) 35 | } 36 | 37 | // GetError returns the first error of initializers. 38 | func (i *Initializer) GetError() error { 39 | if i.e != nil { 40 | return i.e 41 | } 42 | return nil 43 | } 44 | 45 | // Do starts the initialization. 46 | func Do(fn func() error) *Initializer { 47 | i := new(Initializer) 48 | return i.Do(fn) 49 | } 50 | -------------------------------------------------------------------------------- /initializer/v2/initializer_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package initializer_test 6 | 7 | import ( 8 | "errors" 9 | "testing" 10 | 11 | . "github.com/smartystreets/goconvey/convey" 12 | "github.com/linuxdeepin/go-lib/initializer/v2" 13 | ) 14 | 15 | func e1() error { 16 | return nil 17 | } 18 | 19 | func e2() error { 20 | var err error 21 | return err 22 | } 23 | 24 | func TestInitializer(t *testing.T) { 25 | Convey("test initializer with success", t, func(c C) { 26 | err := initializer.Do(func() error { 27 | return nil 28 | }).Do(func() error { 29 | return e1() 30 | }).Do(func() error { 31 | return e2() 32 | }).GetError() 33 | 34 | c.So(err, ShouldBeNil) 35 | }) 36 | } 37 | 38 | func TestInitializerError(t *testing.T) { 39 | Convey("test initializer with error", t, func(c C) { 40 | var err error 41 | c.So(func() { 42 | err = initializer.Do(func() error { 43 | return e1() 44 | }).Do(func() error { 45 | return e2() 46 | }).Do(func() error { 47 | return errors.New("initialize error") 48 | }).Do(func() error { 49 | panic("should not be executed") 50 | }).GetError() 51 | 52 | }, ShouldNotPanic) 53 | 54 | c.So(err, ShouldNotBeNil) 55 | c.So(err.Error(), ShouldEqual, "initialize error") 56 | }) 57 | } 58 | -------------------------------------------------------------------------------- /iso/README.md: -------------------------------------------------------------------------------- 1 | ISO 标准配置解析库, 相关文件位于 /usr/share/xml/iso-codes/, 目前实现了 2 | 对 iso_3166.xml 的解析从而可以获取国家和地区的相关信息. 3 | -------------------------------------------------------------------------------- /iso/iso_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package iso 6 | 7 | import ( 8 | C "gopkg.in/check.v1" 9 | "testing" 10 | ) 11 | 12 | type testWrapper struct{} 13 | 14 | func Test(t *testing.T) { C.TestingT(t) } 15 | 16 | func init() { 17 | C.Suite(&testWrapper{}) 18 | } 19 | -------------------------------------------------------------------------------- /locale/testdata/locale.alias: -------------------------------------------------------------------------------- 1 | # Locale name alias data base. 2 | 3 | bokmal nb_NO.ISO-8859-1 4 | catalan ca_ES.ISO-8859-1 5 | croatian hr_HR.ISO-8859-2 6 | -------------------------------------------------------------------------------- /log/backend_console.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package log 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "github.com/linuxdeepin/go-lib/utils" 11 | "time" 12 | ) 13 | 14 | const defaultDebugConsoleEnv = "DDE_DEBUG_CONSOLE" 15 | 16 | var ( 17 | // DebugConsoleEnv is the name of environment variable that used to control 18 | // the console backend print log in syslog format. 19 | DebugConsoleEnv = defaultDebugConsoleEnv 20 | ) 21 | 22 | type backendConsole struct { 23 | name string 24 | syslogMode bool 25 | } 26 | 27 | func newBackendConsole(name string) (b *backendConsole) { 28 | b = &backendConsole{} 29 | b.name = name 30 | if utils.IsEnvExists(DebugConsoleEnv) { 31 | b.syslogMode = true 32 | } 33 | return 34 | } 35 | 36 | func (b *backendConsole) log(level Priority, msg string) (err error) { 37 | formatMsg, err := b.formatMsg(level, msg) 38 | if err != nil { 39 | return 40 | } 41 | if b.syslogMode { 42 | fmt.Println(getSyslogPrefix(b.name), formatMsg) 43 | } else { 44 | fmt.Println(formatMsg) 45 | } 46 | return 47 | } 48 | func getSyslogPrefix(name string) (prefix string) { 49 | hostname, _ := os.Hostname() 50 | prefix = fmt.Sprintf("%s %s %s[%d]:", time.Now().Format("Jan 2 15:04:05"), hostname, name, os.Getpid()) 51 | return 52 | } 53 | 54 | func (b *backendConsole) formatMsg(level Priority, msg string) (fmtMsg string, err error) { 55 | var levelStr string 56 | switch level { 57 | case LevelDebug: 58 | levelStr = "" 59 | case LevelInfo: 60 | levelStr = "" 61 | case LevelWarning: 62 | levelStr = "" 63 | case LevelError: 64 | levelStr = "" 65 | case LevelPanic: 66 | levelStr = "" 67 | case LevelFatal: 68 | levelStr = "" 69 | default: 70 | err = errUnknownLogLevel 71 | return 72 | } 73 | fmtMsg = levelStr + " " + msg 74 | return 75 | } 76 | 77 | func (b *backendConsole) close() (err error) { 78 | return 79 | } 80 | -------------------------------------------------------------------------------- /log/backend_syslog.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package log 6 | 7 | import ( 8 | "log/syslog" 9 | ) 10 | 11 | const defaultSyslogTagPrefix = "" 12 | 13 | var ( 14 | // SyslogTagPrefix define the prefix of syslog tag, default is 15 | // empty. 16 | SyslogTagPrefix = defaultSyslogTagPrefix 17 | ) 18 | 19 | type backendSyslog struct { 20 | name string 21 | writer *syslog.Writer 22 | } 23 | 24 | func newBackendSyslog(name string) (b *backendSyslog) { 25 | b = &backendSyslog{} 26 | b.name = name 27 | var err error 28 | b.writer, err = newSyslogWriter(name) 29 | if err != nil { 30 | std.Println(" syslog is not available:", err) 31 | return nil 32 | } 33 | return 34 | } 35 | func newSyslogWriter(name string) (l *syslog.Writer, err error) { 36 | tag := SyslogTagPrefix + name 37 | l, err = syslog.New(syslog.LOG_DAEMON, tag) 38 | return 39 | } 40 | 41 | func (b *backendSyslog) log(level Priority, msg string) (err error) { 42 | switch level { 43 | case LevelDebug: 44 | err = b.writer.Debug(msg) 45 | case LevelInfo: 46 | err = b.writer.Info(msg) 47 | case LevelWarning: 48 | err = b.writer.Warning(msg) 49 | case LevelError: 50 | err = b.writer.Err(msg) 51 | case LevelPanic: 52 | err = b.writer.Emerg(msg) 53 | case LevelFatal: 54 | err = b.writer.Emerg(msg) 55 | default: 56 | err = errUnknownLogLevel 57 | } 58 | return 59 | } 60 | 61 | func (b *backendSyslog) close() (err error) { 62 | err = b.writer.Close() 63 | return 64 | } 65 | -------------------------------------------------------------------------------- /log/restart_config.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package log 6 | 7 | import ( 8 | "os" 9 | "path/filepath" 10 | "strings" 11 | ) 12 | 13 | // TODO 14 | var crashReporterArgs = []string{crashReporterExe, "--remove-config", "--config"} 15 | 16 | // restartConfig stores data to be used by deepin-crash-reporter 17 | type restartConfig struct { 18 | AppName string 19 | RestartCommand []string 20 | RestartEnv map[string]string 21 | RestartDirectory string 22 | LogDetail string 23 | } 24 | 25 | func newRestartConfig(logname string) *restartConfig { 26 | config := &restartConfig{} 27 | config.AppName = logname 28 | config.RestartCommand = os.Args 29 | config.RestartCommand[0], _ = filepath.Abs(os.Args[0]) 30 | config.RestartDirectory, _ = os.Getwd() 31 | 32 | // setup envrionment variables 33 | config.RestartEnv = make(map[string]string) 34 | environs := os.Environ() 35 | for _, env := range environs { 36 | values := strings.SplitN(env, "=", 2) 37 | // values[0] is environment variable name, values[1] is the value 38 | if len(values) == 2 { 39 | config.RestartEnv[values[0]] = values[1] 40 | } 41 | } 42 | return config 43 | } 44 | -------------------------------------------------------------------------------- /log/testdata/dde_debug: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/log/testdata/dde_debug -------------------------------------------------------------------------------- /log/testdata/stdout: -------------------------------------------------------------------------------- 1 | Jun 28 17:05:02 uos-PC test-console[27804]: this line shows as syslog format in console 2 | -------------------------------------------------------------------------------- /log/utils.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package log 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | ) 11 | 12 | // same with fmt.Sprintln() but trim the additional end line 13 | func fmtSprint(v ...interface{}) (s string) { 14 | s = fmt.Sprintln(v...) 15 | s = strings.TrimSuffix(s, "\n") 16 | return 17 | } 18 | 19 | func isStringInArray(s string, arr []string) bool { 20 | for _, t := range arr { 21 | if t == s { 22 | return true 23 | } 24 | } 25 | return false 26 | } 27 | -------------------------------------------------------------------------------- /mime/mime_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package mime 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestQueryURI(t *testing.T) { 15 | var infos = []struct { 16 | uri string 17 | mime string 18 | }{ 19 | { 20 | uri: "testdata/data.txt", 21 | mime: "text/plain", 22 | }, 23 | { 24 | uri: "testdata/Deepin/index.theme", 25 | mime: MimeTypeGtk, 26 | }, 27 | } 28 | 29 | for _, info := range infos { 30 | m, err := Query(info.uri) 31 | require.NoError(t, err) 32 | assert.Equal(t, m, info.mime) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /mime/testdata/Deepin/cursors/left_ptr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/mime/testdata/Deepin/cursors/left_ptr -------------------------------------------------------------------------------- /mime/testdata/Deepin/gtk-3.0/settings.ini: -------------------------------------------------------------------------------- 1 | [Settings] 2 | gtk-auto-mnemonics = 1 3 | gtk-visible-focus = automatic 4 | -------------------------------------------------------------------------------- /mime/testdata/Deepin/index.theme: -------------------------------------------------------------------------------- 1 | [Icon Theme] 2 | Name=Deepin 3 | Directories=apps/24,apps/32,apps/48 4 | -------------------------------------------------------------------------------- /mime/testdata/data.txt: -------------------------------------------------------------------------------- 1 | 123456 2 | -------------------------------------------------------------------------------- /mime/theme_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package mime 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestIsGtkTheme(t *testing.T) { 15 | ok, err := isGtkTheme("testdata/Deepin/index.theme") 16 | require.NoError(t, err) 17 | assert.Equal(t, ok, true) 18 | } 19 | 20 | func TestIsIconTheme(t *testing.T) { 21 | ok, err := isIconTheme("testdata/Deepin/index.theme") 22 | require.NoError(t, err) 23 | assert.Equal(t, ok, true) 24 | } 25 | 26 | func TestIsCursorTheme(t *testing.T) { 27 | ok, err := isCursorTheme("testdata/Deepin/index.theme") 28 | require.NoError(t, err) 29 | assert.Equal(t, ok, true) 30 | } 31 | -------------------------------------------------------------------------------- /misc.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package lib 6 | 7 | import "github.com/godbus/dbus/v5" 8 | 9 | const ( 10 | SystemBus = 1 11 | SessionBus = 2 12 | ) 13 | 14 | func UniqueOnSession(name string) bool { 15 | con, err := dbus.SessionBus() 16 | if err != nil { 17 | return false 18 | } 19 | return uniqueOnAny(con, name) 20 | } 21 | func UniqueOnSystem(name string) bool { 22 | con, err := dbus.SystemBus() 23 | if err != nil { 24 | return false 25 | } 26 | return uniqueOnAny(con, name) 27 | } 28 | 29 | func uniqueOnAny(bus *dbus.Conn, name string) bool { 30 | reply, err := bus.RequestName(name, dbus.NameFlagDoNotQueue) 31 | if err != nil || reply != dbus.RequestNameReplyPrimaryOwner { 32 | return false 33 | } 34 | return true 35 | } 36 | -------------------------------------------------------------------------------- /mobileprovider/README.md: -------------------------------------------------------------------------------- 1 | mobile-broadband-provider-info XML 配置解析库, 默认配置文件是 2 | /usr/share/mobile-broadband-provider-info/serviceproviders.xml, 可以提 3 | 供各国家和地区的移动运营商信息(GSM/CDMA). 4 | -------------------------------------------------------------------------------- /multierr/append.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package multierr 6 | 7 | // Append is a helper function that will append more errors 8 | // onto an Error in order to create a larger multi-error. 9 | // 10 | // If err is not a multierror.Error, then it will be turned into 11 | // one. If any of the errs are multierr.Error, they will be flattened 12 | // one level into err. 13 | func Append(err error, errs ...error) *Error { 14 | switch err := err.(type) { 15 | case *Error: 16 | // Typed nils can reach here, so initialize if we are nil 17 | if err == nil { 18 | err = new(Error) 19 | } 20 | 21 | // Go through each error and flatten 22 | for _, e := range errs { 23 | switch e := e.(type) { 24 | case *Error: 25 | if e != nil { 26 | err.Errors = append(err.Errors, e.Errors...) 27 | } 28 | default: 29 | if e != nil { 30 | err.Errors = append(err.Errors, e) 31 | } 32 | } 33 | } 34 | 35 | return err 36 | default: 37 | newErrs := make([]error, 0, len(errs)+1) 38 | if err != nil { 39 | newErrs = append(newErrs, err) 40 | } 41 | newErrs = append(newErrs, errs...) 42 | 43 | return Append(&Error{}, newErrs...) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /multierr/format.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package multierr 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | ) 11 | 12 | // ErrorFormatFunc is a function callback that is called by Error to 13 | // turn the list of errors into a string. 14 | type ErrorFormatFunc func([]error) string 15 | 16 | // ListFormatFunc is a basic formatter that outputs the number of errors 17 | // that occurred along with a bullet point list of the errors. 18 | func ListFormatFunc(es []error) string { 19 | if len(es) == 1 { 20 | return fmt.Sprintf("1 error occurred:\n\t* %s", es[0]) 21 | } 22 | 23 | points := make([]string, len(es)) 24 | for i, err := range es { 25 | points[i] = fmt.Sprintf("* %s", err) 26 | } 27 | 28 | return fmt.Sprintf( 29 | "%d errors occurred:\n\t%s", 30 | len(es), strings.Join(points, "\n\t")) 31 | } 32 | -------------------------------------------------------------------------------- /multierr/format_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package multierr 6 | 7 | import ( 8 | "errors" 9 | "testing" 10 | ) 11 | 12 | func TestListFormatFuncSingle(t *testing.T) { 13 | expected := `1 error occurred: 14 | * foo` 15 | 16 | errs := []error{ 17 | errors.New("foo"), 18 | } 19 | 20 | actual := ListFormatFunc(errs) 21 | if actual != expected { 22 | t.Fatalf("bad: %#v", actual) 23 | } 24 | } 25 | 26 | func TestListFormatFuncMultiple(t *testing.T) { 27 | expected := `2 errors occurred: 28 | * foo 29 | * bar` 30 | 31 | errs := []error{ 32 | errors.New("foo"), 33 | errors.New("bar"), 34 | } 35 | 36 | actual := ListFormatFunc(errs) 37 | if actual != expected { 38 | t.Fatalf("bad: %#v", actual) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /multierr/multierr.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package multierr 6 | 7 | import ( 8 | "fmt" 9 | ) 10 | 11 | // code copy from github.com/hashicorp/go-multierror 12 | 13 | // Error is an error type to track multiple errors. This is used to 14 | // accumulate errors in cases and return them as a single "error". 15 | type Error struct { 16 | Errors []error 17 | ErrorFormat ErrorFormatFunc 18 | } 19 | 20 | func (e *Error) Error() string { 21 | fn := e.ErrorFormat 22 | if fn == nil { 23 | fn = ListFormatFunc 24 | } 25 | 26 | return fn(e.Errors) 27 | } 28 | 29 | // ErrorOrNil returns an error interface if this Error represents 30 | // a list of errors, or returns nil if the list of errors is empty. This 31 | // function is useful at the end of accumulation to make sure that the value 32 | // returned represents the existence of errors. 33 | func (e *Error) ErrorOrNil() error { 34 | if e == nil { 35 | return nil 36 | } 37 | if len(e.Errors) == 0 { 38 | return nil 39 | } 40 | 41 | return e 42 | } 43 | 44 | func (e *Error) GoString() string { 45 | return fmt.Sprintf("*%#v", *e) 46 | } 47 | 48 | // WrappedErrors returns the list of errors that this Error is wrapping. 49 | // It is an implementation of the errwrap.Wrapper interface so that 50 | // multierror.Error can be used with that library. 51 | // 52 | // This method is not safe to be called concurrently and is no different 53 | // than accessing the Errors field directly. It is implemented only to 54 | // satisfy the errwrap.Wrapper interface. 55 | func (e *Error) WrappedErrors() []error { 56 | return e.Errors 57 | } 58 | 59 | func New() *Error { 60 | return &Error{} 61 | } 62 | 63 | func (e *Error) Append(errs ...error) { 64 | // Go through each error and flatten 65 | for _, item := range errs { 66 | switch item := item.(type) { 67 | case *Error: 68 | if item != nil { 69 | e.Errors = append(e.Errors, item.Errors...) 70 | } 71 | default: 72 | if item != nil { 73 | e.Errors = append(e.Errors, item) 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /multierr/multierr_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package multierr 6 | 7 | import ( 8 | "errors" 9 | "reflect" 10 | "testing" 11 | ) 12 | 13 | func TestError_Impl(t *testing.T) { 14 | var _ error = new(Error) 15 | } 16 | 17 | func TestErrorError_custom(t *testing.T) { 18 | errors := []error{ 19 | errors.New("foo"), 20 | errors.New("bar"), 21 | } 22 | 23 | fn := func(es []error) string { 24 | return "foo" 25 | } 26 | 27 | multi := &Error{Errors: errors, ErrorFormat: fn} 28 | if multi.Error() != "foo" { 29 | t.Fatalf("bad: %s", multi.Error()) 30 | } 31 | } 32 | 33 | func TestErrorError_default(t *testing.T) { 34 | expected := `2 errors occurred: 35 | * foo 36 | * bar` 37 | 38 | errors := []error{ 39 | errors.New("foo"), 40 | errors.New("bar"), 41 | } 42 | 43 | multi := &Error{Errors: errors} 44 | if multi.Error() != expected { 45 | t.Fatalf("bad: %s", multi.Error()) 46 | } 47 | } 48 | 49 | func TestErrorErrorOrNil(t *testing.T) { 50 | err := new(Error) 51 | if err.ErrorOrNil() != nil { 52 | t.Fatalf("bad: %#v", err.ErrorOrNil()) 53 | } 54 | 55 | err.Errors = []error{errors.New("foo")} 56 | if v := err.ErrorOrNil(); v == nil { 57 | t.Fatal("should not be nil") 58 | } else if !reflect.DeepEqual(v, err) { 59 | t.Fatalf("bad: %#v", v) 60 | } 61 | } 62 | 63 | func TestErrorWrappedErrors(t *testing.T) { 64 | errors := []error{ 65 | errors.New("foo"), 66 | errors.New("bar"), 67 | } 68 | 69 | multi := &Error{Errors: errors} 70 | if !reflect.DeepEqual(multi.Errors, multi.WrappedErrors()) { 71 | t.Fatalf("bad: %s", multi.WrappedErrors()) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /notify/dbusnotify/init.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package dbusnotify 6 | 7 | import ( 8 | "fmt" 9 | "sync" 10 | 11 | "github.com/godbus/dbus/v5" 12 | ) 13 | 14 | var __conn *dbus.Conn = nil 15 | var __connLock sync.Mutex 16 | 17 | var __ruleCounter map[string]int = nil 18 | var __ruleCounterLock sync.Mutex 19 | 20 | func getBus() *dbus.Conn { 21 | __connLock.Lock() 22 | defer __connLock.Unlock() 23 | if __conn == nil { 24 | var err error 25 | __conn, err = dbus.SessionBus() 26 | if err != nil { 27 | panic(err) 28 | } 29 | } 30 | return __conn 31 | } 32 | 33 | func getRuleCounter() map[string]int { 34 | __ruleCounterLock.Lock() 35 | defer __ruleCounterLock.Unlock() 36 | if __ruleCounter == nil { 37 | __ruleCounter = make(map[string]int) 38 | } 39 | return __ruleCounter 40 | } 41 | 42 | func dbusCall(method string, flags dbus.Flags, args ...interface{}) (err error) { 43 | err = getBus().BusObject().Call(method, flags, args...).Err 44 | if err != nil { 45 | fmt.Println(err) 46 | } 47 | return 48 | } 49 | 50 | func dbusAddMatch(rule string) (err error) { 51 | ruleCounter := getRuleCounter() 52 | 53 | __ruleCounterLock.Lock() 54 | defer __ruleCounterLock.Unlock() 55 | if _, ok := ruleCounter[rule]; !ok { 56 | err = dbusCall("org.freedesktop.DBus.AddMatch", 0, rule) 57 | } 58 | ruleCounter[rule]++ 59 | return 60 | } 61 | 62 | func dbusRemoveMatch(rule string) (err error) { 63 | ruleCounter := getRuleCounter() 64 | 65 | __ruleCounterLock.Lock() 66 | defer __ruleCounterLock.Unlock() 67 | if _, ok := ruleCounter[rule]; !ok { 68 | return 69 | } 70 | ruleCounter[rule]-- 71 | if ruleCounter[rule] == 0 { 72 | delete(ruleCounter, rule) 73 | err = dbusCall("org.freedesktop.DBus.RemoveMatch", 0, rule) 74 | } 75 | return 76 | } 77 | -------------------------------------------------------------------------------- /notify/examples/action.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 4 | // 5 | // SPDX-License-Identifier: GPL-3.0-or-later 6 | 7 | package main 8 | 9 | import ( 10 | "log" 11 | "time" 12 | 13 | "github.com/linuxdeepin/go-lib/notify" 14 | ) 15 | 16 | func init() { 17 | notify.Init("notify-example-action") 18 | } 19 | 20 | func show() { 21 | n := notify.NewNotification("summary", "body", "icon") 22 | n.Timeout = notify.ExpiresSecond * 5 23 | n.AddAction("x", "XXX", func(_n *notify.Notification, action string) { 24 | log.Println("action", action, "invoked") 25 | _n.Summary = n.Summary + "!" 26 | _n.Show() 27 | }) 28 | 29 | n.AddAction("close", "Close", func(_n *notify.Notification, action string) { 30 | log.Println("close it") 31 | }) 32 | 33 | n.Closed().On(func(_n *notify.Notification, reason notify.ClosedReason) { 34 | log.Printf("reason: %d %s\n", reason, reason) 35 | }) 36 | n.Show() 37 | } 38 | 39 | func main() { 40 | go show() 41 | time.Sleep(time.Second * 100) 42 | } 43 | -------------------------------------------------------------------------------- /notify/examples/desktop-icon.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/notify/examples/desktop-icon.jpeg -------------------------------------------------------------------------------- /notify/examples/image.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 4 | // 5 | // SPDX-License-Identifier: GPL-3.0-or-later 6 | 7 | package main 8 | 9 | import ( 10 | "image" 11 | _ "image/jpeg" 12 | _ "image/png" 13 | "log" 14 | "os" 15 | 16 | "github.com/linuxdeepin/go-lib/notify" 17 | ) 18 | 19 | func init() { 20 | notify.Init("notify-example-image") 21 | } 22 | 23 | func loadImage(filename string) (image.Image, error) { 24 | infile, err := os.Open(filename) 25 | if err != nil { 26 | return nil, err 27 | } 28 | defer infile.Close() 29 | 30 | img, _, err := image.Decode(infile) 31 | if err != nil { 32 | return nil, err 33 | } 34 | return img, nil 35 | } 36 | 37 | func show(filename string) { 38 | n := notify.NewNotification("image test", "file "+filename, "") 39 | img, err := loadImage(filename) 40 | if err != nil { 41 | log.Fatal(err) 42 | } 43 | n.SetImage(img) 44 | n.Show() 45 | n.Destroy() 46 | } 47 | 48 | func main() { 49 | // opaque 50 | show("./desktop-icon.jpeg") 51 | // not opaque 52 | show("./libreoffice-base.png") 53 | 54 | notify.Destroy() 55 | } 56 | -------------------------------------------------------------------------------- /notify/examples/libreoffice-base.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linuxdeepin/go-lib/de7ec8f89a8aa84bc7e25a79f9aaf943431adc5b/notify/examples/libreoffice-base.png -------------------------------------------------------------------------------- /notify/examples/simple.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 4 | // 5 | // SPDX-License-Identifier: GPL-3.0-or-later 6 | 7 | package main 8 | 9 | import ( 10 | "github.com/linuxdeepin/go-lib/notify" 11 | ) 12 | 13 | func init() { 14 | notify.Init("notify-example-simple") 15 | } 16 | 17 | func main() { 18 | n := notify.NewNotification("x", "y", "player") 19 | n.Show() 20 | n.Destroy() 21 | notify.Destroy() 22 | } 23 | -------------------------------------------------------------------------------- /notify/examples/update.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 4 | // 5 | // SPDX-License-Identifier: GPL-3.0-or-later 6 | 7 | package main 8 | 9 | import ( 10 | "log" 11 | "time" 12 | 13 | "github.com/linuxdeepin/go-lib/notify" 14 | ) 15 | 16 | func init() { 17 | notify.Init("notify-example-update") 18 | } 19 | 20 | func main() { 21 | serverInfo, err := notify.GetServerInfo() 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | log.Printf("serverInfo: %#v\n", serverInfo) 26 | caps, err := notify.GetServerCaps() 27 | if err != nil { 28 | log.Println(err) 29 | } 30 | log.Println("server caps:", caps) 31 | 32 | n := notify.NewNotification("s1", "b1", "deepin-music") 33 | n.Show() 34 | 35 | time.Sleep(time.Second * 2) 36 | n.Update("s2", "b2", "deepin-terminal") 37 | n.Show() 38 | 39 | time.Sleep(time.Second * 2) 40 | n.Update("s3", "b3", "deepin-terminal") 41 | n.Show() 42 | } 43 | -------------------------------------------------------------------------------- /notify/image.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package notify 6 | 7 | import ( 8 | "image" 9 | "image/draw" 10 | ) 11 | 12 | // This is a raw data image format which describes the width, height, rowstride, 13 | // has alpha, bits per sample, channels and image data respectively. 14 | type Image struct { 15 | Width int32 16 | Height int32 17 | RowStride int32 18 | HasAlpha bool 19 | BitsPerSample int32 20 | Channels int32 21 | Pix []byte 22 | } 23 | 24 | func (n *Notification) SetImage(img image.Image) { 25 | n.SetHint(HintImageData, NewImage(img)) 26 | } 27 | 28 | func toRGBA(src image.Image) *image.RGBA { 29 | b := src.Bounds() 30 | m := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy())) 31 | draw.Draw(m, m.Bounds(), src, b.Min, draw.Src) 32 | return m 33 | } 34 | 35 | func NewImage(src image.Image) *Image { 36 | return newImageFromRGBA(toRGBA(src)) 37 | } 38 | 39 | func newImageFromRGBA(img *image.RGBA) *Image { 40 | opaque := img.Opaque() 41 | b := img.Bounds() 42 | w := b.Dx() 43 | h := b.Dy() 44 | 45 | nchan := 4 46 | if opaque { 47 | nchan = 3 48 | } 49 | stride := w * nchan 50 | pix := make([]byte, stride*h) 51 | 52 | // fill data to pix 53 | // img.Pix idx 54 | i := 0 55 | // pix idx 56 | p := 0 57 | 58 | if opaque { 59 | for y := 0; y < h; y++ { 60 | // copy one row 61 | for x := 0; x < w; x++ { 62 | pix[p] = img.Pix[i] // R 63 | pix[p+1] = img.Pix[i+1] // G 64 | pix[p+2] = img.Pix[i+2] // B 65 | // skip A 66 | 67 | p += nchan 68 | i += (nchan + 1) 69 | } 70 | } 71 | } else { 72 | for y := 0; y < h; y++ { 73 | // copy one row 74 | copy(pix[p:], img.Pix[i:i+stride]) 75 | p += stride 76 | i += img.Stride 77 | } 78 | } 79 | 80 | return &Image{ 81 | Width: int32(w), 82 | Height: int32(h), 83 | RowStride: int32(stride), 84 | HasAlpha: !opaque, 85 | BitsPerSample: 8, 86 | Channels: int32(nchan), 87 | Pix: pix, 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /notify/notification_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package notify 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func Test_notification(t *testing.T) { 12 | // Init("test") 13 | // assert.True(t, IsInitted()) 14 | // SetAppName("testNotify") 15 | // assert.Equal(t, GetAppName(), "testNotify") 16 | 17 | // notify := NewNotification("", "test", "notification-bluetooth-connected") 18 | // assert.Equal(t, notify.getAppName(), "testNotify") 19 | 20 | // notify.Update("", "testNotify", "notification-bluetooth-connected") 21 | // notify.Destroy() 22 | // Destroy() 23 | } 24 | -------------------------------------------------------------------------------- /notify/notify.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package notify 6 | 7 | import ( 8 | "github.com/linuxdeepin/go-lib/notify/dbusnotify" 9 | ) 10 | 11 | var ( 12 | defaultAppName string 13 | notifier *dbusnotify.Notifier 14 | isInitted bool 15 | ) 16 | 17 | // This must be called before anny other functions. 18 | func Init(appName string) bool { 19 | if appName == "" { 20 | return false 21 | } 22 | 23 | if isInitted { 24 | return true 25 | } 26 | 27 | defaultAppName = appName 28 | 29 | var err error 30 | notifier, err = dbusnotify.NewNotifier(dbusDest, dbusPath) 31 | if err != nil { 32 | panic(err) 33 | } 34 | isInitted = true 35 | return true 36 | } 37 | 38 | // Gets whether or not libnotify is initialized. 39 | func IsInitted() bool { 40 | return isInitted 41 | } 42 | 43 | // This should be called when the program no longer needs libnotify for 44 | // the rest of its lifecycle, typically just before exitting. 45 | func Destroy() { 46 | dbusnotify.DestroyNotifier(notifier) 47 | notifier = nil 48 | isInitted = false 49 | } 50 | 51 | func GetAppName() string { 52 | return defaultAppName 53 | } 54 | 55 | func SetAppName(name string) { 56 | defaultAppName = name 57 | } 58 | 59 | func GetServerCaps() ([]string, error) { 60 | return notifier.GetCapabilities() 61 | } 62 | 63 | type ServerInfo struct { 64 | Name, Vendor, Version, SpecVersion string 65 | } 66 | 67 | //name string, vendor string, version string, spec_version string 68 | func GetServerInfo() (*ServerInfo, error) { 69 | name, vendor, version, specVersion, err := notifier.GetServerInformation() 70 | if err != nil { 71 | return nil, err 72 | } 73 | return &ServerInfo{ 74 | Name: name, 75 | Vendor: vendor, 76 | Version: version, 77 | SpecVersion: specVersion, 78 | }, nil 79 | } 80 | -------------------------------------------------------------------------------- /pam/handler.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pam 6 | 7 | import "sync" 8 | 9 | // ConversationHandler is an interface for objects that can be used as 10 | // conversation callbacks during PAM authentication. 11 | type ConversationHandler interface { 12 | // RespondPAM receives a message style and a message string. If the 13 | // message Style is PromptEchoOff or PromptEchoOn then the function 14 | // should return a response string. 15 | RespondPAM(Style, string) (string, error) 16 | } 17 | 18 | // ConversationFunc is an adapter to allow the use of ordinary functions as 19 | // conversation callbacks. 20 | type ConversationFunc func(Style, string) (string, error) 21 | 22 | func (f ConversationFunc) RespondPAM(s Style, msg string) (string, error) { 23 | return f(s, msg) 24 | } 25 | 26 | var globalHandlers struct { 27 | sync.Mutex 28 | m map[handlerId]ConversationHandler 29 | nextId handlerId 30 | } 31 | 32 | type handlerId int 33 | 34 | func init() { 35 | globalHandlers.m = make(map[handlerId]ConversationHandler) 36 | globalHandlers.nextId = 1 37 | } 38 | 39 | func addHandler(handler ConversationHandler) handlerId { 40 | globalHandlers.Lock() 41 | defer globalHandlers.Unlock() 42 | id := globalHandlers.nextId 43 | globalHandlers.nextId++ 44 | globalHandlers.m[id] = handler 45 | return id 46 | } 47 | 48 | func getHandler(id handlerId) ConversationHandler { 49 | globalHandlers.Lock() 50 | defer globalHandlers.Unlock() 51 | v := globalHandlers.m[id] 52 | if v != nil { 53 | return v 54 | } 55 | panic("handler not found") 56 | } 57 | 58 | func deleteHandler(id handlerId) { 59 | globalHandlers.Lock() 60 | defer globalHandlers.Unlock() 61 | if _, ok := globalHandlers.m[id]; !ok { 62 | panic("handler not found") 63 | } 64 | delete(globalHandlers.m, id) 65 | } 66 | -------------------------------------------------------------------------------- /pam/transaction.c: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | #include "_cgo_export.h" 6 | #include 7 | #include 8 | 9 | int cb_pam_conv(int num_msg, 10 | const struct pam_message **msg, 11 | struct pam_response **resp, void *appdata_ptr) 12 | { 13 | *resp = calloc(num_msg, sizeof **resp); 14 | if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG) { 15 | return PAM_CONV_ERR; 16 | } 17 | if (!*resp) { 18 | return PAM_BUF_ERR; 19 | } 20 | char *resp_str = NULL; 21 | for (size_t i = 0; i < num_msg; ++i) { 22 | int result = cbPAMConv(msg[i]->msg_style, 23 | (char *)msg[i]->msg, 24 | (long)appdata_ptr, 25 | &resp_str); 26 | if (result != PAM_SUCCESS) { 27 | goto error; 28 | } 29 | (*resp)[i].resp = resp_str; 30 | (*resp)[i].resp_retcode = 0; 31 | } 32 | return PAM_SUCCESS; 33 | error: 34 | for (size_t i = 0; i < num_msg; ++i) { 35 | if ((*resp)[i].resp) { 36 | memset((*resp)[i].resp, 0, strlen((*resp)[i].resp)); 37 | free((*resp)[i].resp); 38 | } 39 | } 40 | memset(*resp, 0, num_msg * sizeof *resp); 41 | free(*resp); 42 | *resp = NULL; 43 | return PAM_CONV_ERR; 44 | } 45 | 46 | void init_pam_conv(struct pam_conv *conv, long c) 47 | { 48 | conv->conv = cb_pam_conv; 49 | conv->appdata_ptr = (void *)c; 50 | } 51 | -------------------------------------------------------------------------------- /pinyin/pinyin.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pinyin 6 | 7 | import ( 8 | "strconv" 9 | "strings" 10 | "unicode" 11 | ) 12 | 13 | func HansToPinyin(hans string) []string { 14 | return getPinyinFromKey(hans) 15 | } 16 | 17 | func getPinyinFromKey(key string) []string { 18 | rets := []string{} 19 | for _, c := range key { 20 | if unicode.Is(unicode.Scripts["Han"], c) { 21 | array := getPinyinByHan(int64(c)) 22 | if len(rets) == 0 { 23 | rets = array 24 | continue 25 | } 26 | rets = rangeArray(rets, array) 27 | } else { 28 | array := []string{string(c)} 29 | if len(rets) == 0 { 30 | rets = array 31 | } else { 32 | rets = rangeArray(rets, array) 33 | } 34 | } 35 | } 36 | 37 | return rets 38 | } 39 | 40 | func getPinyinByHan(han int64) []string { 41 | code := strconv.FormatInt(han, 16) 42 | value := PinyinDataMap[strings.ToUpper(code)] 43 | array := strings.Split(value, ";") 44 | return array 45 | } 46 | 47 | func rangeArray(a1, a2 []string) []string { 48 | rets := []string{} 49 | for _, v := range a1 { 50 | for _, r := range a2 { 51 | rets = append(rets, v+r) 52 | } 53 | } 54 | 55 | return rets 56 | } 57 | -------------------------------------------------------------------------------- /pinyin/pinyin_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pinyin 6 | 7 | import ( 8 | "github.com/stretchr/testify/assert" 9 | "testing" 10 | ) 11 | 12 | func Test_HansToPinyin(t *testing.T) { 13 | pinyinMap := make(map[int]string) 14 | array := HansToPinyin("统信软件") 15 | for i, a := range array { 16 | pinyinMap[i] = a 17 | } 18 | assert.Len(t, pinyinMap, 2) 19 | assert.Equal(t, pinyinMap[0], "tongxinruanjian") 20 | assert.Equal(t, pinyinMap[1], "tongshenruanjian") 21 | } 22 | -------------------------------------------------------------------------------- /profile/profile_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package profile 6 | 7 | func ExampleConfig_Start() { 8 | p := &Config{CPUProfile: "test"} 9 | if err := p.Start(); err != nil { 10 | // error handle 11 | return 12 | } 13 | } 14 | 15 | func ExampleConfig_Stop() { 16 | p := &Config{CPUProfile: "cpu.prof", NoShutdownHook: true} 17 | if err := p.Start(); err != nil { 18 | // error handle 19 | return 20 | } 21 | p.Stop() 22 | } 23 | -------------------------------------------------------------------------------- /profile/time.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package profile 6 | 7 | import ( 8 | "time" 9 | ) 10 | 11 | // Timer recoreds time cost. 12 | type Timer struct { 13 | startTime time.Time 14 | moduleStartTime time.Time 15 | endTime time.Time 16 | } 17 | 18 | // NewTimer creates a new timer and start it. 19 | func NewTimer() *Timer { 20 | t := &Timer{} 21 | t.startTime = time.Now() 22 | t.endTime = t.startTime 23 | return t 24 | } 25 | 26 | // Elapsed returns the time duration from the time of start or last elapsed. 27 | func (t *Timer) Elapsed() time.Duration { 28 | endTime := time.Now() 29 | sub := endTime.Sub(t.moduleStartTime) 30 | t.moduleStartTime = endTime 31 | return sub 32 | } 33 | 34 | // TotalCost will stop the timer and return the total cost time. 35 | func (t *Timer) TotalCost() time.Duration { 36 | if t.startTime == t.endTime { 37 | t.endTime = time.Now() 38 | } 39 | return t.endTime.Sub(t.startTime) 40 | } 41 | -------------------------------------------------------------------------------- /proxy/README.md: -------------------------------------------------------------------------------- 1 | 网络代理相关库, 监听并将 gsettings(com.deepin.wrap.gnome.system.proxy) 2 | 的值同步给当前进程的环境变量, 用到的环境变量包括: 3 | 4 | ``` 5 | http_proxy="http://user:pass@127.0.0.1:8080/" 6 | https_proxy="https://127.0.0.1:8080/" 7 | ftp_proxy="ftp://127.0.0.1:8080/" 8 | all_proxy="http://127.0.0.1:8080/" 9 | SOCKS_SERVER=socks5://127.0.0.1:8000/ 10 | no_proxy="localhost,127.0.0.0/8,::1" 11 | ``` 12 | 13 | 因为 Linux 没有统一的接口处理系统代理, Deepin 在兼容 GNOME 系统代理的 14 | 基础上同时会设置环境变量, 以求适配更多的网络应用, 由于环境变量是进程内 15 | 设置的, 所以抽象出这个库用于给 Deepin 相关程序(startdde/launcher/dock) 16 | 动态更新系统代理环境变量, 使用方法很简单: 17 | 18 | ```go 19 | import ( 20 | "github.com/linuxdeepin/go-gir/glib-2.0" 21 | "github.com/linuxdeepin/go-lib/proxy" 22 | ) 23 | 24 | func main() { 25 | SetupProxy() 26 | glib.StartLoop() 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /proxy/dev_test.go: -------------------------------------------------------------------------------- 1 | //+build dev 2 | 3 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 4 | // 5 | // SPDX-License-Identifier: GPL-3.0-or-later 6 | 7 | package proxy 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/linuxdeepin/go-gir/glib-2.0" 13 | "github.com/linuxdeepin/go-lib/log" 14 | ) 15 | 16 | func TestMain(t testing.T) { 17 | logger.SetLogLevel(log.LevelDebug) 18 | SetupProxy() 19 | logger.Info("start loop...") 20 | glib.StartLoop() 21 | } 22 | -------------------------------------------------------------------------------- /pulse/dde-pulse.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | #ifndef DDE_PULSE_H 6 | #define DDE_PULSE_H 7 | 8 | /* 9 | ANY function touch a _pa_context_ must hold the pa_threaded_mainloop lock !!!!!! 10 | And may object created by pa_context, like pa_stream_new also need hold the lock. 11 | */ 12 | 13 | #include 14 | 15 | #define DECLARE(TYPE) \ 16 | void _get_##TYPE##_info(pa_threaded_mainloop*, pa_context*, int64_t, uint32_t); \ 17 | void _get_##TYPE##_info_list(pa_threaded_mainloop*, pa_context*, int64_t); 18 | 19 | DECLARE(sink); 20 | DECLARE(sink_input); 21 | DECLARE(source); 22 | DECLARE(source_output); 23 | DECLARE(client); 24 | DECLARE(card); 25 | DECLARE(module); 26 | DECLARE(sample); 27 | 28 | void _get_server_info(pa_threaded_mainloop*, pa_context *c, int64_t cookie); 29 | 30 | pa_context* new_pa_context(pa_threaded_mainloop* ml); 31 | 32 | // Fixed gccgo(1.4) compile failed, becase of 'success_cb' duplicate definition 33 | pa_context_success_cb_t get_success_cb(); 34 | 35 | void set_connect_timeout(); 36 | 37 | pa_context_index_cb_t get_index_cb(); 38 | 39 | pa_stream* createMonitorStreamForSource(pa_threaded_mainloop* loop, pa_context* ctx, uint32_t source_idx, uint32_t stream_idx, int suspend); 40 | 41 | void _suspend_sink_by_id(pa_threaded_mainloop* loop, pa_context* ctx, uint32_t idx, int suspend); 42 | void _suspend_source_by_id(pa_threaded_mainloop* loop, pa_context* ctx, uint32_t idx, int suspend); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /pulse/info_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pulse 6 | 7 | import ( 8 | "os" 9 | "testing" 10 | 11 | "github.com/linuxdeepin/go-lib/xdg/basedir" 12 | ) 13 | 14 | // Please manually enable test CFLAGS in ./pulse.go 15 | 16 | func TestQueryInfo(t *testing.T) { 17 | homeDir := basedir.GetUserHomeDir() 18 | _, err := os.Stat(homeDir) 19 | if os.IsNotExist(err) { 20 | t.Skip("home dir is not exist") 21 | } 22 | 23 | _ = GetContext() 24 | ctx := GetContextForced() 25 | if ctx == nil { 26 | t.Skip("Can't connect to pulseaudio.") 27 | return 28 | } 29 | _, err = ctx.GetServer() 30 | if err != nil { 31 | t.Fatal("Can't query server info", err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pulse/meter.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pulse 6 | 7 | /* 8 | #include "dde-pulse.h" 9 | */ 10 | import "C" 11 | import "sync" 12 | 13 | var sourceMeterCBs = make(map[uint32]func(float64)) 14 | var sourceMeterLock sync.RWMutex 15 | 16 | type SourceMeter struct { 17 | core *C.pa_stream 18 | sourceIndex uint32 19 | ctx *Context 20 | } 21 | 22 | func NewSourceMeter(c *Context, idx uint32) *SourceMeter { 23 | core := C.createMonitorStreamForSource(c.loop, c.ctx, C.uint32_t(idx), 0, 0) 24 | return &SourceMeter{ 25 | core: core, 26 | sourceIndex: idx, 27 | ctx: c, 28 | } 29 | } 30 | func (s *SourceMeter) Destroy() { 31 | sourceMeterLock.Lock() 32 | delete(sourceMeterCBs, s.sourceIndex) 33 | sourceMeterLock.Unlock() 34 | 35 | s.ctx.safeDo(func() { 36 | C.pa_stream_disconnect(s.core) 37 | C.pa_stream_unref(s.core) 38 | }) 39 | } 40 | 41 | func (s *SourceMeter) ConnectChanged(cb func(v float64)) { 42 | sourceMeterLock.Lock() 43 | sourceMeterCBs[s.sourceIndex] = cb 44 | sourceMeterLock.Unlock() 45 | } 46 | -------------------------------------------------------------------------------- /pulse/pulse_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pulse 6 | 7 | import ( 8 | "errors" 9 | 10 | "testing" 11 | 12 | "github.com/stretchr/testify/assert" 13 | "github.com/stretchr/testify/require" 14 | ) 15 | 16 | func Test_pulse(t *testing.T) { 17 | ctx := GetContextForced() 18 | if ctx == nil { 19 | return 20 | } 21 | defaultSink := getPulseDefaultSink(ctx) 22 | if defaultSink == nil { 23 | err := errors.New("failed to get default sink") 24 | t.Log(err) 25 | return 26 | } 27 | ctx.SetDefaultSink(defaultSink.Name) 28 | 29 | defaultSource := getPulseDefaultSource(ctx) 30 | if defaultSource == nil { 31 | err := errors.New("failed to get default source") 32 | t.Log(err) 33 | return 34 | } 35 | ctx.SetDefaultSource(defaultSource.Name) 36 | 37 | card, err := getCard(ctx, 0) 38 | require.NoError(t, err) 39 | if err != nil { 40 | t.Log(err) 41 | return 42 | } 43 | assert.NotNil(t, card) 44 | } 45 | 46 | func getPulseDefaultSink(ctx *Context) (defaultSink *Sink) { 47 | defaultSinkName := ctx.GetDefaultSink() 48 | for _, sink := range ctx.GetSinkList() { 49 | if sink.Name == defaultSinkName { 50 | defaultSink = sink 51 | break 52 | } 53 | } 54 | return 55 | } 56 | 57 | func getPulseDefaultSource(ctx *Context) (defaultSource *Source) { 58 | defaultSinkName := ctx.GetDefaultSource() 59 | for _, source := range ctx.GetSourceList() { 60 | if source.Name == defaultSinkName { 61 | defaultSource = source 62 | break 63 | } 64 | } 65 | return 66 | } 67 | 68 | func getCard(ctx *Context, index uint32) (*Card, error) { 69 | cardIndex, err := ctx.GetCard(index) 70 | if err != nil { 71 | err := errors.New("failed to get default source") 72 | return nil, err 73 | } 74 | for _, card := range ctx.GetCardList() { 75 | if card.Name == cardIndex.Name { 76 | return card, nil 77 | } 78 | } 79 | return nil, errors.New("failed to get default source") 80 | } 81 | -------------------------------------------------------------------------------- /pulse/server.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pulse 6 | 7 | /* 8 | #include "dde-pulse.h" 9 | */ 10 | import "C" 11 | 12 | type Server struct { 13 | UserName string 14 | HostName string 15 | ServerVersion string 16 | ServerName string 17 | //sample_spec 18 | DefaultSinkName string 19 | DefaultSourceName string 20 | Cookie uint32 21 | ChannelMap ChannelMap 22 | } 23 | 24 | func toServerInfo(info *C.pa_server_info) *Server { 25 | s := &Server{} 26 | s.UserName = C.GoString(info.user_name) 27 | s.HostName = C.GoString(info.host_name) 28 | s.ServerVersion = C.GoString(info.server_version) 29 | s.ServerName = C.GoString(info.server_name) 30 | //sample_spec 31 | s.DefaultSinkName = C.GoString(info.default_sink_name) 32 | s.DefaultSourceName = C.GoString(info.default_source_name) 33 | s.Cookie = uint32(info.cookie) 34 | s.ChannelMap = ChannelMap{info.channel_map} 35 | return s 36 | } 37 | -------------------------------------------------------------------------------- /pulse/sink.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pulse 6 | 7 | /* 8 | #include "dde-pulse.h" 9 | */ 10 | import "C" 11 | 12 | type Sink struct { 13 | Index uint32 14 | 15 | Name string 16 | Description string 17 | 18 | //sample_spec 19 | 20 | ChannelMap ChannelMap 21 | 22 | OwnerModule uint32 23 | Volume CVolume 24 | Mute bool 25 | MonitorSource uint32 26 | MonitorSourceName string 27 | //latency pa_usec_t 28 | 29 | Driver string 30 | Flags int 31 | 32 | PropList map[string]string 33 | 34 | //configured_latency pa_usec_t 35 | 36 | BaseVolume Volume 37 | 38 | //state pa_sink_state_t 39 | 40 | NVolumeSteps uint32 41 | 42 | Card uint32 43 | 44 | Ports []PortInfo 45 | ActivePort PortInfo 46 | 47 | //n_formats 48 | //formats 49 | } 50 | 51 | func toSinkInfo(info *C.pa_sink_info) *Sink { 52 | s := &Sink{} 53 | 54 | s.Index = uint32(info.index) 55 | 56 | s.Name = C.GoString(info.name) 57 | 58 | s.Description = C.GoString(info.description) 59 | 60 | //sample_spec 61 | 62 | s.ChannelMap = ChannelMap{info.channel_map} 63 | 64 | s.OwnerModule = uint32(info.owner_module) 65 | 66 | s.Volume = CVolume{info.volume} 67 | 68 | s.Mute = toBool(info.mute) 69 | 70 | s.MonitorSource = uint32(info.monitor_source) 71 | 72 | s.MonitorSourceName = C.GoString(info.monitor_source_name) 73 | 74 | //latency 75 | 76 | s.Flags = int(info.flags) 77 | 78 | s.Driver = C.GoString(info.driver) 79 | 80 | s.PropList = toProplist(info.proplist) 81 | 82 | //configured_latency 83 | 84 | s.BaseVolume = Volume{info.base_volume} 85 | 86 | //state 87 | 88 | s.NVolumeSteps = uint32(info.n_volume_steps) 89 | 90 | s.Card = uint32(info.card) 91 | 92 | s.Ports = toPorts(uint32(info.n_ports), info.ports) 93 | 94 | s.ActivePort = toPort(info.active_port) 95 | 96 | //n_formats 97 | //formats 98 | 99 | return s 100 | } 101 | -------------------------------------------------------------------------------- /pulse/sink_input.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pulse 6 | 7 | /* 8 | #include "dde-pulse.h" 9 | */ 10 | import "C" 11 | 12 | type SinkInput struct { 13 | Index uint32 14 | Name string 15 | OwnerModule uint32 16 | Client uint32 17 | Sink uint32 18 | 19 | //sample_spec 20 | 21 | ChannelMap ChannelMap 22 | Volume CVolume 23 | 24 | //buffer usec 25 | //sink usec 26 | 27 | ResampleMethod string 28 | Driver string 29 | 30 | Mute bool 31 | PropList map[string]string 32 | Corked int 33 | 34 | HasVolume bool 35 | VolumeWritable bool 36 | 37 | //format 38 | } 39 | 40 | func toSinkInputInfo(info *C.pa_sink_input_info) *SinkInput { 41 | s := &SinkInput{} 42 | s.Index = uint32(info.index) 43 | s.Name = C.GoString(info.name) 44 | s.OwnerModule = uint32(info.owner_module) 45 | s.Client = uint32(info.client) 46 | s.Sink = uint32(info.sink) 47 | 48 | //sample_spec 49 | 50 | s.ChannelMap = ChannelMap{info.channel_map} 51 | s.Volume = CVolume{info.volume} 52 | 53 | //buffer usec 54 | //sink usec 55 | 56 | s.ResampleMethod = C.GoString(info.resample_method) 57 | s.Driver = C.GoString(info.driver) 58 | 59 | s.Mute = toBool(info.mute) 60 | 61 | s.PropList = toProplist(info.proplist) 62 | s.Corked = int(info.corked) 63 | 64 | s.HasVolume = toBool(info.has_volume) 65 | s.VolumeWritable = toBool(info.volume_writable) 66 | 67 | //format 68 | 69 | return s 70 | } 71 | -------------------------------------------------------------------------------- /pulse/source.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pulse 6 | 7 | /* 8 | #include "dde-pulse.h" 9 | */ 10 | import "C" 11 | 12 | type Source struct { 13 | Index uint32 14 | 15 | Name string 16 | Description string 17 | 18 | //sample_spec 19 | 20 | ChannelMap ChannelMap 21 | OwnerModule uint32 22 | Volume CVolume 23 | Mute bool 24 | MonitorOfSink uint32 25 | MonitorOfSinkName string 26 | 27 | //latency pa_usec_t 28 | 29 | Driver string 30 | 31 | Flags int 32 | 33 | Proplist map[string]string 34 | 35 | BaseVolume Volume 36 | 37 | //state 38 | 39 | NVolumeSteps uint32 40 | Card uint32 41 | Ports []PortInfo 42 | ActivePort PortInfo 43 | 44 | //n_formats 45 | //formats 46 | } 47 | 48 | func toSourceInfo(info *C.pa_source_info) *Source { 49 | s := &Source{} 50 | s.Index = uint32(info.index) 51 | s.Name = C.GoString(info.name) 52 | s.Description = C.GoString(info.description) 53 | s.ChannelMap = ChannelMap{info.channel_map} 54 | //sample_spec 55 | s.OwnerModule = uint32(info.owner_module) 56 | s.Volume = CVolume{info.volume} 57 | s.Mute = toBool(info.mute) 58 | s.MonitorOfSink = uint32(info.monitor_of_sink) 59 | s.MonitorOfSinkName = C.GoString(info.monitor_of_sink_name) 60 | 61 | //latency pa_usec_t 62 | 63 | s.Driver = C.GoString(info.driver) 64 | 65 | //flags pa_source_flags_t 66 | s.Flags = int(info.flags) 67 | 68 | s.Proplist = toProplist(info.proplist) 69 | s.BaseVolume = Volume{info.base_volume} 70 | 71 | //state 72 | 73 | s.NVolumeSteps = uint32(info.n_volume_steps) 74 | s.Card = uint32(info.card) 75 | s.Ports = toSourcePorts(uint32(info.n_ports), info.ports) 76 | s.ActivePort = toSourcePort(info.active_port) 77 | 78 | //n_formats 79 | //formats 80 | return s 81 | } 82 | -------------------------------------------------------------------------------- /pulse/source_output.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pulse 6 | 7 | /* 8 | #include "dde-pulse.h" 9 | */ 10 | import "C" 11 | 12 | type SourceOutput struct{} 13 | 14 | func toSourceOutputInfo(info *C.pa_source_output_info) *SourceOutput { 15 | return nil 16 | } 17 | -------------------------------------------------------------------------------- /pulse/thread_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package pulse 6 | 7 | import ( 8 | "math/rand" 9 | "testing" 10 | ) 11 | 12 | func BenchmarkTheadSafe(b *testing.B) { 13 | ctx := GetContext() 14 | sinks := ctx.GetSinkList() 15 | for _, s := range sinks { 16 | old := s.Volume 17 | for i := 0; i < b.N; i++ { 18 | v := s.Volume.SetAvg(rand.Float64()) 19 | ctx.SetSinkVolumeByIndex(s.Index, v) 20 | } 21 | ctx.SetSinkVolumeByIndex(s.Index, old) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /shell/shell.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package shell 6 | 7 | import ( 8 | "bytes" 9 | "strings" 10 | ) 11 | 12 | const specialChars = "`~!#$&*()|\\;'\"<>? " 13 | 14 | func isSpecialChar(c byte) bool { 15 | return strings.IndexByte(specialChars, c) >= 0 16 | } 17 | 18 | // Encode returns a sh string literal representing s 19 | func Encode(s string) string { 20 | var buf bytes.Buffer 21 | for i := 0; i < len(s); i++ { 22 | c := s[i] 23 | if isSpecialChar(c) { 24 | buf.WriteByte('\\') 25 | buf.WriteByte(c) 26 | } else if c == '\t' { 27 | buf.WriteString(`'\t'`) 28 | } else if c == '\r' { 29 | buf.WriteString(`'\r'`) 30 | } else if c == '\n' { 31 | buf.WriteString(`'\n'`) 32 | } else { 33 | buf.WriteByte(c) 34 | } 35 | } 36 | return buf.String() 37 | } 38 | -------------------------------------------------------------------------------- /shell/shell_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package shell 6 | 7 | import ( 8 | "os/exec" 9 | "testing" 10 | ) 11 | 12 | func TestEncode(t *testing.T) { 13 | _, err := exec.LookPath("dash") 14 | if err != nil { 15 | t.Skip("not found dash") 16 | } 17 | 18 | for _, s := range []string{ 19 | "hello world", 20 | "hello$world", 21 | "hello\t\r\nworld", 22 | "中文 english", 23 | "`~!#$&*()|\\;'\"<>? ", 24 | } { 25 | r := Encode(s) 26 | t.Log(r) 27 | 28 | cmd := exec.Command("dash", "-c", "echo -n "+r) 29 | output, err := cmd.Output() 30 | if err != nil { 31 | t.Fatal(err) 32 | } 33 | if s != string(output) { 34 | t.Errorf("%q != %q", s, string(output)) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sound/player.h: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | #ifndef __PLAYER_H__ 6 | #define __PLAYER_H__ 7 | 8 | #include 9 | 10 | int canberra_play_system_sound(char *theme, char *event_id, 11 | char *device, char* driver); 12 | int canberra_play_sound_file(char *file, char *device, char* driver); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /sound/utils.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package sound 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "path" 11 | "github.com/linuxdeepin/go-lib/utils" 12 | ) 13 | 14 | var ( 15 | errInvalidEvent = fmt.Errorf("invalid theme event") 16 | ) 17 | 18 | func findThemeFile(theme, event string) (string, error) { 19 | var home = os.Getenv("HOME") 20 | var themeDirs = []string{ 21 | path.Join(home, ".local/share/sounds"), 22 | "/usr/local/share/sounds", 23 | "/usr/share/sounds", 24 | } 25 | 26 | for _, dir := range themeDirs { 27 | // TODO: fix non ogg/oga event 28 | // TODO: handle sound theme 'index.theme' 29 | file := path.Join(dir, theme, "stereo", event+".ogg") 30 | if utils.IsFileExist(file) { 31 | return file, nil 32 | } 33 | file = path.Join(dir, theme, "stereo", event+".oga") 34 | if utils.IsFileExist(file) { 35 | return file, nil 36 | } 37 | } 38 | return "", errInvalidEvent 39 | } 40 | -------------------------------------------------------------------------------- /sound/utils_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package sound 6 | 7 | import ( 8 | "fmt" 9 | "github.com/stretchr/testify/assert" 10 | "testing" 11 | ) 12 | 13 | func Test_findThemeFile(t *testing.T) { 14 | file, err := findThemeFile("freedesktop", "service-login") 15 | if err != nil { 16 | assert.Equal(t, err, fmt.Errorf("invalid theme event")) 17 | } else { 18 | assert.Equal(t, file, "/usr/share/sounds/freedesktop/stereo/service-login.oga") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /sound_effect/ogg.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package sound_effect 6 | 7 | import ( 8 | "io" 9 | "time" 10 | 11 | "github.com/linuxdeepin/go-lib/asound" 12 | paSimple "github.com/linuxdeepin/go-lib/pulse/simple" 13 | "github.com/linuxdeepin/go-lib/stb_vorbis" 14 | ) 15 | 16 | func newOggDecoder(file string) (Decoder, error) { 17 | decoder, err := stb_vorbis.OpenFile(file) 18 | if err != nil { 19 | return nil, err 20 | } 21 | info := decoder.GetInfo() 22 | channels := info.Channels 23 | sampleRate := info.SampleRate 24 | sampleSpec := &SampleSpec{ 25 | channels: channels, 26 | rate: int(sampleRate), 27 | paFormat: paSimple.SampleFormatS16LE, 28 | pcmFormat: asound.PCMFormatS16LE, 29 | } 30 | bufSize := int(sampleRate) / 8 * channels * 2 31 | return &OggDecoder{ 32 | core: decoder, 33 | sampleSpec: sampleSpec, 34 | bufSize: bufSize, 35 | }, nil 36 | } 37 | 38 | type OggDecoder struct { 39 | core stb_vorbis.Decoder 40 | sampleSpec *SampleSpec 41 | bufSize int 42 | } 43 | 44 | func (d *OggDecoder) GetDuration() time.Duration { 45 | // TODO 46 | return 0 47 | } 48 | 49 | func (d *OggDecoder) Decode() ([]byte, error) { 50 | channels := d.sampleSpec.channels 51 | buf := make([]byte, d.bufSize) 52 | samples := d.core.GetSamplesShortInterleaved(channels, buf) 53 | if samples <= 0 { 54 | err := d.core.GetError() 55 | if err != nil { 56 | return nil, err 57 | } 58 | return nil, io.EOF 59 | } 60 | 61 | bytes := uint(2 * samples * channels) 62 | return buf[:bytes], nil 63 | } 64 | 65 | func (d *OggDecoder) GetSampleSpec() *SampleSpec { 66 | return d.sampleSpec 67 | } 68 | 69 | func (d *OggDecoder) Close() error { 70 | d.core.Close() 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /sound_effect/pulse_backend.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package sound_effect 6 | 7 | import ( 8 | "fmt" 9 | "unsafe" 10 | 11 | "github.com/linuxdeepin/go-lib/pulse" 12 | paSimple "github.com/linuxdeepin/go-lib/pulse/simple" 13 | ) 14 | 15 | type PulseAudioPlayBackend struct { 16 | conn paSimple.Conn 17 | } 18 | 19 | func getPulseDefaultSink() string { 20 | ctx := pulse.GetContext() 21 | if ctx == nil { 22 | return "" 23 | } 24 | device := ctx.GetDefaultSink() 25 | fmt.Printf("use '%s' instead of empty device\n", device) 26 | return device 27 | } 28 | 29 | func newPulseAudioPlayBackend(event, device string, sampleSpec *SampleSpec) (PlayBackend, error) { 30 | if device == "" { 31 | device = getPulseDefaultSink() 32 | } 33 | 34 | paConn, err := paSimple.NewConn("", "com.deepin.SoundEffect", 35 | paSimple.StreamDirectionPlayback, device, event, sampleSpec.GetPaSampleSpec()) 36 | 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | return &PulseAudioPlayBackend{ 42 | conn: paConn, 43 | }, nil 44 | } 45 | 46 | func (pb *PulseAudioPlayBackend) Write(data []byte) error { 47 | _, err := pb.conn.Write(unsafe.Pointer(&data[0]), uint(len(data))) 48 | return err 49 | } 50 | 51 | func (pb *PulseAudioPlayBackend) Drain() error { 52 | _, err := pb.conn.Drain() 53 | return err 54 | } 55 | 56 | func (pb *PulseAudioPlayBackend) Close() error { 57 | pb.conn.Free() 58 | return nil 59 | } 60 | -------------------------------------------------------------------------------- /strv/strv.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package strv 6 | 7 | // string vector 8 | 9 | type Strv []string 10 | 11 | func (vector Strv) Contains(str string) bool { 12 | for _, e := range vector { 13 | if e == str { 14 | return true 15 | } 16 | } 17 | return false 18 | } 19 | 20 | func (v1 Strv) Equal(v2 Strv) bool { 21 | if len(v1) != len(v2) { 22 | return false 23 | } 24 | for i, e1 := range v1 { 25 | if e1 != v2[i] { 26 | return false 27 | } 28 | } 29 | return true 30 | } 31 | 32 | func (vector Strv) Uniq() Strv { 33 | var newVector Strv 34 | for _, e := range vector { 35 | if !newVector.Contains(e) { 36 | newVector = append(newVector, e) 37 | } 38 | } 39 | return newVector 40 | } 41 | 42 | func (vector Strv) FilterFunc(fn func(string) bool) Strv { 43 | if fn == nil { 44 | return vector 45 | } 46 | 47 | newVector := make(Strv, 0, len(vector)) 48 | for _, e := range vector { 49 | if fn(e) { 50 | continue 51 | } 52 | newVector = append(newVector, e) 53 | } 54 | return newVector 55 | } 56 | 57 | func (vector Strv) FilterEmpty() Strv { 58 | newVector := make(Strv, 0, len(vector)) 59 | for _, e := range vector { 60 | if len(e) == 0 { 61 | continue 62 | } 63 | newVector = append(newVector, e) 64 | } 65 | return newVector 66 | } 67 | 68 | func (vector Strv) Add(str string) (Strv, bool) { 69 | if vector.Contains(str) { 70 | return vector, false 71 | } 72 | return Strv(append(vector, str)), true 73 | } 74 | 75 | func (vector Strv) Delete(str string) (Strv, bool) { 76 | var found bool 77 | ret := make(Strv, 0, len(vector)) 78 | 79 | for _, e := range vector { 80 | if e == str { 81 | found = true 82 | continue 83 | } 84 | ret = append(ret, e) 85 | } 86 | 87 | return ret, found 88 | } 89 | -------------------------------------------------------------------------------- /tasker/delay_task_manager.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package tasker 6 | 7 | import ( 8 | "fmt" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | type DelayTaskManager struct { 14 | taskMap map[string]*DelayTask 15 | locker sync.Mutex 16 | } 17 | 18 | func NewDelayTaskManager() *DelayTaskManager { 19 | return &DelayTaskManager{ 20 | taskMap: make(map[string]*DelayTask), 21 | } 22 | } 23 | 24 | func (m *DelayTaskManager) AddTask(name string, duration time.Duration, cb interface{}) error { 25 | m.locker.Lock() 26 | defer m.locker.Unlock() 27 | if _, ok := m.taskMap[name]; ok { 28 | return fmt.Errorf("Task '%s' has exists", name) 29 | } 30 | 31 | task, err := NewDelayTask(duration, cb) 32 | if err != nil { 33 | return err 34 | } 35 | m.taskMap[name] = task 36 | return nil 37 | } 38 | 39 | func (m *DelayTaskManager) GetTask(name string) (*DelayTask, error) { 40 | m.locker.Lock() 41 | defer m.locker.Unlock() 42 | task, ok := m.taskMap[name] 43 | if !ok { 44 | return nil, fmt.Errorf("No task '%s' exists", name) 45 | } 46 | return task, nil 47 | } 48 | 49 | func (m *DelayTaskManager) DeleteTask(name string) { 50 | m.locker.Lock() 51 | defer m.locker.Unlock() 52 | task, ok := m.taskMap[name] 53 | if !ok { 54 | return 55 | } 56 | task.Stop() 57 | task = nil 58 | delete(m.taskMap, name) 59 | } 60 | 61 | func (m *DelayTaskManager) Destroy() { 62 | m.locker.Lock() 63 | defer m.locker.Unlock() 64 | for _, task := range m.taskMap { 65 | task.Stop() 66 | task = nil 67 | } 68 | m.taskMap = nil 69 | } 70 | -------------------------------------------------------------------------------- /tasker/tasker_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package tasker 6 | 7 | import ( 8 | "fmt" 9 | "testing" 10 | "time" 11 | ) 12 | 13 | func handleTask(id int, name string) { 14 | fmt.Printf("%v: %s\n", id, name) 15 | } 16 | 17 | func TestDelayTask(t *testing.T) { 18 | _, err := NewDelayTask(time.Second*1, nil) 19 | if err == nil { 20 | panic("Failed: should error, because if invalid callback function") 21 | } 22 | 23 | task, err := NewDelayTask(time.Second*1, handleTask) 24 | if err != nil { 25 | panic("Failed: should no error") 26 | } 27 | 28 | err = task.Start(1, "First") 29 | if err != nil { 30 | panic("Failed: should no error") 31 | } 32 | time.Sleep(time.Second * 2) 33 | err = task.Start(2, "Second") 34 | if err != nil { 35 | panic("Failed: should no error") 36 | } 37 | time.Sleep(time.Millisecond * 500) 38 | err = task.Start(3, "Third") 39 | if err != nil { 40 | panic("Failed: should no error") 41 | } 42 | time.Sleep(time.Millisecond * 1200) 43 | } 44 | -------------------------------------------------------------------------------- /timer/time.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package timer 6 | 7 | // #include 8 | import "C" 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // TimeSpec holds times. 15 | type TimeSpec struct { 16 | seconds int64 17 | nanoSeconds int64 18 | } 19 | 20 | func (ts TimeSpec) String() string { 21 | return fmt.Sprintf("%d.%d", ts.Seconds(), ts.NanoSeconds()) 22 | } 23 | 24 | // Seconds returns the seconds. 25 | func (ts TimeSpec) Seconds() int64 { 26 | return ts.seconds 27 | } 28 | 29 | // Milliseconds returns the milliseconds 30 | func (ts TimeSpec) Milliseconds() int64 { 31 | return ts.seconds*1000 + ts.nanoSeconds/1000000 32 | } 33 | 34 | // MicroSeconds returns milliseconds 35 | func (ts TimeSpec) MicroSeconds() int64 { 36 | return ts.seconds*1000000 + ts.nanoSeconds/1000 37 | } 38 | 39 | // NanoSeconds returns nanoseconds 40 | func (ts TimeSpec) NanoSeconds() int64 { 41 | return ts.nanoSeconds 42 | } 43 | 44 | // GetMonotonicTime returns the monotonic time, used when the time should be effected by time adjust, like timer. 45 | // according to the sources of golang, the time.Now() is the CLOCK_REALTIME 46 | // which will be affected by discontinuous jumps in the system time. 47 | func GetMonotonicTime() TimeSpec { 48 | var ts C.struct_timespec 49 | 50 | // see http://man7.org/linux/man-pages/man2/clock_gettime.2.html for a list of CLOCK_ constants 51 | C.clock_gettime(C.CLOCK_MONOTONIC_RAW, &ts) 52 | 53 | // convert to something easier to manipulate 54 | return TimeSpec{int64(ts.tv_sec), int64(ts.tv_nsec)} 55 | } 56 | -------------------------------------------------------------------------------- /timer/timer.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package timer 6 | 7 | import ( 8 | "time" 9 | ) 10 | 11 | type _TimerState uint16 12 | 13 | const ( 14 | _TimerStateNotStarted _TimerState = iota 15 | _TimerStateStarted 16 | _TimerStateStopped 17 | ) 18 | 19 | // Timer is used for reporting rate. 20 | type Timer struct { 21 | timer time.Time 22 | duration time.Duration 23 | lastDuration time.Duration 24 | state _TimerState 25 | } 26 | 27 | // NewTimer creates a new timer. 28 | func NewTimer() *Timer { 29 | timer := &Timer{ 30 | timer: time.Now(), 31 | duration: 0, 32 | state: _TimerStateNotStarted, 33 | } 34 | return timer 35 | } 36 | 37 | // Start the timer. 38 | func (timer *Timer) Start() { 39 | timer.state = _TimerStateStarted 40 | timer.timer = time.Now() 41 | } 42 | 43 | // Stop timer. 44 | func (timer *Timer) Stop() { 45 | if timer.state&_TimerStateStarted != 1 { 46 | return 47 | } 48 | timer.state = _TimerStateStopped 49 | timer.duration += time.Since(timer.timer) 50 | timer.lastDuration = timer.duration 51 | } 52 | 53 | // Continue a stopped timer. 54 | func (timer *Timer) Continue() { 55 | timer.Start() 56 | } 57 | 58 | // Reset a timer. 59 | func (timer *Timer) Reset() { 60 | timer.duration = time.Duration(0) 61 | timer.Start() 62 | } 63 | 64 | // Elapsed returns the duration from start to end if timer is stopped. 65 | // Elapsed returns the duration from start to now if timer is not stopped. 66 | func (timer *Timer) Elapsed() time.Duration { 67 | if timer.state == _TimerStateStarted { 68 | return timer.lastDuration + time.Since(timer.timer) 69 | } 70 | 71 | return timer.duration 72 | } 73 | -------------------------------------------------------------------------------- /timer/timer_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package timer 6 | 7 | import ( 8 | "github.com/stretchr/testify/assert" 9 | "testing" 10 | "time" 11 | ) 12 | 13 | func TestTimer(t *testing.T) { 14 | timer := NewTimer() 15 | timer.Stop() 16 | assert.Equal(t, timer.Elapsed(), time.Duration(0)) 17 | 18 | timer = NewTimer() 19 | timer.Start() 20 | 21 | time.Sleep(time.Second) 22 | assert.NotEqual(t, timer.Elapsed(), time.Second-time.Millisecond*100, time.Second+time.Millisecond*100) 23 | 24 | time.Sleep(time.Second) 25 | assert.NotEqual(t, timer.Elapsed(), time.Second*2-time.Millisecond*100, time.Second*3+time.Millisecond*100) 26 | 27 | timer = NewTimer() 28 | timer.Start() 29 | 30 | time.Sleep(time.Second) 31 | timer.Stop() 32 | assert.NotEqual(t, timer.Elapsed(), time.Second-time.Millisecond*100, time.Second+time.Millisecond*100) 33 | 34 | time.Sleep(time.Second) 35 | assert.NotEqual(t, timer.Elapsed(), time.Second-time.Millisecond*100, time.Second+time.Millisecond*100) 36 | 37 | timer = NewTimer() 38 | timer.Start() 39 | 40 | time.Sleep(time.Second) 41 | assert.NotEqual(t, timer.Elapsed(), time.Second-time.Millisecond*100, time.Second+time.Millisecond*100) 42 | 43 | timer.Stop() 44 | assert.NotEqual(t, timer.Elapsed(), time.Second-time.Millisecond*100, time.Second+time.Millisecond*100) 45 | 46 | time.Sleep(time.Second) 47 | timer.Continue() 48 | assert.NotEqual(t, timer.Elapsed(), time.Second-time.Millisecond*100, time.Second+time.Millisecond*100) 49 | 50 | time.Sleep(time.Second) 51 | assert.NotEqual(t, timer.Elapsed(), time.Second*2-time.Millisecond*100, time.Second*2+time.Millisecond*100) 52 | 53 | timer = NewTimer() 54 | timer.Start() 55 | 56 | time.Sleep(time.Second) 57 | assert.NotEqual(t, timer.Elapsed(), time.Second-time.Millisecond*100, time.Second+time.Millisecond*100) 58 | 59 | timer.Reset() 60 | time.Sleep(time.Second) 61 | assert.NotEqual(t, timer.Elapsed(), time.Second-time.Millisecond*100, time.Second+time.Millisecond*100) 62 | } 63 | -------------------------------------------------------------------------------- /users/group/group_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package group 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestGetGroupByName(t *testing.T) { 15 | name := "root" 16 | group, err := GetGroupByName(name) 17 | require.NoError(t, err) 18 | assert.Equal(t, group.Gid, uint32(0)) 19 | 20 | name = "root2" 21 | group, err = GetGroupByName(name) 22 | require.Nil(t, group) 23 | assert.Equal(t, err, &GroupNotFoundError{Name: name}) 24 | } 25 | 26 | func TestGetGroupByGid(t *testing.T) { 27 | uid := uint32(0) 28 | group, err := GetGroupByGid(uid) 29 | require.NoError(t, err) 30 | assert.Equal(t, group.Name, "root") 31 | } 32 | 33 | func TestGetGroupEntry(t *testing.T) { 34 | groups := GetGroupEntry() 35 | assert.NotEqual(t, len(groups), 0) 36 | } 37 | -------------------------------------------------------------------------------- /users/passwd/passwd_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package passwd 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestGetPasswdByName(t *testing.T) { 15 | name := "root" 16 | passwd, err := GetPasswdByName(name) 17 | assert.Equal(t, passwd.Home, "/root") 18 | assert.Equal(t, passwd.Uid, uint32(0)) 19 | require.NoError(t, err) 20 | 21 | name = "root2" 22 | passwd, err = GetPasswdByName(name) 23 | require.Nil(t, passwd) 24 | assert.Equal(t, err, &UserNotFoundError{Name: name}) 25 | } 26 | 27 | func TestGetPasswdByUid(t *testing.T) { 28 | uid := uint32(0) 29 | passwd, err := GetPasswdByUid(uid) 30 | require.NoError(t, err) 31 | assert.Equal(t, passwd.Name, "root") 32 | } 33 | 34 | func TestGetPasswdEntry(t *testing.T) { 35 | passwds := GetPasswdEntry() 36 | assert.NotEqual(t, len(passwds), 0) 37 | assert.Equal(t, passwds[0].Name, "root") 38 | } 39 | -------------------------------------------------------------------------------- /users/shadow/shadow_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package shadow 6 | 7 | import ( 8 | "syscall" 9 | "testing" 10 | 11 | "github.com/stretchr/testify/assert" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestGetShadowByName(t *testing.T) { 16 | name := "root" 17 | shadow, err := GetShadowByName(name) 18 | 19 | if err != nil { 20 | // Permission denied, current user has no access to shadow file 21 | require.Nil(t, shadow) 22 | assert.Equal(t, err, syscall.EACCES) 23 | } else { 24 | assert.Equal(t, shadow.Name, "root") 25 | } 26 | } 27 | 28 | func TestGetShadowEntry(t *testing.T) { 29 | shadows := GetShadowEntry() 30 | if len(shadows) > 0 { 31 | assert.Equal(t, shadows[0].Name, "root") 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /utils/cache.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "path" 11 | ) 12 | 13 | var DefaultCachePrefix = os.Getenv("HOME") + "/.cache/deepin" 14 | 15 | func GenerateCacheFilePath(keyword string) (dstfile string) { 16 | cachePathFormat := DefaultCachePrefix + "/%s" 17 | md5, _ := SumStrMd5(keyword) 18 | dstfile = fmt.Sprintf(cachePathFormat, md5) 19 | _ = EnsureDirExist(path.Dir(dstfile)) 20 | return 21 | } 22 | 23 | func GenerateCacheFilePathWithPrefix(prefix, keyword string) (dstfile string) { 24 | graphicCacheFormat := DefaultCachePrefix + "/%s/%s" 25 | md5, _ := SumStrMd5(keyword) 26 | dstfile = fmt.Sprintf(graphicCacheFormat, prefix, md5) 27 | _ = EnsureDirExist(path.Dir(dstfile)) 28 | return 29 | } 30 | -------------------------------------------------------------------------------- /utils/config.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | import ( 8 | "encoding/json" 9 | "io/ioutil" 10 | "os" 11 | "path" 12 | "sync" 13 | ) 14 | 15 | var ( 16 | DefaultHomeConfigPrefix = os.Getenv("HOME") + "/.config/deepin/" 17 | DefaultSystemConfigPrefix = "/var/cache/deepin/" 18 | DefaultConfigExt = ".json" 19 | ) 20 | 21 | type Config struct { 22 | configFile string 23 | lock sync.Mutex 24 | } 25 | 26 | func (c *Config) Lock() { 27 | c.lock.Lock() 28 | } 29 | 30 | func (c *Config) Unlock() { 31 | c.lock.Unlock() 32 | } 33 | 34 | func (c *Config) SetConfigFile(file string) { 35 | c.configFile = file 36 | } 37 | 38 | func (c *Config) GetConfigFile() string { 39 | return c.configFile 40 | } 41 | 42 | func (c *Config) SetConfigName(name string) { 43 | c.SetConfigFile(DefaultHomeConfigPrefix + name + DefaultConfigExt) 44 | } 45 | 46 | func (c *Config) SetSystemConfigName(name string) { 47 | c.SetConfigFile(DefaultSystemConfigPrefix + name + DefaultConfigExt) 48 | } 49 | 50 | func (c *Config) IsConfigFileExists() bool { 51 | return IsFileExist(c.configFile) 52 | } 53 | 54 | func (c *Config) RemoveConfigFile() error { 55 | return os.Remove(c.configFile) 56 | } 57 | 58 | func (c *Config) Load(v interface{}) (err error) { 59 | if IsFileExist(c.configFile) { 60 | var fileContent []byte 61 | fileContent, err = ioutil.ReadFile(c.configFile) 62 | if err != nil { 63 | return 64 | } 65 | err = json.Unmarshal(fileContent, v) 66 | } else { 67 | err = c.Save(v) 68 | } 69 | return 70 | } 71 | 72 | func (c *Config) Save(v interface{}) (err error) { 73 | c.Lock() 74 | defer c.Unlock() 75 | _ = EnsureDirExist(path.Dir(c.configFile)) 76 | var fileContent []byte 77 | fileContent, err = c.GetFileContentToSave(v) 78 | if err != nil { 79 | return 80 | } 81 | err = ioutil.WriteFile(c.configFile, fileContent, 0644) 82 | return 83 | } 84 | 85 | func (c *Config) GetFileContentToSave(v interface{}) (fileContent []byte, err error) { 86 | fileContent, err = json.Marshal(v) 87 | return 88 | } 89 | -------------------------------------------------------------------------------- /utils/config_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | type testConfig struct { 14 | core Config 15 | Data string 16 | } 17 | 18 | func newTestConfig() (c *testConfig) { 19 | c = &testConfig{} 20 | c.core.SetConfigName("test") 21 | return 22 | } 23 | func (c *testConfig) save() error { 24 | return c.core.Save(c) 25 | } 26 | func (c *testConfig) load() { 27 | _ = c.core.Load(c) 28 | } 29 | 30 | func TestConfig(t *testing.T) { 31 | conf := newTestConfig() 32 | _ = conf.core.RemoveConfigFile() 33 | conf.Data = "data" 34 | err := conf.save() 35 | if err != nil { 36 | t.Skip("Save config failed:" + err.Error()) 37 | return 38 | } 39 | conf.Data = "" 40 | conf.load() 41 | assert.Equal(t, conf.Data, "data") 42 | } 43 | -------------------------------------------------------------------------------- /utils/filesystem.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | /* 8 | #include 9 | #include 10 | */ 11 | import "C" 12 | import ( 13 | "errors" 14 | "unsafe" 15 | ) 16 | 17 | type FilesystemInfo struct { 18 | TotalSize uint64 // byte 19 | FreeSize uint64 20 | AvailSize uint64 21 | UsedSize uint64 22 | } 23 | 24 | func QueryFilesytemInfo(path string) (*FilesystemInfo, error) { 25 | buf := C.struct_statvfs{} 26 | cpath := C.CString(path) 27 | defer C.free(unsafe.Pointer(cpath)) 28 | if C.statvfs(cpath, &buf) != 0 { 29 | return nil, errors.New("Statvfs error.") 30 | } 31 | 32 | total := uint64(buf.f_blocks) * uint64(buf.f_frsize) 33 | free := uint64(buf.f_bfree) * uint64(buf.f_frsize) 34 | //Get real avail size instead of free size. 35 | avail := uint64(buf.f_bavail) * uint64(buf.f_frsize) 36 | return &FilesystemInfo{ 37 | TotalSize: total, 38 | FreeSize: free, 39 | AvailSize: avail, 40 | UsedSize: total - free, 41 | }, nil 42 | } 43 | -------------------------------------------------------------------------------- /utils/keyfile_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | import ( 8 | "github.com/stretchr/testify/assert" 9 | "os" 10 | "testing" 11 | ) 12 | 13 | func TestKeyFile(t *testing.T) { 14 | file := "testdata/test_keyfile.ini" 15 | group := "Test" 16 | key := "id" 17 | value := "1234" 18 | 19 | assert.Equal(t, WriteKeyToKeyFile(file, group, key, value), true) 20 | ifc, ok := ReadKeyFromKeyFile(file, group, key, "") 21 | assert.Equal(t, ok, true) 22 | 23 | assert.Equal(t, value, ifc.(string)) 24 | 25 | os.Remove(file) 26 | } 27 | -------------------------------------------------------------------------------- /utils/md5.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | import ( 8 | "crypto/md5" 9 | "fmt" 10 | "io" 11 | "os" 12 | ) 13 | 14 | func SumStrMd5(str string) (string, bool) { 15 | return fmt.Sprintf("%x", md5.Sum([]byte(str))), true 16 | } 17 | 18 | func SumFileMd5(filename string) (string, bool) { 19 | f, err := os.Open(filename) 20 | if err != nil { 21 | return "", false 22 | } 23 | defer f.Close() 24 | h := md5.New() 25 | _, _ = io.Copy(h, f) 26 | return fmt.Sprintf("%x", h.Sum(nil)), true 27 | } 28 | -------------------------------------------------------------------------------- /utils/md5_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestMD5Sum(t *testing.T) { 14 | testStr := "hello world" 15 | if ret, ok := SumStrMd5(testStr); !ok { 16 | t.Errorf("SumStrMd5 '%s' Faild", testStr) 17 | return 18 | } else { 19 | assert.Equal(t, ret, "5eb63bbbe01eeed093cb22bb8f5acdc3") 20 | } 21 | 22 | testFile := "testdata/testfile" 23 | if ret, ok := SumFileMd5(testFile); !ok { 24 | t.Errorf("SumFileMd5 '%s' Failed", testFile) 25 | return 26 | } else { 27 | assert.Equal(t, ret, "0a75266cc21da8c88a940b00d4d535b7") 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /utils/schemas.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/linuxdeepin/go-gir/gio-2.0" 11 | ) 12 | 13 | func CheckAndNewGSettings(schema string) (*gio.Settings, error) { 14 | if !IsGSchemaExist(schema) { 15 | return nil, fmt.Errorf("Not found this schema: %s", schema) 16 | } 17 | 18 | return gio.NewSettings(schema), nil 19 | } 20 | 21 | func IsGSchemaExist(schema string) bool { 22 | if isSchemaInList(schema, gio.SettingsListSchemas()) || 23 | isSchemaInList(schema, gio.SettingsListRelocatableSchemas()) { 24 | return true 25 | } 26 | 27 | return false 28 | } 29 | 30 | func isSchemaInList(schema string, list []string) bool { 31 | for _, s := range list { 32 | if schema == s { 33 | return true 34 | } 35 | } 36 | 37 | return false 38 | } 39 | -------------------------------------------------------------------------------- /utils/schemas_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | type schemaTest struct { 14 | schema string 15 | exist bool 16 | } 17 | 18 | func TestGSchemaIsExist(t *testing.T) { 19 | schemas := []string{ 20 | "com.deepin.wacom", 21 | "com.deepin.touchpad", 22 | } 23 | 24 | list1 := []schemaTest{ 25 | schemaTest{"com.deepin.wacom", true}, 26 | schemaTest{"com.deepin.touchpad", true}, 27 | } 28 | 29 | list2 := []schemaTest{ 30 | schemaTest{"org.123.123", false}, 31 | schemaTest{"org/11/11", false}, 32 | schemaTest{"sdsdsvfdsfs", false}, 33 | schemaTest{"/dsfd/assasd", false}, 34 | schemaTest{".sds.sadsd.", false}, 35 | schemaTest{"-sds-sds-ss", false}, 36 | schemaTest{"(jjjj)", false}, 37 | schemaTest{"$fgg$", false}, 38 | } 39 | 40 | for _, l := range list1 { 41 | assert.Equal(t, isSchemaInList(l.schema, schemas), l.exist) 42 | } 43 | 44 | for _, l := range list2 { 45 | assert.Equal(t, IsGSchemaExist(l.schema), l.exist) 46 | assert.Equal(t, isSchemaInList(l.schema, schemas), l.exist) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /utils/testdata/copy-dest/file1: -------------------------------------------------------------------------------- 1 | sdddddddddsdxcvdxs 2 | sddddfsdsfffxccccccc 3 | -------------------------------------------------------------------------------- /utils/testdata/copy-dest/test/file2: -------------------------------------------------------------------------------- 1 | qwsancsdjhdj 2 | sdvsdvjsdkjv 3 | -------------------------------------------------------------------------------- /utils/testdata/copy-src/file1: -------------------------------------------------------------------------------- 1 | sdddddddddsdxcvdxs 2 | sddddfsdsfffxccccccc 3 | -------------------------------------------------------------------------------- /utils/testdata/copy-src/test/file2: -------------------------------------------------------------------------------- 1 | qwsancsdjhdj 2 | sdvsdvjsdkjv 3 | -------------------------------------------------------------------------------- /utils/testdata/test-get_files/file1: -------------------------------------------------------------------------------- 1 | ../test1 -------------------------------------------------------------------------------- /utils/testdata/test-get_files/file2: -------------------------------------------------------------------------------- 1 | ../testfile -------------------------------------------------------------------------------- /utils/testdata/test1: -------------------------------------------------------------------------------- 1 | test for md5 2 | -------------------------------------------------------------------------------- /utils/testdata/testfile: -------------------------------------------------------------------------------- 1 | test for md5 2 | -------------------------------------------------------------------------------- /utils/user_special_dir.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | import ( 8 | "os/user" 9 | "path" 10 | ) 11 | 12 | func GetHomeDir() string { 13 | info, err := user.Current() 14 | if err != nil { 15 | return "" 16 | } 17 | 18 | return info.HomeDir 19 | } 20 | 21 | func GetConfigDir() string { 22 | if homeDir := GetHomeDir(); len(homeDir) > 0 { 23 | return path.Join(homeDir, ".config") 24 | } 25 | return "" 26 | } 27 | 28 | func GetCacheDir() string { 29 | if homeDir := GetHomeDir(); len(homeDir) > 0 { 30 | return path.Join(homeDir, ".cache") 31 | } 32 | return "" 33 | } 34 | -------------------------------------------------------------------------------- /utils/utils.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd. 2 | // 3 | // SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | package utils 6 | 7 | import ( 8 | "crypto/rand" 9 | "fmt" 10 | "io" 11 | "reflect" 12 | ) 13 | 14 | func IsElementEqual(e1, e2 interface{}) bool { 15 | if e1 == nil && e2 == nil { 16 | return true 17 | } 18 | 19 | return reflect.DeepEqual(e1, e2) 20 | } 21 | 22 | func IsElementInList(e interface{}, list interface{}) bool { 23 | if list == nil { 24 | return false 25 | } 26 | 27 | v := reflect.ValueOf(list) 28 | if !v.IsValid() { 29 | return false 30 | } 31 | 32 | if v.Type().Kind() == reflect.Slice || 33 | v.Type().Kind() == reflect.Array { 34 | l := v.Len() 35 | for i := 0; i < l; i++ { 36 | if IsElementEqual(e, v.Index(i).Interface()) { 37 | return true 38 | } 39 | } 40 | } 41 | 42 | return false 43 | } 44 | 45 | func GenUuid() string { 46 | uuid := make([]byte, 16) 47 | n, err := io.ReadFull(rand.Reader, uuid) 48 | if n != len(uuid) || err != nil { 49 | panic("This can failed?") 50 | } 51 | // variant bits; see section 4.1.1 52 | uuid[8] = uuid[8]&^0xc0 | 0x80 53 | // version 4 (pseudo-random); see section 4.1.3 54 | uuid[6] = uuid[6]&^0xf0 | 0x40 55 | return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]) 56 | } 57 | 58 | func RandString(n int) string { 59 | const alphanum = "0123456789abcdef" 60 | var bytes = make([]byte, n) 61 | _, _ = rand.Read(bytes) 62 | for i, b := range bytes { 63 | bytes[i] = alphanum[b%byte(len(alphanum))] 64 | } 65 | return string(bytes) 66 | } 67 | 68 | func IsInterfaceNil(v interface{}) bool { 69 | if v == nil { 70 | return true 71 | } 72 | 73 | value := reflect.ValueOf(v) 74 | 75 | // The argument must be a chan, func, interface, map, pointer, or 76 | // slice value; if it is not, Value.IsNil panics. 77 | switch value.Kind() { 78 | case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice: 79 | return value.IsNil() 80 | } 81 | 82 | // should be a not nil type for rest cases 83 | return false 84 | } 85 | -------------------------------------------------------------------------------- /xdg/userdir/testdata/user-dirs.dirs: -------------------------------------------------------------------------------- 1 | # This file is written by xdg-user-dirs-update 2 | # If you want to change or add directories, just edit the line you're 3 | # interested in. All local changes will be retained on the next run 4 | # Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped 5 | # homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an 6 | # absolute path. No other format is supported. 7 | # 8 | XDG_DESKTOP_DIR="$HOME/桌面" 9 | XDG_DOWNLOAD_DIR="$HOME/下载" 10 | XDG_TEMPLATES_DIR="$HOME/.Templates" 11 | XDG_PUBLICSHARE_DIR="$HOME/.Public" 12 | XDG_DOCUMENTS_DIR="$HOME/文档" 13 | XDG_MUSIC_DIR="$HOME/音乐" 14 | XDG_PICTURES_DIR="$HOME/图片" 15 | XDG_VIDEOS_DIR="$HOME/视频" 16 | -------------------------------------------------------------------------------- /xdg/userdir/testdata2/user-dirs.dirs: -------------------------------------------------------------------------------- 1 | XDG_DESKTOP_DIR="$HOME/MyDesktop" 2 | XDG_DOWNLOAD_DIR="$HOME/下载" 3 | XDG_TEMPLATES_DIR="$HOME/.Templates" 4 | XDG_PUBLICSHARE_DIR="$HOME/.Public" 5 | XDG_DOCUMENTS_DIR="$HOME/文档" 6 | XDG_MUSIC_DIR="$HOME/音乐" 7 | XDG_PICTURES_DIR="$HOME/图片" 8 | XDG_VIDEOS_DIR="$HOME/视频" 9 | --------------------------------------------------------------------------------