dhun 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2009 Deepak Jois
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # Introduction
2
+
3
+ > A dhun (Hindi: धुन; literally "tune") is a light instrumental piece in the
4
+ > Hindustani classical music of North India.
5
+ >
6
+ > Source : [Wikipedia](http://en.wikipedia.org/wiki/Dhun)
7
+
8
+ Dhun is a minimalist commandline music player for OS X.
9
+
10
+ It uses Spotlight to search for audio files on your computer and play them.
11
+
12
+ # Features
13
+
14
+ ### Sneak Peek
15
+
16
+ deepak@vyombook ~/code/personal/dhun (master) $ ./dhun Spirit
17
+ Querying for kMDItemContentTypeTree == 'public.audio' && kMDItemAlbum == '*Spirit*'wc
18
+ /Users/deepak/Dropbox/shared/music/Coke Studio/Mai-Ne.mp3
19
+ /Users/deepak/Dropbox/shared/music/Coke Studio/Saari-Raat.mp3
20
+ /Users/deepak/Dropbox/shared/music/Coke Studio/Bulleya.mp3
21
+ /Users/deepak/Dropbox/shared/music/Coke Studio/Mahi-Ve.mp3
22
+ /Users/deepak/Dropbox/shared/music/Coke Studio/Chup.mp3
23
+ 5 results total
24
+ Now Playing /Users/deepak/Dropbox/shared/music/Coke Studio/Mai-Ne.mp3
25
+
26
+ Here is what is planned.
27
+
28
+ * Client server model, where you can issue commands to the server like
29
+ `dhun play Spirit`, `dhun pause`, `dhun next`, `dhun prev` and `dhun stop`
30
+
31
+ * Flexible query syntax (like `artist:Rahman` or `album spirit`)
32
+
data/Rakefile ADDED
@@ -0,0 +1,83 @@
1
+ require 'rake/clean'
2
+
3
+ task :default => :package
4
+
5
+ # PACKAGING =================================================================
6
+
7
+ require 'rubygems/specification'
8
+ $spec = eval(File.read('dhun.gemspec'))
9
+
10
+ def package(ext='')
11
+ "pkg/dhun-#{$spec.version}" + ext
12
+ end
13
+
14
+ desc 'Build packages'
15
+ task :package => %w[.gem .tar.gz].map {|e| package(e)}
16
+
17
+ desc 'Build and install as local gem'
18
+ task :install => package('.gem') do
19
+ sh "gem install #{package('.gem')}"
20
+ end
21
+
22
+ directory 'pkg/'
23
+
24
+ file package('.gem') => %w[pkg/ dhun.gemspec] + $spec.files do |f|
25
+ sh "gem build dhun.gemspec"
26
+ mv File.basename(f.name), f.name
27
+ end
28
+
29
+ file package('.tar.gz') => %w[pkg/] + $spec.files do |f|
30
+ sh "git archive --format=tar HEAD | gzip > #{f.name}"
31
+ end
32
+
33
+ # GEMSPEC HELPERS ==========================================================
34
+
35
+ def source_version
36
+ line = File.read('lib/dhun.rb')[/^\s*VERSION = .*/]
37
+ line.match(/.*VERSION = '(.*)'/)[1]
38
+ end
39
+
40
+ file 'dhun.gemspec' => FileList['Rakefile','lib/dhun.rb'] do |f|
41
+ puts "running"
42
+ # read spec file and split out manifest section
43
+ spec = File.read(f.name)
44
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
45
+ head.sub!(/\.version = '.*'/, ".version = '#{source_version}'")
46
+ head.sub!(/\.date = '.*'/, ".date = '#{Date.today.to_s}'")
47
+ # determine file list from git ls-files
48
+ files = `git ls-files`.
49
+ split("\n").
50
+ sort.
51
+ reject{ |file| file =~ /^\./ || file =~ /^test/ }.
52
+ map{ |file| " #{file}" }.
53
+ join("\n")
54
+ # piece file back together and write...
55
+ manifest = " s.files = %w[\n#{files}\n ]\n"
56
+ spec = [head,manifest,tail].join(" # = MANIFEST =\n")
57
+ File.open(f.name, 'w') { |io| io.write(spec) }
58
+ puts "updated #{f.name}"
59
+ end
60
+
61
+ # ==========================================================
62
+ # Ruby Extension
63
+ # ==========================================================
64
+
65
+ DLEXT = Config::CONFIG['DLEXT']
66
+
67
+ file 'ext/Makefile' => FileList['ext/{*.c,*.h,*.rb}'] do
68
+ chdir('ext') { ruby 'extconf.rb' }
69
+ end
70
+ CLEAN.include 'ext/Makefile', 'ext/mkmf.log'
71
+
72
+ file "ext/dhun_ext.#{DLEXT}" => FileList['ext/Makefile', 'ext/*.{c,h,rb}'] do |f|
73
+ sh 'cd ext && make'
74
+ end
75
+ CLEAN.include 'ext/*.{o,bundle,so,dll}'
76
+
77
+ file "lib/dhun_ext.#{DLEXT}" => "ext/dhun_ext.#{DLEXT}" do |f|
78
+ cp f.prerequisites, "lib/", :preserve => true
79
+ end
80
+
81
+ desc 'Build the dhun extension'
82
+ task :build => "lib/dhun_ext.#{DLEXT}"
83
+
data/TODO.md ADDED
@@ -0,0 +1,19 @@
1
+ * Gem files
2
+
3
+ TODO
4
+ ====
5
+
6
+ * Daemonizing/Logging of Server
7
+
8
+ * Better querying mechanism using a treetop parser
9
+
10
+ * Prev, by keeping a history
11
+
12
+ * Display info from idv3 tags
13
+
14
+ * Advanced Querying Support
15
+
16
+ * iTunes support
17
+
18
+ * Pause and Skip functionality
19
+
data/bin/dhun ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # Thin command line interface script.
3
+ # Run <tt>dhun -h</tt> to get more usage.
4
+ $: << File.expand_path(File.dirname(__FILE__) + "/../lib")
5
+ require 'dhun'
6
+ Dhun::Runner.new(ARGV).run!
7
+
data/ext/Makefile ADDED
@@ -0,0 +1,157 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /usr/local/lib/ruby/1.8/i686-darwin10.0.0
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ exec_prefix = $(prefix)
11
+ prefix = $(DESTDIR)/usr/local
12
+ sharedstatedir = $(prefix)/com
13
+ mandir = $(datarootdir)/man
14
+ psdir = $(docdir)
15
+ oldincludedir = $(DESTDIR)/usr/include
16
+ localedir = $(datarootdir)/locale
17
+ bindir = $(exec_prefix)/bin
18
+ libexecdir = $(exec_prefix)/libexec
19
+ sitedir = $(libdir)/ruby/site_ruby
20
+ htmldir = $(docdir)
21
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
22
+ includedir = $(prefix)/include
23
+ infodir = $(datarootdir)/info
24
+ vendorlibdir = $(vendordir)/$(ruby_version)
25
+ sysconfdir = $(prefix)/etc
26
+ libdir = $(exec_prefix)/lib
27
+ sbindir = $(exec_prefix)/sbin
28
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
29
+ docdir = $(datarootdir)/doc/$(PACKAGE)
30
+ dvidir = $(docdir)
31
+ vendordir = $(libdir)/ruby/vendor_ruby
32
+ datarootdir = $(prefix)/share
33
+ pdfdir = $(docdir)
34
+ archdir = $(rubylibdir)/$(arch)
35
+ sitearchdir = $(sitelibdir)/$(sitearch)
36
+ datadir = $(datarootdir)
37
+ localstatedir = $(prefix)/var
38
+ sitelibdir = $(sitedir)/$(ruby_version)
39
+
40
+ CC = gcc
41
+ LIBRUBY = $(LIBRUBY_SO)
42
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
43
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
44
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
45
+
46
+ RUBY_EXTCONF_H =
47
+ CFLAGS = -fno-common -D_XOPEN_SOURCE=1 -fno-common -pipe -fno-common $(cflags) -std=c99
48
+ INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
49
+ DEFS =
50
+ CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
51
+ CXXFLAGS = $(CFLAGS)
52
+ ldflags = -L. -framework AudioToolbox -framework CoreServices
53
+ dldflags =
54
+ archflag =
55
+ DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
56
+ LDSHARED = cc -dynamic -bundle -undefined suppress -flat_namespace
57
+ AR = ar
58
+ EXEEXT =
59
+
60
+ RUBY_INSTALL_NAME = ruby
61
+ RUBY_SO_NAME = ruby
62
+ arch = i686-darwin10.0.0
63
+ sitearch = i686-darwin10.0.0
64
+ ruby_version = 1.8
65
+ ruby = /usr/local/bin/ruby
66
+ RUBY = $(ruby)
67
+ RM = rm -f
68
+ MAKEDIRS = mkdir -p
69
+ INSTALL = /usr/bin/install -c
70
+ INSTALL_PROG = $(INSTALL) -m 0755
71
+ INSTALL_DATA = $(INSTALL) -m 644
72
+ COPY = cp
73
+
74
+ #### End of system configuration section. ####
75
+
76
+ preload =
77
+
78
+ libpath = . $(libdir)
79
+ LIBPATH = -L. -L$(libdir)
80
+ DEFFILE =
81
+
82
+ CLEANFILES = mkmf.log
83
+ DISTCLEANFILES =
84
+
85
+ extout =
86
+ extout_prefix =
87
+ target_prefix =
88
+ LOCAL_LIBS =
89
+ LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lobjc
90
+ SRCS = dhun_ext.c player.c query.c
91
+ OBJS = dhun_ext.o player.o query.o
92
+ TARGET = dhun_ext
93
+ DLLIB = $(TARGET).bundle
94
+ EXTSTATIC =
95
+ STATIC_LIB =
96
+
97
+ BINDIR = $(bindir)
98
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
99
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
100
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
101
+
102
+ TARGET_SO = $(DLLIB)
103
+ CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
104
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
105
+
106
+ all: $(DLLIB)
107
+ static: $(STATIC_LIB)
108
+
109
+ clean:
110
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
111
+
112
+ distclean: clean
113
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
114
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
115
+
116
+ realclean: distclean
117
+ install: install-so install-rb
118
+
119
+ install-so: $(RUBYARCHDIR)
120
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
121
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
122
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
123
+ install-rb: pre-install-rb install-rb-default
124
+ install-rb-default: pre-install-rb-default
125
+ pre-install-rb: Makefile
126
+ pre-install-rb-default: Makefile
127
+ $(RUBYARCHDIR):
128
+ $(MAKEDIRS) $@
129
+
130
+ site-install: site-install-so site-install-rb
131
+ site-install-so: install-so
132
+ site-install-rb: install-rb
133
+
134
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
135
+
136
+ .cc.o:
137
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
138
+
139
+ .cxx.o:
140
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
141
+
142
+ .cpp.o:
143
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
144
+
145
+ .C.o:
146
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
147
+
148
+ .c.o:
149
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
150
+
151
+ $(DLLIB): $(OBJS) Makefile
152
+ @-$(RM) $@
153
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
154
+
155
+
156
+
157
+ $(OBJS): ruby.h defines.h
data/ext/dhun.h ADDED
@@ -0,0 +1,37 @@
1
+ #include <stdio.h>
2
+ #include <string.h>
3
+
4
+ #include <CoreServices/CoreServices.h>
5
+ #include <CoreAudio/CoreAudioTypes.h>
6
+ #include <AudioToolbox/AudioToolbox.h>
7
+ #include <CoreServices/CoreServices.h>
8
+
9
+ #define LOG(f,s) fprintf(stderr,f,s);fflush(stderr);
10
+ #define QUERY_TEMPLATE "kMDItemContentTypeTree == 'public.audio' && (kMDItemAlbum == '*%s*'wc || kMDItemTitle == '*%s*'wc || kMDItemDisplayName == '*%s*'wc)"
11
+
12
+ #define kNumberBuffers 3
13
+ typedef struct {
14
+ AudioStreamBasicDescription mDataFormat;
15
+ AudioQueueRef mQueue;
16
+ AudioQueueBufferRef mBuffers[kNumberBuffers];
17
+ AudioFileID mAudioFile;
18
+ UInt32 bufferByteSize;
19
+ SInt64 mCurrentPacket;
20
+ UInt32 mNumPacketsToRead;
21
+ AudioStreamPacketDescription *mPacketDescs;
22
+ bool mIsRunning;
23
+ } AQPlayerState;
24
+
25
+ extern AQPlayerState aqData;
26
+
27
+ typedef struct {
28
+ int size;
29
+ char** files;
30
+ } SearchResults;
31
+
32
+ extern SearchResults queryResults;
33
+
34
+
35
+ void playFile(const char* filePath);
36
+ void free_aqData();
37
+ int getFilesForQuery(const char* queryStr);
data/ext/dhun_ext.c ADDED
@@ -0,0 +1,84 @@
1
+ #include "dhun.h"
2
+ #include <assert.h>
3
+ #include <pthread.h>
4
+
5
+ // Include the Ruby headers and goodies
6
+ #include "ruby.h"
7
+ #include "rubysig.h"
8
+ // Defining a space for information and references about the module to be stored internally
9
+ static VALUE DhunExt = Qnil;
10
+
11
+ static VALUE Spotlight = Qnil;
12
+
13
+ static VALUE Player = Qnil;
14
+
15
+ static pthread_t posixThreadID;
16
+
17
+ // Prototype for the initialization method - Ruby calls this, not you
18
+ void Init_dhunruby();
19
+
20
+ static VALUE method_play_file(VALUE self, VALUE fileName);
21
+ static VALUE method_pause_play(VALUE self);
22
+ static VALUE method_query_spotlight(VALUE self, VALUE query);
23
+ static VALUE method_is_playing(VALUE self);
24
+
25
+ // The initialization method for this module
26
+ void Init_dhun_ext() {
27
+ DhunExt = rb_define_class("DhunExt", rb_cObject);
28
+ rb_define_singleton_method(DhunExt, "play_file", method_play_file, 1);
29
+ rb_define_singleton_method(DhunExt, "query_spotlight", method_query_spotlight, 1);
30
+ rb_define_singleton_method(DhunExt, "pause_play", method_pause_play, 0);
31
+ rb_define_singleton_method(DhunExt, "is_playing?", method_is_playing, 0);
32
+ }
33
+
34
+ static VALUE method_play_file(VALUE self, VALUE filename) {
35
+ playFile(StringValuePtr(filename));
36
+ struct timeval wait;
37
+ wait.tv_sec=0;
38
+ wait.tv_usec=100*1000;
39
+ do {
40
+ CHECK_INTS;
41
+ CFRunLoopRunInMode (kCFRunLoopDefaultMode,
42
+ 0.25,
43
+ false);
44
+ } while (aqData.mIsRunning);
45
+
46
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode,
47
+ 1,
48
+ false);
49
+ free_aqData();
50
+ return Qnil;
51
+ }
52
+
53
+ static VALUE method_pause_play(VALUE self) {
54
+ aqData.mIsRunning = false;
55
+ return Qnil;
56
+ }
57
+
58
+ static VALUE method_is_playing(VALUE self) {
59
+ if (aqData.mIsRunning == true)
60
+ return Qtrue;
61
+ else
62
+ return Qfalse;
63
+ }
64
+
65
+ static VALUE method_query_spotlight(VALUE self, VALUE query) {
66
+ getFilesForQuery(StringValuePtr(query));
67
+ VALUE files = rb_ary_new();
68
+
69
+ if (queryResults.size > 0) { // there were some results
70
+
71
+ for(int i=0; i<queryResults.size;i++) {
72
+ rb_ary_push(files,rb_str_new2(queryResults.files[i]));
73
+ free(queryResults.files[i]);
74
+ }
75
+
76
+ if (queryResults.size > 0) {
77
+ queryResults.size = 0;
78
+ free(queryResults.files);
79
+ }
80
+ }
81
+
82
+ return files;
83
+ }
84
+