From 92ad388884a938cbe247503dd789a21215e90636 Mon Sep 17 00:00:00 2001 From: "Adam D. Ruppe" Date: Mon, 22 Dec 2014 13:54:23 -0500 Subject: [PATCH] catchup --- eventloop.d | 8 +++++++- jsvar.d | 9 +++++++-- simpleaudio.d | 54 ++++++++++++++++++++++++++++++++++++++++++++++----- terminal.d | 10 +++++++--- 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/eventloop.d b/eventloop.d index 189d4e2..0583276 100644 --- a/eventloop.d +++ b/eventloop.d @@ -438,7 +438,13 @@ version(linux) { private void addFileToLoopImplementation(int fd, int events) { epoll_event ev; - ev.events = EPOLL_EVENTS.EPOLLET; // edge triggered + // I don't remember why I made it edge triggered in the first + // place as that requires a bit more care to do correctly and I don't + // think I've ever taken that kind of care. I'm going to try switching it + // to level triggered (the event fires whenever the loop goes through and + // there's still data available) and see if things work better. + + // ev.events = EPOLL_EVENTS.EPOLLET; // edge triggered if(events & FileEvents.read) ev.events |= EPOLL_EVENTS.EPOLLIN; diff --git a/jsvar.d b/jsvar.d index d715204..e919bca 100644 --- a/jsvar.d +++ b/jsvar.d @@ -636,8 +636,9 @@ struct var { this._type = Type.Array; var[] arr; arr.length = t.length; - foreach(i, item; t) - arr[i] = var(item); + static if(!is(T == void[])) // we can't append a void array but it is nice to support x = []; + foreach(i, item; t) + arr[i] = var(item); this._payload._array = arr; } else static if(is(T == bool)) { this._type = Type.Boolean; @@ -647,6 +648,10 @@ struct var { return this; } + public size_t opDollar() { + return this.length().get!size_t; + } + public var opOpAssign(string op, T)(T t) { if(payloadType() == Type.Object) { var* operator = this._payload._object._peekMember("opOpAssign", true); diff --git a/simpleaudio.d b/simpleaudio.d index 36605b9..6cba564 100644 --- a/simpleaudio.d +++ b/simpleaudio.d @@ -294,6 +294,7 @@ struct MidiOutput { } } + // FIXME: maybe add a PC speaker beep function for completeness /// Interfaces with the default sound card. You should only have a single instance of this and it should @@ -317,7 +318,7 @@ struct AudioMixer { snd_mixer_selem_id_t* sid; snd_mixer_elem_t* selem; - c_long maxVolume, minVolume; + c_long maxVolume, minVolume; // these are ok to use if you are writing ALSA specific code i guess enum selemName = "Master"; } @@ -353,16 +354,45 @@ struct AudioMixer { if(auto err = snd_mixer_selem_get_playback_volume_range(selem, &minVolume, &maxVolume)) throw new AlsaException("get volume range", err); + + version(with_eventloop) { + import arsd.eventloop; + addFileEventListeners(getAlsaFileDescriptors()[0], &eventListener, null, null); + setAlsaElemCallback(&alsaCallback); + } } else static assert(0); } ~this() { version(ALSA) { + version(with_eventloop) { + import arsd.eventloop; + removeFileEventListeners(getAlsaFileDescriptors()[0]); + } snd_mixer_selem_id_free(sid); snd_mixer_close(handle); } else static assert(0); } + version(ALSA) + version(with_eventloop) { + static struct MixerEvent {} + nothrow @nogc + extern(C) static int alsaCallback(snd_mixer_elem_t*, uint) { + import arsd.eventloop; + try + send(MixerEvent()); + catch(Exception) + return 1; + + return 0; + } + + void eventListener(int fd) { + handleAlsaEvents(); + } + } + /// Gets the master channel's mute state /// Note: this affects shared system state and you should not use it unless the end user wants you to. @property bool muteMaster() { @@ -384,12 +414,19 @@ struct AudioMixer { } /// returns a percentage, between 0 and 100 (inclusive) - /// Note: this affects shared system state and you should not use it unless the end user wants you to. int getMasterVolume() { + version(ALSA) { + auto volume = getMasterVolumeExact(); + return volume * 100 / (maxVolume - minVolume); + } else static assert(0); + } + + /// Gets the exact value returned from the operating system. The range may vary. + int getMasterVolumeExact() { version(ALSA) { c_long volume; snd_mixer_selem_get_playback_volume(selem, 0, &volume); - return volume * 100 / (maxVolume - minVolume); + return volume; } else static assert(0); } @@ -398,8 +435,15 @@ struct AudioMixer { void setMasterVolume(int volume) { version(ALSA) { assert(volume >= 0 && volume <= 100); - snd_mixer_selem_set_playback_volume_all(selem, - volume * (maxVolume - minVolume) / 100); + setMasterVolumeExact(volume * (maxVolume - minVolume) / 100); + } else static assert(0); + } + + /// Sets an exact volume. Must be in range of the OS provided min and max. + void setMasterVolumeExact(int volume) { + version(ALSA) { + if(auto err = snd_mixer_selem_set_playback_volume_all(selem, volume)) + throw new AlsaException("set volume", err); } else static assert(0); } diff --git a/terminal.d b/terminal.d index 9e4f668..ab441ec 100644 --- a/terminal.d +++ b/terminal.d @@ -2350,6 +2350,10 @@ void main() { FIXME: support lines that wrap FIXME: better controls maybe + FIXME: support multi-line "lines" and some form of line continuation, both + from the user (if permitted) and from the application, so like the user + hits "class foo { \n" and the app says "that line needs continuation" automatically. + FIXME: fix lengths on prompt and suggestion A note on history: @@ -2757,7 +2761,7 @@ class LineGetter { case InputEvent.Type.EndOfFileEvent: justHitTab = false; return false; - break; + //break; case InputEvent.Type.CharacterEvent: if(e.characterEvent.eventType == CharacterEvent.Type.Released) return true; @@ -2899,11 +2903,11 @@ class LineGetter { case InputEvent.Type.UserInterruptionEvent: /* I'll take this as canceling the line. */ throw new Exception("user canceled"); // FIXME - break; + //break; case InputEvent.Type.HangupEvent: /* I'll take this as canceling the line. */ throw new Exception("user hanged up"); // FIXME - break; + //break; default: /* ignore. ideally it wouldn't be passed to us anyway! */ }