Changeset View
Changeset View
Standalone View
Standalone View
src/modules/mixer/emixer.c
1 | #include <Elementary.h> | 1 | #include <Elementary.h> | ||
---|---|---|---|---|---|
2 | #include "emix.h" | 2 | #include "emix.h" | ||
3 | 3 | | |||
4 | Evas_Object *win; | 4 | Evas_Object *win; | ||
5 | Evas_Object *source_scroller, *sink_input_scroller, *sink_scroller; | 5 | Evas_Object *source_scroller, *sink_input_scroller, *sink_scroller, *card_scroller; | ||
6 | Evas_Object *source_box, *sink_input_box, *sink_box; | 6 | Evas_Object *source_box, *sink_input_box, *sink_box, *card_box; | ||
7 | 7 | | |||
8 | Eina_List *source_list = NULL, *sink_input_list = NULL, *sink_list = NULL; | 8 | Eina_List *source_list = NULL, *sink_input_list = NULL, *sink_list = NULL, *card_list = NULL; | ||
9 | 9 | | |||
10 | ////////////////////////////////////////////////////////////////////////////// | 10 | ////////////////////////////////////////////////////////////////////////////// | ||
11 | 11 | | |||
12 | static Eina_Bool | 12 | static Eina_Bool | ||
13 | _backend_init(const char *back) | 13 | _backend_init(const char *back) | ||
14 | { | 14 | { | ||
15 | const Eina_List *l; | 15 | const Eina_List *l; | ||
16 | const char *name; | 16 | const char *name; | ||
▲ Show 20 Lines • Show All 492 Lines • ▼ Show 20 Line(s) | 499 | { | |||
509 | elm_slider_value_set(sl, source->volume.volumes[0]); | 509 | elm_slider_value_set(sl, source->volume.volumes[0]); | ||
510 | 510 | | |||
511 | ck = evas_object_data_get(bxv, "mute"); | 511 | ck = evas_object_data_get(bxv, "mute"); | ||
512 | elm_check_state_set(ck, source->mute); | 512 | elm_check_state_set(ck, source->mute); | ||
513 | elm_object_disabled_set(sl, source->mute); | 513 | elm_object_disabled_set(sl, source->mute); | ||
514 | } | 514 | } | ||
515 | 515 | | |||
516 | ////////////////////////////////////////////////////////////////////////////// | 516 | ////////////////////////////////////////////////////////////////////////////// | ||
517 | static void | ||||
518 | _cb_card_profile_change(void *data, | ||||
519 | Evas_Object *obj, | ||||
520 | void *event_info EINA_UNUSED) | ||||
521 | { | ||||
522 | Emix_Profile *profile = data; | ||||
523 | Evas_Object *bxv = evas_object_data_get(obj, "parent"); | ||||
524 | Emix_Card *card = evas_object_data_get(bxv, "card"); | ||||
525 | elm_object_text_set(obj, profile->description); | ||||
526 | emix_card_profile_set(card, profile); | ||||
527 | } | ||||
528 | | ||||
529 | static void | ||||
530 | _emix_card_add(Emix_Card *card) | ||||
531 | { | ||||
532 | Evas_Object *bxv, *bx, *lb, *hv, *sep; | ||||
533 | Eina_List *l; | ||||
534 | Emix_Profile *profile; | ||||
535 | | ||||
536 | bxv = elm_box_add(win); | ||||
537 | card_list = eina_list_append(card_list, bxv); | ||||
538 | evas_object_data_set(bxv, "card", card); | ||||
539 | evas_object_size_hint_weight_set(bxv, EVAS_HINT_EXPAND, 0.0); | ||||
540 | evas_object_size_hint_align_set(bxv, EVAS_HINT_FILL, 0.0); | ||||
541 | | ||||
542 | bx = elm_box_add(win); | ||||
543 | elm_box_horizontal_set(bx, EINA_TRUE); | ||||
544 | evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); | ||||
545 | evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); | ||||
546 | elm_box_pack_end(bxv, bx); | ||||
547 | evas_object_show(bx); | ||||
548 | | ||||
549 | lb = elm_label_add(win); | ||||
550 | elm_object_text_set(lb, card->name); | ||||
551 | evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, 0.5); | ||||
552 | evas_object_size_hint_align_set(lb, 0.0, 0.5); | ||||
553 | elm_box_pack_end(bx, lb); | ||||
554 | evas_object_show(lb); | ||||
555 | | ||||
556 | hv = elm_hoversel_add(win); | ||||
557 | evas_object_data_set(hv, "parent", bxv); | ||||
558 | evas_object_data_set(bxv, "profile", hv); | ||||
559 | elm_hoversel_hover_parent_set(hv, win); | ||||
560 | EINA_LIST_FOREACH(card->profiles, l, profile) | ||||
561 | { | ||||
562 | if (!profile->plugged) continue; | ||||
563 | elm_hoversel_item_add(hv, profile->description, | ||||
564 | NULL, ELM_ICON_NONE, | ||||
565 | _cb_card_profile_change, profile); | ||||
566 | if (profile->active) elm_object_text_set(hv, profile->description); | ||||
567 | } | ||||
568 | evas_object_size_hint_weight_set(hv, 0.0, 0.5); | ||||
569 | evas_object_size_hint_align_set(hv, EVAS_HINT_FILL, 0.5); | ||||
570 | elm_box_pack_end(bx, hv); | ||||
571 | evas_object_show(hv); | ||||
572 | | ||||
573 | sep = elm_separator_add(win); | ||||
574 | elm_separator_horizontal_set(sep, EINA_TRUE); | ||||
575 | evas_object_size_hint_weight_set(sep, EVAS_HINT_EXPAND, 0.0); | ||||
576 | evas_object_size_hint_align_set(sep, EVAS_HINT_FILL, 0.0); | ||||
577 | elm_box_pack_end(bxv, sep); | ||||
578 | evas_object_show(sep); | ||||
579 | | ||||
580 | elm_box_pack_end(card_box, bxv); | ||||
581 | evas_object_show(bxv); | ||||
582 | } | ||||
583 | | ||||
584 | static void | ||||
585 | _emix_card_change(Emix_Card *card) | ||||
586 | { | ||||
587 | const Eina_List *l; | ||||
588 | Evas_Object *bxv, *hv; | ||||
589 | Emix_Profile *profile; | ||||
590 | | ||||
591 | EINA_LIST_FOREACH(card_list, l, bxv) | ||||
592 | { | ||||
593 | if (evas_object_data_get(bxv, "card") == card) break; | ||||
594 | } | ||||
595 | if (!l) return; | ||||
596 | hv = evas_object_data_get(bxv, "profile"); | ||||
597 | elm_hoversel_clear(hv); | ||||
598 | EINA_LIST_FOREACH(card->profiles, l, profile) | ||||
599 | { | ||||
600 | if (!profile->plugged) continue; | ||||
601 | elm_hoversel_item_add(hv, profile->description, | ||||
602 | NULL, ELM_ICON_NONE, | ||||
603 | _cb_card_profile_change, profile); | ||||
604 | if (profile->active) elm_object_text_set(hv, profile->description); | ||||
605 | } | ||||
606 | } | ||||
607 | | ||||
608 | | ||||
609 | static void | ||||
610 | _emix_card_del(Emix_Card *card) | ||||
611 | { | ||||
612 | Eina_List *l; | ||||
613 | Evas_Object *bxv; | ||||
614 | EINA_LIST_FOREACH(card_list, l, bxv) | ||||
615 | { | ||||
616 | if (evas_object_data_get(bxv, "card") == card) | ||||
617 | { | ||||
618 | card_list = eina_list_remove_list(card_list, l); | ||||
619 | evas_object_del(bxv); | ||||
620 | return; | ||||
621 | } | ||||
622 | } | ||||
623 | } | ||||
624 | | ||||
625 | | ||||
626 | ////////////////////////////////////////////////////////////////////////////// | ||||
627 | | ||||
517 | 628 | | |||
518 | static void | 629 | static void | ||
519 | _cb_emix_event(void *data EINA_UNUSED, enum Emix_Event event, void *event_info) | 630 | _cb_emix_event(void *data EINA_UNUSED, enum Emix_Event event, void *event_info) | ||
520 | { | 631 | { | ||
521 | switch (event) | 632 | switch (event) | ||
522 | { | 633 | { | ||
523 | case EMIX_READY_EVENT: | 634 | case EMIX_READY_EVENT: | ||
524 | break; | 635 | break; | ||
Show All 22 Lines | 657 | case EMIX_SOURCE_ADDED_EVENT: | |||
547 | _emix_source_add(event_info); | 658 | _emix_source_add(event_info); | ||
548 | break; | 659 | break; | ||
549 | case EMIX_SOURCE_REMOVED_EVENT: | 660 | case EMIX_SOURCE_REMOVED_EVENT: | ||
550 | _emix_source_del(event_info); | 661 | _emix_source_del(event_info); | ||
551 | break; | 662 | break; | ||
552 | case EMIX_SOURCE_CHANGED_EVENT: | 663 | case EMIX_SOURCE_CHANGED_EVENT: | ||
553 | _emix_source_change(event_info); | 664 | _emix_source_change(event_info); | ||
554 | break; | 665 | break; | ||
666 | case EMIX_CARD_ADDED_EVENT: | ||||
667 | _emix_card_add(event_info); | ||||
668 | break; | ||||
669 | case EMIX_CARD_REMOVED_EVENT: | ||||
670 | _emix_card_del(event_info); | ||||
671 | break; | ||||
672 | case EMIX_CARD_CHANGED_EVENT: | ||||
673 | _emix_card_change(event_info); | ||||
674 | break; | ||||
555 | default: | 675 | default: | ||
556 | break; | 676 | break; | ||
557 | } | 677 | } | ||
558 | } | 678 | } | ||
559 | 679 | | |||
560 | ////////////////////////////////////////////////////////////////////////////// | 680 | ////////////////////////////////////////////////////////////////////////////// | ||
561 | 681 | | |||
562 | static void | 682 | static void | ||
563 | _cb_playback(void *data EINA_UNUSED, | 683 | _cb_playback(void *data EINA_UNUSED, | ||
564 | Evas_Object *obj EINA_UNUSED, | 684 | Evas_Object *obj EINA_UNUSED, | ||
565 | void *event_info EINA_UNUSED) | 685 | void *event_info EINA_UNUSED) | ||
566 | { | 686 | { | ||
567 | evas_object_hide(source_scroller); | 687 | evas_object_hide(source_scroller); | ||
568 | evas_object_show(sink_input_scroller); | 688 | evas_object_show(sink_input_scroller); | ||
569 | evas_object_hide(sink_scroller); | 689 | evas_object_hide(sink_scroller); | ||
690 | evas_object_hide(card_scroller); | ||||
570 | } | 691 | } | ||
571 | 692 | | |||
572 | static void | 693 | static void | ||
573 | _cb_outputs(void *data EINA_UNUSED, | 694 | _cb_outputs(void *data EINA_UNUSED, | ||
574 | Evas_Object *obj EINA_UNUSED, | 695 | Evas_Object *obj EINA_UNUSED, | ||
575 | void *event_info EINA_UNUSED) | 696 | void *event_info EINA_UNUSED) | ||
576 | { | 697 | { | ||
577 | evas_object_hide(source_scroller); | 698 | evas_object_hide(source_scroller); | ||
578 | evas_object_hide(sink_input_scroller); | 699 | evas_object_hide(sink_input_scroller); | ||
579 | evas_object_show(sink_scroller); | 700 | evas_object_show(sink_scroller); | ||
701 | evas_object_hide(card_scroller); | ||||
580 | } | 702 | } | ||
581 | 703 | | |||
582 | static void | 704 | static void | ||
583 | _cb_inputs(void *data EINA_UNUSED, | 705 | _cb_inputs(void *data EINA_UNUSED, | ||
584 | Evas_Object *obj EINA_UNUSED, | 706 | Evas_Object *obj EINA_UNUSED, | ||
585 | void *event_info EINA_UNUSED) | 707 | void *event_info EINA_UNUSED) | ||
586 | { | 708 | { | ||
587 | evas_object_show(source_scroller); | 709 | evas_object_show(source_scroller); | ||
588 | evas_object_hide(sink_input_scroller); | 710 | evas_object_hide(sink_input_scroller); | ||
589 | evas_object_hide(sink_scroller); | 711 | evas_object_hide(sink_scroller); | ||
712 | evas_object_hide(card_scroller); | ||||
590 | } | 713 | } | ||
591 | 714 | | |||
715 | static void | ||||
716 | _cb_card(void *data EINA_UNUSED, | ||||
717 | Evas_Object *obj EINA_UNUSED, | ||||
718 | void *event_info EINA_UNUSED) | ||||
719 | { | ||||
720 | evas_object_hide(source_scroller); | ||||
721 | evas_object_hide(sink_input_scroller); | ||||
722 | evas_object_hide(sink_scroller); | ||||
723 | evas_object_show(card_scroller); | ||||
724 | } | ||||
725 | | ||||
726 | | ||||
592 | ////////////////////////////////////////////////////////////////////////////// | 727 | ////////////////////////////////////////////////////////////////////////////// | ||
593 | 728 | | |||
594 | static void | 729 | static void | ||
595 | _event_init(void) | 730 | _event_init(void) | ||
596 | { | 731 | { | ||
597 | emix_event_callback_add(_cb_emix_event, NULL); | 732 | emix_event_callback_add(_cb_emix_event, NULL); | ||
598 | } | 733 | } | ||
599 | 734 | | |||
Show All 28 Lines | 761 | { | |||
628 | Emix_Sink *sink; | 763 | Emix_Sink *sink; | ||
629 | 764 | | |||
630 | EINA_LIST_FOREACH(emix_sinks_get(), l, sink) | 765 | EINA_LIST_FOREACH(emix_sinks_get(), l, sink) | ||
631 | { | 766 | { | ||
632 | _emix_sink_add(sink); | 767 | _emix_sink_add(sink); | ||
633 | } | 768 | } | ||
634 | } | 769 | } | ||
635 | 770 | | |||
771 | static void | ||||
772 | _fill_card(void) | ||||
773 | { | ||||
774 | const Eina_List *l; | ||||
775 | Emix_Card *card; | ||||
776 | | ||||
777 | EINA_LIST_FOREACH(emix_cards_get(), l, card) | ||||
778 | { | ||||
779 | _emix_card_add(card); | ||||
780 | } | ||||
781 | } | ||||
782 | | ||||
636 | ////////////////////////////////////////////////////////////////////////////// | 783 | ////////////////////////////////////////////////////////////////////////////// | ||
637 | 784 | | |||
638 | EAPI_MAIN int | 785 | EAPI_MAIN int | ||
639 | elm_main(int argc, char **argv) | 786 | elm_main(int argc, char **argv) | ||
640 | { | 787 | { | ||
641 | Evas_Object *tb, *tbar, *sc, *rect, *bx; | 788 | Evas_Object *tb, *tbar, *sc, *rect, *bx; | ||
642 | const char *back = NULL; | 789 | const char *back = NULL; | ||
643 | 790 | | |||
Show All 25 Lines | 808 | */ | |||
669 | elm_toolbar_select_mode_set(tbar, ELM_OBJECT_SELECT_MODE_ALWAYS); | 816 | elm_toolbar_select_mode_set(tbar, ELM_OBJECT_SELECT_MODE_ALWAYS); | ||
670 | elm_toolbar_homogeneous_set(tbar, EINA_TRUE); | 817 | elm_toolbar_homogeneous_set(tbar, EINA_TRUE); | ||
671 | evas_object_size_hint_weight_set(tbar, EVAS_HINT_EXPAND, 0.0); | 818 | evas_object_size_hint_weight_set(tbar, EVAS_HINT_EXPAND, 0.0); | ||
672 | evas_object_size_hint_align_set(tbar, EVAS_HINT_FILL, EVAS_HINT_FILL); | 819 | evas_object_size_hint_align_set(tbar, EVAS_HINT_FILL, EVAS_HINT_FILL); | ||
673 | 820 | | |||
674 | elm_toolbar_item_append(tbar, NULL, "Playback", _cb_playback, NULL); | 821 | elm_toolbar_item_append(tbar, NULL, "Playback", _cb_playback, NULL); | ||
675 | elm_toolbar_item_append(tbar, NULL, "Outputs", _cb_outputs, NULL); | 822 | elm_toolbar_item_append(tbar, NULL, "Outputs", _cb_outputs, NULL); | ||
676 | elm_toolbar_item_append(tbar, NULL, "Inputs", _cb_inputs, NULL); | 823 | elm_toolbar_item_append(tbar, NULL, "Inputs", _cb_inputs, NULL); | ||
824 | elm_toolbar_item_append(tbar, NULL, "Cards", _cb_card, NULL); | ||||
677 | 825 | | |||
678 | elm_table_pack(tb, tbar, 0, 0, 1, 1); | 826 | elm_table_pack(tb, tbar, 0, 0, 1, 1); | ||
679 | evas_object_show(tbar); | 827 | evas_object_show(tbar); | ||
680 | 828 | | |||
681 | sc = elm_scroller_add(win); | 829 | sc = elm_scroller_add(win); | ||
682 | source_scroller = sc; | 830 | source_scroller = sc; | ||
683 | evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); | 831 | evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); | ||
684 | evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL); | 832 | evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL); | ||
685 | elm_table_pack(tb, sc, 0, 1, 1, 1); | 833 | elm_table_pack(tb, sc, 0, 1, 1, 1); | ||
686 | 834 | | |||
687 | sc = elm_scroller_add(win); | 835 | sc = elm_scroller_add(win); | ||
688 | sink_input_scroller = sc; | 836 | sink_input_scroller = sc; | ||
689 | evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); | 837 | evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); | ||
690 | evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL); | 838 | evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL); | ||
691 | elm_table_pack(tb, sc, 0, 1, 1, 1); | 839 | elm_table_pack(tb, sc, 0, 1, 1, 1); | ||
692 | evas_object_show(sc); | 840 | evas_object_show(sc); | ||
693 | 841 | | |||
694 | sc = elm_scroller_add(win); | 842 | sc = elm_scroller_add(win); | ||
695 | sink_scroller = sc; | 843 | sink_scroller = sc; | ||
696 | evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); | 844 | evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); | ||
697 | evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL); | 845 | evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL); | ||
698 | elm_table_pack(tb, sc, 0, 1, 1, 1); | 846 | elm_table_pack(tb, sc, 0, 1, 1, 1); | ||
699 | 847 | | |||
848 | sc = elm_scroller_add(win); | ||||
849 | card_scroller = sc; | ||||
850 | evas_object_size_hint_weight_set(sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); | ||||
851 | evas_object_size_hint_align_set(sc, EVAS_HINT_FILL, EVAS_HINT_FILL); | ||||
852 | elm_table_pack(tb, sc, 0, 1, 1, 1); | ||||
853 | | ||||
700 | bx = elm_box_add(win); | 854 | bx = elm_box_add(win); | ||
701 | source_box = bx; | 855 | source_box = bx; | ||
702 | evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); | 856 | evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); | ||
703 | evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); | 857 | evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); | ||
704 | elm_object_content_set(source_scroller, bx); | 858 | elm_object_content_set(source_scroller, bx); | ||
705 | evas_object_show(bx); | 859 | evas_object_show(bx); | ||
706 | 860 | | |||
707 | bx = elm_box_add(win); | 861 | bx = elm_box_add(win); | ||
708 | sink_input_box = bx; | 862 | sink_input_box = bx; | ||
709 | evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); | 863 | evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); | ||
710 | evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); | 864 | evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); | ||
711 | elm_object_content_set(sink_input_scroller, bx); | 865 | elm_object_content_set(sink_input_scroller, bx); | ||
712 | evas_object_show(bx); | 866 | evas_object_show(bx); | ||
713 | 867 | | |||
714 | bx = elm_box_add(win); | 868 | bx = elm_box_add(win); | ||
715 | sink_box = bx; | 869 | sink_box = bx; | ||
716 | evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); | 870 | evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); | ||
717 | evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); | 871 | evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); | ||
718 | elm_object_content_set(sink_scroller, bx); | 872 | elm_object_content_set(sink_scroller, bx); | ||
719 | evas_object_show(bx); | 873 | evas_object_show(bx); | ||
720 | 874 | | |||
875 | bx = elm_box_add(win); | ||||
876 | card_box = bx; | ||||
877 | evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, 0.0); | ||||
878 | evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, 0.0); | ||||
879 | elm_object_content_set(card_scroller, bx); | ||||
880 | evas_object_show(bx); | ||||
881 | | ||||
721 | rect = evas_object_rectangle_add(evas_object_evas_get(win)); | 882 | rect = evas_object_rectangle_add(evas_object_evas_get(win)); | ||
722 | evas_object_size_hint_weight_set(rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); | 883 | evas_object_size_hint_weight_set(rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); | ||
723 | evas_object_size_hint_align_set(rect, EVAS_HINT_FILL, EVAS_HINT_FILL); | 884 | evas_object_size_hint_align_set(rect, EVAS_HINT_FILL, EVAS_HINT_FILL); | ||
724 | evas_object_size_hint_min_set(rect, | 885 | evas_object_size_hint_min_set(rect, | ||
725 | 440 * elm_config_scale_get(), | 886 | 440 * elm_config_scale_get(), | ||
726 | 220 * elm_config_scale_get()); | 887 | 220 * elm_config_scale_get()); | ||
727 | elm_table_pack(tb, rect, 0, 1, 1, 1); | 888 | elm_table_pack(tb, rect, 0, 1, 1, 1); | ||
728 | 889 | | |||
729 | _fill_source(); | 890 | _fill_source(); | ||
730 | _fill_sink_input(); | 891 | _fill_sink_input(); | ||
731 | _fill_sink(); | 892 | _fill_sink(); | ||
893 | _fill_card(); | ||||
732 | evas_object_show(win); | 894 | evas_object_show(win); | ||
733 | 895 | | |||
734 | elm_run(); | 896 | elm_run(); | ||
735 | done: | 897 | done: | ||
736 | emix_shutdown(); | 898 | emix_shutdown(); | ||
737 | return 0; | 899 | return 0; | ||
738 | } | 900 | } | ||
739 | ELM_MAIN() | 901 | ELM_MAIN() |