dhun 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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
+