This commit is contained in:
Adam D. Ruppe 2014-12-22 13:54:23 -05:00
parent 6c3507ca3b
commit 92ad388884
4 changed files with 70 additions and 11 deletions

View File

@ -438,7 +438,13 @@ version(linux) {
private void addFileToLoopImplementation(int fd, int events) { private void addFileToLoopImplementation(int fd, int events) {
epoll_event ev; 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) if(events & FileEvents.read)
ev.events |= EPOLL_EVENTS.EPOLLIN; ev.events |= EPOLL_EVENTS.EPOLLIN;

View File

@ -636,8 +636,9 @@ struct var {
this._type = Type.Array; this._type = Type.Array;
var[] arr; var[] arr;
arr.length = t.length; arr.length = t.length;
foreach(i, item; t) static if(!is(T == void[])) // we can't append a void array but it is nice to support x = [];
arr[i] = var(item); foreach(i, item; t)
arr[i] = var(item);
this._payload._array = arr; this._payload._array = arr;
} else static if(is(T == bool)) { } else static if(is(T == bool)) {
this._type = Type.Boolean; this._type = Type.Boolean;
@ -647,6 +648,10 @@ struct var {
return this; return this;
} }
public size_t opDollar() {
return this.length().get!size_t;
}
public var opOpAssign(string op, T)(T t) { public var opOpAssign(string op, T)(T t) {
if(payloadType() == Type.Object) { if(payloadType() == Type.Object) {
var* operator = this._payload._object._peekMember("opOpAssign", true); var* operator = this._payload._object._peekMember("opOpAssign", true);

View File

@ -294,6 +294,7 @@ struct MidiOutput {
} }
} }
// FIXME: maybe add a PC speaker beep function for completeness // 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 /// 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_selem_id_t* sid;
snd_mixer_elem_t* selem; 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"; enum selemName = "Master";
} }
@ -353,16 +354,45 @@ struct AudioMixer {
if(auto err = snd_mixer_selem_get_playback_volume_range(selem, &minVolume, &maxVolume)) if(auto err = snd_mixer_selem_get_playback_volume_range(selem, &minVolume, &maxVolume))
throw new AlsaException("get volume range", err); 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); } else static assert(0);
} }
~this() { ~this() {
version(ALSA) { version(ALSA) {
version(with_eventloop) {
import arsd.eventloop;
removeFileEventListeners(getAlsaFileDescriptors()[0]);
}
snd_mixer_selem_id_free(sid); snd_mixer_selem_id_free(sid);
snd_mixer_close(handle); snd_mixer_close(handle);
} else static assert(0); } 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 /// 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. /// Note: this affects shared system state and you should not use it unless the end user wants you to.
@property bool muteMaster() { @property bool muteMaster() {
@ -384,12 +414,19 @@ struct AudioMixer {
} }
/// returns a percentage, between 0 and 100 (inclusive) /// 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() { 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) { version(ALSA) {
c_long volume; c_long volume;
snd_mixer_selem_get_playback_volume(selem, 0, &volume); snd_mixer_selem_get_playback_volume(selem, 0, &volume);
return volume * 100 / (maxVolume - minVolume); return volume;
} else static assert(0); } else static assert(0);
} }
@ -398,8 +435,15 @@ struct AudioMixer {
void setMasterVolume(int volume) { void setMasterVolume(int volume) {
version(ALSA) { version(ALSA) {
assert(volume >= 0 && volume <= 100); assert(volume >= 0 && volume <= 100);
snd_mixer_selem_set_playback_volume_all(selem, setMasterVolumeExact(volume * (maxVolume - minVolume) / 100);
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); } else static assert(0);
} }

View File

@ -2350,6 +2350,10 @@ void main() {
FIXME: support lines that wrap FIXME: support lines that wrap
FIXME: better controls maybe 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 FIXME: fix lengths on prompt and suggestion
A note on history: A note on history:
@ -2757,7 +2761,7 @@ class LineGetter {
case InputEvent.Type.EndOfFileEvent: case InputEvent.Type.EndOfFileEvent:
justHitTab = false; justHitTab = false;
return false; return false;
break; //break;
case InputEvent.Type.CharacterEvent: case InputEvent.Type.CharacterEvent:
if(e.characterEvent.eventType == CharacterEvent.Type.Released) if(e.characterEvent.eventType == CharacterEvent.Type.Released)
return true; return true;
@ -2899,11 +2903,11 @@ class LineGetter {
case InputEvent.Type.UserInterruptionEvent: case InputEvent.Type.UserInterruptionEvent:
/* I'll take this as canceling the line. */ /* I'll take this as canceling the line. */
throw new Exception("user canceled"); // FIXME throw new Exception("user canceled"); // FIXME
break; //break;
case InputEvent.Type.HangupEvent: case InputEvent.Type.HangupEvent:
/* I'll take this as canceling the line. */ /* I'll take this as canceling the line. */
throw new Exception("user hanged up"); // FIXME throw new Exception("user hanged up"); // FIXME
break; //break;
default: default:
/* ignore. ideally it wouldn't be passed to us anyway! */ /* ignore. ideally it wouldn't be passed to us anyway! */
} }